Merge branch 'dev/11/fp3/security-aosp-rvc-release' into int/11/fp3

* dev/11/fp3/security-aosp-rvc-release:
  DO NOT MERGE: Update password check for WAPI

Change-Id: I7db4288c26db54d7ac376826f2bda6503e34d606
diff --git a/libs/WifiTrackerLib/Android.bp b/libs/WifiTrackerLib/Android.bp
index 5355d00..7a61f30 100644
--- a/libs/WifiTrackerLib/Android.bp
+++ b/libs/WifiTrackerLib/Android.bp
@@ -5,6 +5,9 @@
         "androidx.preference_preference",
         "SettingsLibHelpUtils",
     ],
+    defaults: [
+        "framework-wifi-vendor-hide-access-defaults",
+    ],
 
     min_sdk_version: "21",
 }
diff --git a/libs/WifiTrackerLib/res/values-af/strings.xml b/libs/WifiTrackerLib/res/values-af/strings.xml
index 1289205..1246b10 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Voltooi tans aanmelding …"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kon nie aanmelding voltooi nie. Tik om weer te probeer."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Aanmelding is voltooi. Koppel tans …"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Hierdie netwerk ontvang \'n unieke ID wat gebruik kan word om toestelligging na te spoor. "<annotation id="url">"Kom meer te wete"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Hierdie netwerk ontvang \'n SIM-ID wat gebruik kan word om toestelligging na te spoor. "<annotation id="url">"Kom meer te wete"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Baie stadig"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Stadig"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-am/strings.xml b/libs/WifiTrackerLib/res/values-am/strings.xml
index cf57ddc..78c66a2 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"መመዝገብን በማጠናቀቅ ላይ…"</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">"ይህ አውታረ መረብ የመሣሪያ አካባቢን ለመከታተል ስራ ላይ ሊውል የሚችል ልዩ መታወቂያ ተቀብሏል። "<annotation id="url">"የበለጠ ለመረዳት"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"ይህ አውታረ መረብ የመሣሪያ አካባቢን ለመከታተል ሥራ ላይ ሊውል የሚችል የሲም መታወቂያ ይቀበላል። "<annotation id="url">"የበለጠ ለመረዳት"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"በጣም ቀርፋፋ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"አዘግይ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"እሺ"</string>
diff --git a/libs/WifiTrackerLib/res/values-ar/strings.xml b/libs/WifiTrackerLib/res/values-ar/strings.xml
index ef0f107..40ac149 100644
--- a/libs/WifiTrackerLib/res/values-ar/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ar/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">"لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص"</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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"جارٍ إكمال الاشتراك…"</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">"تتلقّى هذه الشبكة معرّفًا فريدًا يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز. "<annotation id="url">"مزيد من المعلومات"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"‏تتلقّى هذه الشبكة رقم تعريف لشريحة SIM يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز. "<annotation id="url">"مزيد من المعلومات"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"بطيئة جدًا"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"بطيئة"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"حسنًا"</string>
diff --git a/libs/WifiTrackerLib/res/values-as/strings.xml b/libs/WifiTrackerLib/res/values-as/strings.xml
index a211b32..a9a17b3 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ছাইন আপ সম্পূৰ্ণ কৰি থকা হৈছে…"</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">"এই নেটৱৰ্কটোৱে এটা সুকীয়া আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি। "<annotation id="url">"অধিক জানক"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"এই নেটৱৰ্কটোৱে এটা ছিম আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি। "<annotation id="url">"অধিক জানক"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"অতি লেহেম"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"লেহেমীয়া"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ঠিক"</string>
diff --git a/libs/WifiTrackerLib/res/values-az/strings.xml b/libs/WifiTrackerLib/res/values-az/strings.xml
index 5bc7a70..8752985 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Qeydiyyat tamamlanır…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Qeydiyyat tamamlanmadı. Yenidən cəhd etmək üçün toxunun."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Qeydiyyat tamamlandı. Qoşulur…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Bu şəbəkə cihaz məkanını izləmək üçün istifadə edilə biləcək unikal ID qəbul edir. "<annotation id="url">"Ətraflı məlumat"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu şəbəkə cihaz məkanını izləmək üçün istifadə edilə biləcək SIM ID qəbul edir. "<annotation id="url">"Ətraflı məlumat"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Çox Yavaş"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Yavaş"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</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..4a36f1b 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registracija se dovršava…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Dovršavanje registracije nije uspelo. Dodirnite da biste probali ponovo."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je dovršena. Povezuje se…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ova mreža zahteva jedinstveni ID koji može da se koristi za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža dobija ID SIM kartice koji može da se koristi za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Veoma spora"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Spora"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Potvrdi"</string>
diff --git a/libs/WifiTrackerLib/res/values-be/strings.xml b/libs/WifiTrackerLib/res/values-be/strings.xml
index de04599..e8f0f7c 100644
--- a/libs/WifiTrackerLib/res/values-be/strings.xml
+++ b/libs/WifiTrackerLib/res/values-be/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Пункт доступу часова заняты"</string>
     <string name="wifi_disconnected" msgid="3720926757662831062">"Адключана"</string>
     <string name="wifi_remembered" msgid="5126903736498678708">"Захавана"</string>
-    <string name="wifi_metered_label" msgid="1362621600006544014">"Сетка з улікам трафіка"</string>
+    <string name="wifi_metered_label" msgid="1362621600006544014">"Сетка з падлікам трафіка"</string>
     <string name="wifi_unmetered_label" msgid="499466875639448350">"Сетка без уліку трафіка"</string>
     <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>
@@ -36,7 +36,8 @@
     <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_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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Рэгістрацыя завяршаецца…"</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">"Гэта сетка атрымлівае ўнікальны ідэнтыфікатар, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады. "<annotation id="url">"Даведацца больш"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Гэта сетка атрымлівае ідэнтыфікатар SIM-карты, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады. "<annotation id="url">"Даведацца больш"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Вельмі павольная"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Павольная"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string>
diff --git a/libs/WifiTrackerLib/res/values-bg/strings.xml b/libs/WifiTrackerLib/res/values-bg/strings.xml
index f17e36a..83230d8 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Регистрацията се завършва…"</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">"Тази мрежа получава уникален идентификатор, който може да се използва за проследяване на местоположението на устройството. "<annotation id="url">"Научете повече"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Тази мрежа получава идентификатор за SIM карта, който може да се използва за проследяване на местоположението на устройството. "<annotation id="url">"Научете повече"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Много бавна"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Бавна"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ОK"</string>
diff --git a/libs/WifiTrackerLib/res/values-bn/strings.xml b/libs/WifiTrackerLib/res/values-bn/strings.xml
index 8b3bdc2..0528cb7 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"সাইন-আপ করা হচ্ছে…"</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">"এই নেটওয়ার্কে একটি অনন্য আইডি পাবেন যার সাহায্যে এই নেটওয়ার্কের সাথে যুক্ত থাকা ডিভাইসের লোকেশন ট্র্যাক করা যাবে। "<annotation id="url">"আরও জানুন"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"এই নেটওয়ার্কের কাছে একটি সিম আইডি থাকে যা ব্যবহার করে ডিভাইসের লোকেশন ট্র্যাক করা যাবে। "<annotation id="url">"আরও জানুন"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"খুব ধীরে"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ধীরে"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ঠিক আছে"</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..148c020 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Završavanje registracije…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registraciju nije moguće izvršiti. Dodirnite da pokušate ponovo."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je završena. Povezivanje…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ova mreža prima jedinstveni ID koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža prima ID SIM-a koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Veoma sporo"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Sporo"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Uredu"</string>
diff --git a/libs/WifiTrackerLib/res/values-ca/strings.xml b/libs/WifiTrackerLib/res/values-ca/strings.xml
index 4711bd4..a07ee2e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"S\'està completant el registre…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"No s\'ha pogut completar el registre. Toca per tornar-ho a provar."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"S\'ha completat el registre. S\'està connectant…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Aquesta xarxa rep un identificador únic que es pot utilitzar per fer el seguiment de la ubicació del dispositiu. "<annotation id="url">"Més informació"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Aquesta xarxa rep un identificador de SIM que es pot utilitzar per fer el seguiment de la ubicació del dispositiu. "<annotation id="url">"Més informació"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Molt lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Correcta"</string>
diff --git a/libs/WifiTrackerLib/res/values-cs/strings.xml b/libs/WifiTrackerLib/res/values-cs/strings.xml
index 69d90f5..6562a28 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončování registrace…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registraci se nepodařilo dokončit. Klepnutím opakujte akci."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrace byla dokončena. Připojování…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Tato síť dostane jedinečný identifikátor, pomocí kterého lze sledovat polohu zařízení. "<annotation id="url">"Další informace"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Tato síť dostane identifikátor SIM karty, pomocí kterého lze sledovat polohu zařízení. "<annotation id="url">"Další informace"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Velmi pomalá"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Pomalá"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-da/strings.xml b/libs/WifiTrackerLib/res/values-da/strings.xml
index ff21ffb..d8a2cb9 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Fuldfører registrering…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registreringen kunne ikke fuldføres. Tryk for at prøve igen."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreringen er fuldført. Opretter forbindelse…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Dette netværk kræver et unikt id, der kan bruges til at spore enhedens placering. "<annotation id="url">"Få flere oplysninger"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Dette netværk kræver et SIM-id, der kan bruges til at spore enhedens placering. "<annotation id="url">"Få flere oplysninger"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Meget langsom"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Langsom"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-de/strings.xml b/libs/WifiTrackerLib/res/values-de/strings.xml
index 9007073..c6a554e 100644
--- a/libs/WifiTrackerLib/res/values-de/strings.xml
+++ b/libs/WifiTrackerLib/res/values-de/strings.xml
@@ -29,7 +29,7 @@
     <string name="wifi_disconnected" msgid="3720926757662831062">"Nicht verbunden"</string>
     <string name="wifi_remembered" msgid="5126903736498678708">"Gespeichert"</string>
     <string name="wifi_metered_label" msgid="1362621600006544014">"Kostenpflichtig"</string>
-    <string name="wifi_unmetered_label" msgid="499466875639448350">"Kostenlos"</string>
+    <string name="wifi_unmetered_label" msgid="499466875639448350">"Ohne Datenlimit"</string>
     <string name="connected_via_app" msgid="1818040967936972127">"Verbunden über <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="available_via_app" msgid="9110324040292242769">"Über <xliff:g id="NAME">%1$s</xliff:g> verfügbar"</string>
     <string name="connected_via_network_scorer" msgid="209764314005159012">"Automatisch verbunden über <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registrierung wird abgeschlossen…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registrierung konnte nicht abgeschlossen werden. Tippe, um es noch einmal zu versuchen."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrierung abgeschlossen. Verbindung wird hergestellt…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Dieses Netzwerk empfängt eine eindeutige ID, mit der der Gerätestandort erfasst werden kann. "<annotation id="url">"Weitere Informationen"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Dieses Netzwerk empfängt eine SIM-ID, mit der der Gerätestandort erfasst werden kann. "<annotation id="url">"Weitere Informationen."</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Sehr langsam"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Langsam"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string>
diff --git a/libs/WifiTrackerLib/res/values-el/strings.xml b/libs/WifiTrackerLib/res/values-el/strings.xml
index 31c065d..4ae7d74 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Ολοκλήρωση εγγραφής…"</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">"Αυτό το δίκτυο λαμβάνει ένα μοναδικό αναγνωριστικό το οποίο μπορεί να χρησιμοποιηθεί για τον εντοπισμό της τοποθεσίας της συσκευής. "<annotation id="url">"Μάθετε περισσότερα"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Αυτό το δίκτυο λαμβάνει ένα αναγνωριστικό SIM το οποίο μπορεί να χρησιμοποιηθεί για τον εντοπισμό της τοποθεσίας της συσκευής. "<annotation id="url">"Μάθετε περισσότερα"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Πολύ αργή"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Αργή"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ΟΚ"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
index 2f8fc15..70d1a9c 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>
@@ -46,7 +47,7 @@
     <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>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string>
     <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-en-rCA/strings.xml b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
index 2f8fc15..70d1a9c 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>
@@ -46,7 +47,7 @@
     <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>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string>
     <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-en-rGB/strings.xml b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
index 2f8fc15..70d1a9c 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>
@@ -46,7 +47,7 @@
     <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>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string>
     <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-en-rIN/strings.xml b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
index 2f8fc15..70d1a9c 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>
@@ -46,7 +47,7 @@
     <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>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"This network receives a SIM ID that can be used to track device location. "<annotation id="url">"Learn more"</annotation></string>
     <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-en-rXC/strings.xml b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
index 087ad38..2a7fadc 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,7 @@
     <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>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎This network receives a SIM ID that can be used to track device location. ‎‏‎‎‏‏‎"<annotation id="url">"‎‏‎‎‏‏‏‎Learn more‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <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..65a7697 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando registro…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"No se pudo completar el registro. Presiona para volver a intentarlo."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Se completó el registro. Conectando…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta red recibe un ID único que se puede usar para realizar el seguimiento de la ubicación del dispositivo. "<annotation id="url">"Más información"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta red recibe un ID de SIM que se puede usar para realizar el seguimiento de la ubicación del dispositivo. "<annotation id="url">"Más información"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Muy lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Aceptar"</string>
diff --git a/libs/WifiTrackerLib/res/values-es/strings.xml b/libs/WifiTrackerLib/res/values-es/strings.xml
index 6c6990e..a9435e3 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando registro…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"No se ha podido completar el registro. Toca para volver a intentarlo."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Se ha completado el registro. Conectando…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta red recibe un ID único con el que se puede rastrear la ubicación del dispositivo "<annotation id="url">"Más información"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta red recibe un ID de SIM con el que se puede rastrear la ubicación del dispositivo. "<annotation id="url">"Más información"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Muy lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Aceptable"</string>
diff --git a/libs/WifiTrackerLib/res/values-et/strings.xml b/libs/WifiTrackerLib/res/values-et/strings.xml
index 6843d21..aa91929 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registreerimise lõpuleviimine …"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registreerimist ei saanud lõpule viia. Puudutage, et uuesti proovida."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreerimine on lõpule viidud. Ühendamine …"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"See võrk saab kordumatu ID, mida saab kasutada seadme asukoha jälgimiseks. "<annotation id="url">"Lisateave"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"See võrk saab SIM-i ID, mida saab kasutada seadme asukoha jälgimiseks. "<annotation id="url">"Lisateave"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Väga aeglane"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Aeglane"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Hea"</string>
diff --git a/libs/WifiTrackerLib/res/values-eu/strings.xml b/libs/WifiTrackerLib/res/values-eu/strings.xml
index a440007..da6fa13 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Izena ematen…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ezin izan da eman izena. Berriro saiatzeko, ukitu hau."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Eman da izena. Konektatzen…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Gailuaren kokapenaren jarraipena egiteko balio duen ID esklusibo bat jasotzen du sare honek. "<annotation id="url">"Lortu informazio gehiago"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Gailuaren kokapenaren jarraipena egiteko balio duen SIM ID esklusibo bat jasotzen du sare honek. "<annotation id="url">"Lortu informazio gehiago"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Oso motela"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Motela"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Ados"</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..ec535eb 100644
--- a/libs/WifiTrackerLib/res/values-fa/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fa/strings.xml
@@ -20,8 +20,8 @@
     <string name="auto_connect_disable" msgid="1078319396240632542">"اتصال خودکار خاموش است"</string>
     <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_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_generic" msgid="8307050327779256414">"غیرفعال شد"</string>
@@ -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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"درحال تکمیل ثبت‌نام…"</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">"این شبکه شناسه یکتایی را دریافت می‌کند که می‌توان از آن برای ردیابی مکان دستگاه استفاده کرد. "<annotation id="url">"بیشتر بدانید"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"این شبکه شناسه سیم‌کارتی را دریافت می‌کند که می‌توان از آن برای ردیابی مکان دستگاه استفاده کرد. "<annotation id="url">"بیشتر بدانید"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"بسیار آهسته"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"آهسته"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"تأیید"</string>
diff --git a/libs/WifiTrackerLib/res/values-fi/strings.xml b/libs/WifiTrackerLib/res/values-fi/strings.xml
index 43c1eea..e8c7b72 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Viimeistellään rekisteröitymistä…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Rekisteröityminen ei onnistunut. Yritä uudelleen napauttamalla."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Rekisteröityminen valmis. Yhdistetään…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Tälle verkolle lähetetään yksilöllinen tunnus, jolla voidaan seurata laitteen sijaintia. "<annotation id="url">"Lue lisää"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Tälle verkolle luodaan SIM-tunnus, jolla voidaan seurata laitteen sijaintia. "<annotation id="url">"Lue lisää"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Hyvin hidas"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Hidas"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
index 15cbde5..abc03f4 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Finalisation de l\'inscription en cours…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossible de terminer l\'inscription. Touchez pour réessayer."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscription terminée. Connexion en cours…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ce réseau reçoit un identifiant unique qui peut être utilisé pour faire le suivi de la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ce réseau reçoit un identifiant SIM qui peut être utilisé pour faire le suivi de la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Très lente"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lente"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-fr/strings.xml b/libs/WifiTrackerLib/res/values-fr/strings.xml
index f917d8f..3a6e68e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Finalisation de l\'inscription…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossible de finaliser l\'inscription. Appuyez ici pour réessayer."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscription terminée. Connexion…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ce réseau reçoit un identifiant unique qui peut être utilisé pour suivre la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ce réseau reçoit un ID de carte SIM qui peut être utilisé pour suivre la position de l\'appareil. "<annotation id="url">"En savoir plus"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Très lente"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lente"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Correcte"</string>
diff --git a/libs/WifiTrackerLib/res/values-gl/strings.xml b/libs/WifiTrackerLib/res/values-gl/strings.xml
index d4a8c0e..c0788f9 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completando rexistro…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Non se puido completar o rexistro. Toca para tentalo de novo."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Completouse o rexistro. Conectando…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta rede recibe un código exclusivo que se pode utilizar para realizar un seguimento da localización dos dispositivos. "<annotation id="url">"Máis información"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta rede recibe un código SIM que se pode utilizar para realizar un seguimento da localización do dispositivo. "<annotation id="url">"Máis información"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Moi lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Aceptar"</string>
diff --git a/libs/WifiTrackerLib/res/values-gu/strings.xml b/libs/WifiTrackerLib/res/values-gu/strings.xml
index e387dd3..91ab289 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"સાઇન અપ પૂર્ણ કરી રહ્યા છીએ…"</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="imsi_protection_warning" msgid="5231726821588271569">"આ નેટવર્કને સિમ ID મળે છે જેનો ઉપયોગ ડિવાઇસનું સ્થાન ટ્રૅક કરવા માટે થઈ શકે છે. "<annotation id="url">"વધુ જાણો"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ખૂબ જ ધીમી"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ધીમી"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ઓકે"</string>
diff --git a/libs/WifiTrackerLib/res/values-hi/strings.xml b/libs/WifiTrackerLib/res/values-hi/strings.xml
index 53d55e7..8cb0649 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन अप किया जा रहा है…"</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">"इस नेटवर्क को एक विशेष आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"इस नेटवर्क को एक सिम आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"अत्‍यधिक धीमी"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"धीमी"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ठीक है"</string>
diff --git a/libs/WifiTrackerLib/res/values-hr/strings.xml b/libs/WifiTrackerLib/res/values-hr/strings.xml
index 6ddae4f..6d1b010 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dovršavanje registracije…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registracija nije dovršena. Dodirnite za ponovni pokušaj."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je dovršena. Povezivanje…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ova mreža prima jedinstveni ID koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ova mreža prima jedinstveni ID SIM-a koji se može koristiti za praćenje lokacije uređaja. "<annotation id="url">"Saznajte više"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Vrlo sporo"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Sporo"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"U redu"</string>
diff --git a/libs/WifiTrackerLib/res/values-hu/strings.xml b/libs/WifiTrackerLib/res/values-hu/strings.xml
index 3f3afef..f8fd554 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Regisztráció befejezése…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nem sikerült a regisztráció befejezése. Koppintással újrapróbálkozhat."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"A regisztráció befejeződött. Csatlakozás…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ez a hálózat egyedi azonosítót kap, amely felhasználható az eszköz helyadatainak követésére. "<annotation id="url">"További információ"</annotation>"."</string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ez a hálózat SIM-azonosítót kap, amely felhasználható az eszköz helyadatainak követésére. "<annotation id="url">"További információ"</annotation>"."</string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Nagyon lassú"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lassú"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Rendben"</string>
diff --git a/libs/WifiTrackerLib/res/values-hy/strings.xml b/libs/WifiTrackerLib/res/values-hy/strings.xml
index 0d3def2..c6125f9 100644
--- a/libs/WifiTrackerLib/res/values-hy/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hy/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>
@@ -46,10 +47,10 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Գրանցումն ավարտվում է…"</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="imsi_protection_warning" msgid="5231726821588271569">"Այս ցանցը ստանում է եզակի ID, որի օգնությամբ հնարավոր է հետագծել սարքի տեղադրությունը։ "<annotation id="url">"Իմանալ ավելին"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Շատ դանդաղ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Դանդաղ"</string>
-    <string name="speed_label_okay" msgid="3741857805086997968">"Հաստատել"</string>
+    <string name="speed_label_okay" msgid="3741857805086997968">"Լավ"</string>
     <string name="speed_label_medium" msgid="3175703848952862009">"Միջին"</string>
     <string name="speed_label_fast" msgid="8344116097613544322">"Արագ"</string>
     <string name="speed_label_very_fast" msgid="1595806641512447877">"Շատ արագ"</string>
diff --git a/libs/WifiTrackerLib/res/values-in/strings.xml b/libs/WifiTrackerLib/res/values-in/strings.xml
index adb4a72..f1b067a 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Menyelesaikan pendaftaran…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Tidak dapat menyelesaikan pendaftaran. Ketuk untuk mencoba lagi."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Pendaftaran selesai. Menyambungkan…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Jaringan ini menerima ID unik yang dapat digunakan untuk melacak lokasi perangkat. "<annotation id="url">"Pelajari lebih lanjut"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Jaringan ini menerima ID SIM yang dapat digunakan untuk melacak lokasi perangkat. "<annotation id="url">"Pelajari lebih lanjut"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Sangat Lambat"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lambat"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Oke"</string>
diff --git a/libs/WifiTrackerLib/res/values-is/strings.xml b/libs/WifiTrackerLib/res/values-is/strings.xml
index b937486..5e7dbdf 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Gengur frá skráningu…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ekki tókst að ljúka við skráningu. Ýttu til að reyna aftur."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Skráningu lokið. Tengist…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Þetta net fær einkvæmt auðkenni sem hægt er að nota til að rekja staðsetningu tækis. "<annotation id="url">"Frekari upplýsingar"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Þetta net fær SIM-auðkenni sem hægt er að nota til að rekja staðsetningu tækisins. "<annotation id="url">"Frekari upplýsingar"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Mjög hægt"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Hægt"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Í lagi"</string>
diff --git a/libs/WifiTrackerLib/res/values-it/strings.xml b/libs/WifiTrackerLib/res/values-it/strings.xml
index 20c113d..3b9c1e1 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Completamento della registrazione…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Impossibile completare la registrazione. Tocca per riprovare."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrazione completata. Connessione…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Questa rete riceve un ID univoco che può essere usato per monitorare la posizione del dispositivo. "<annotation id="url">"Ulteriori informazioni"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Questa rete riceve un ID SIM che può essere usato per monitorare la posizione del dispositivo. "<annotation id="url">"Ulteriori informazioni"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Molto lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-iw/strings.xml b/libs/WifiTrackerLib/res/values-iw/strings.xml
index 3c43377..2cb6448 100644
--- a/libs/WifiTrackerLib/res/values-iw/strings.xml
+++ b/libs/WifiTrackerLib/res/values-iw/strings.xml
@@ -18,25 +18,26 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="summary_separator" msgid="6533720408587140819">" / "</string>
     <string name="auto_connect_disable" msgid="1078319396240632542">"החיבור האוטומטי כבוי"</string>
-    <string name="saved_network" msgid="6241977554502802914">"נשמר על ידי <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <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_check_password_try_again" msgid="2643230209986217827">"בדוק את הסיסמה ונסה שוב"</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>
+    <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>
-    <string name="wifi_remembered" msgid="5126903736498678708">"נשמר"</string>
+    <string name="wifi_remembered" msgid="5126903736498678708">"נשמרה"</string>
     <string name="wifi_metered_label" msgid="1362621600006544014">"נמדדת"</string>
     <string name="wifi_unmetered_label" msgid="499466875639448350">"לא נמדדת"</string>
-    <string name="connected_via_app" msgid="1818040967936972127">"מחוברת באמצעות <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <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="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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"מתבצעת השלמה של ההרשמה…"</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">"הרשת הזו מקבלת מזהה ייחודי שיכול לשמש למעקב אחר מיקום המכשיר. "<annotation id="url">"מידע נוסף"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"‏הרשת הזו מקבלת מזהה SIM שיכול לשמש למעקב אחר מיקום המכשיר. "<annotation id="url">"מידע נוסף"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"איטית מאוד"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"איטית"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"אישור"</string>
diff --git a/libs/WifiTrackerLib/res/values-ja/strings.xml b/libs/WifiTrackerLib/res/values-ja/strings.xml
index bb7187b..b6fc09e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"登録を完了しています…"</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 を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります。"<annotation id="url">"詳細"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"このネットワークは SIM ID を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります。"<annotation id="url">"詳細"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"とても遅い"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"遅い"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-ka/strings.xml b/libs/WifiTrackerLib/res/values-ka/strings.xml
index 56e8836..1c72c3c 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"მიმდინარეობს რეგისტრაციის დასრულება…"</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="imsi_protection_warning" msgid="5231726821588271569">"ეს ქსელი მიიღებს SIM-ის ID-ს, რომლის მეშვეობითაც შესაძლებელია მოწყობილობის მდებარეობაზე თვალის დევნება. "<annotation id="url">"შეიტყვეთ მეტი"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ძალიან ნელი"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ნელი"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"კარგი"</string>
diff --git a/libs/WifiTrackerLib/res/values-kk/strings.xml b/libs/WifiTrackerLib/res/values-kk/strings.xml
index 591170d..ef5c850 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Тіркелу аяқталуда…"</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">"Бұл желіге бірегей идентификатор беріледі, оның көмегімен құрылғының орналасқан жері қадағаланады. "<annotation id="url">"Толығырақ"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Бұл желіге SIM идентификаторы беріледі, оның көмегімен құрылғының орналасқан жері қадағаланады. "<annotation id="url">"Толығырақ"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Өте баяу"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Баяу"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Жарайды"</string>
diff --git a/libs/WifiTrackerLib/res/values-km/strings.xml b/libs/WifiTrackerLib/res/values-km/strings.xml
index 32150fa..ca88fa5 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"កំពុង​បញ្ចប់​ការចុះឈ្មោះ…"</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">"បណ្ដាញនេះទទួលលេខសម្គាល់ពិសេស ដែលអាចប្រើ​សម្រាប់​តាមដាន​ទីតាំងឧបករណ៍។ "<annotation id="url">"ស្វែងយល់បន្ថែម"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"បណ្ដាញនេះ​ទទួលបាន​លេខសម្គាល់ស៊ីម ដែល​អាចប្រើ​ដើម្បី​តាមដាន​ទីតាំង​ឧបករណ៍។ "<annotation id="url">"ស្វែងយល់បន្ថែម"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"យឺតណាស់"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"យឺត"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"យល់ព្រម"</string>
diff --git a/libs/WifiTrackerLib/res/values-kn/strings.xml b/libs/WifiTrackerLib/res/values-kn/strings.xml
index 6793a96..1340a66 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ…"</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">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ ಅನನ್ಯ ಐಡಿಯನ್ನು ಈ ನೆಟ್‌ವರ್ಕ್ ಸ್ವೀಕರಿಸುತ್ತದೆ. "<annotation id="url">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ ಅನನ್ಯ ಐಡಿಯನ್ನು ಈ ನೆಟ್‌ವರ್ಕ್ ಸ್ವೀಕರಿಸುತ್ತದೆ. "<annotation id="url">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ತುಂಬಾ ನಿಧಾನವಾಗಿದೆ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ನಿಧಾನ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ಸರಿ"</string>
diff --git a/libs/WifiTrackerLib/res/values-ko/strings.xml b/libs/WifiTrackerLib/res/values-ko/strings.xml
index eea05e8..ee9d54c 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"가입 완료 중…"</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="imsi_protection_warning" msgid="5231726821588271569">"이 네트워크는 기기 위치 추적에 사용될 수 있는 SIM ID를 수신합니다. "<annotation id="url">"자세히 알아보기"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"매우 느림"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"느림"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"보통"</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..f38ae79 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Катталуу аяктоодо…"</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">"Бул тармакка өзгөчө идентификатор берилет жана аны түзмөктүн жайгашкан жерин көзөмөлдөп туруу үчүн колдонууга болот. "<annotation id="url">"Кеңири маалымат"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Бул тармакка SIM-картанын идентификатору берилет жана аны түзмөктүн жайгашкан жерин көзөмөлдөп туруу үчүн колдонууга болот. "<annotation id="url">"Кеңири маалымат"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Өтө жай"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Жай"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Жарайт"</string>
diff --git a/libs/WifiTrackerLib/res/values-lo/strings.xml b/libs/WifiTrackerLib/res/values-lo/strings.xml
index 96d421b..c1f28f2 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ກຳລັງສຳເລັດການສະໝັກ…"</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">"ເຄືອຂ່າຍນີ້ຈະຮັບ unique ID ທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ອຸປະກອນ "<annotation id="url">"ສຶກສາເພີ່ມເຕີມ"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"ເຄືອຂ່າຍນີ້ຈະຮັບ ID ຊິມທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ອຸປະກອນ "<annotation id="url">"ສຶກສາເພີ່ມເຕີມ"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ຊ້າຫຼາຍ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ຊ້າ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ຕົກລົງ"</string>
diff --git a/libs/WifiTrackerLib/res/values-lt/strings.xml b/libs/WifiTrackerLib/res/values-lt/strings.xml
index ff32f1c..40d3f1e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Baigiamas prisiregistravimas…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nepavyko užbaigti prisiregistravimo. Jei norite bandyti dar kartą, palieskite."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Prisiregistravimas baigtas. Prijungiama…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Šis tinklas gauna unikalų ID, kurį galima naudoti įrenginio vietovei stebėti. "<annotation id="url">"Sužinokite daugiau"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Šis tinklas gauna SIM kortelės ID, kurį galima naudoti įrenginio vietovei stebėti. "<annotation id="url">"Sužinokite daugiau"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Labai lėtas"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lėtas"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Gerai"</string>
diff --git a/libs/WifiTrackerLib/res/values-lv/strings.xml b/libs/WifiTrackerLib/res/values-lv/strings.xml
index 4aebe32..1450cfc 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Notiek reģistrācijas pabeigšana…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nevarēja pabeigt reģistrāciju. Pieskarieties, lai mēģinātu vēlreiz."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Reģistrācija ir pabeigta. Notiek savienojuma izveide…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Šis tīkls saņem unikālo ID, ko var izmantot, lai izsekotu ierīces atrašanās vietu. "<annotation id="url">"Uzziniet vairāk"</annotation>"."</string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Šis tīkls saņem SIM ID, ko var izmantot, lai izsekotu ierīces atrašanās vietai. "<annotation id="url">"Uzziniet vairāk"</annotation>"."</string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Ļoti lēns"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lēns"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Labi"</string>
diff --git a/libs/WifiTrackerLib/res/values-mk/strings.xml b/libs/WifiTrackerLib/res/values-mk/strings.xml
index 36064f3..93d47f9 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,9 +45,9 @@
     <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="imsi_protection_warning" msgid="5231726821588271569">"Мрежава прима ID на SIM-картичка што може да се користи за следење на локацијата на уредот. "<annotation id="url">"Дознајте повеќе"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Многу бавна"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Бавна"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Во ред"</string>
diff --git a/libs/WifiTrackerLib/res/values-ml/strings.xml b/libs/WifiTrackerLib/res/values-ml/strings.xml
index 90798a6..2a69021 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"സൈൻ അപ്പ് പൂർത്തിയാക്കുന്നു…"</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">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന തനത് ഐഡി ഈ നെറ്റ്‌വർക്ക് സ്വീകരിക്കുന്നു. "<annotation id="url">"കൂടുതലറിയുക"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന സിം ഐഡി ഈ നെറ്റ്‌വർക്കിന് ലഭിക്കും. "<annotation id="url">"കൂടുതലറിയുക"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"വളരെ കുറഞ്ഞ വേഗത്തിൽ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"കുറഞ്ഞ വേഗത്തിൽ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ശരി"</string>
diff --git a/libs/WifiTrackerLib/res/values-mn/strings.xml b/libs/WifiTrackerLib/res/values-mn/strings.xml
index 577bd6e..9e9b247 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Бүртгэлийг дуусгаж байна…"</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">"Энэ сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой цор ганц дугаарыг хүлээн авдаг. "<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Энэ сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой SIM ID-г хүлээн авдаг. "<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Маш удаан"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Удаан"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ЗА"</string>
diff --git a/libs/WifiTrackerLib/res/values-mr/strings.xml b/libs/WifiTrackerLib/res/values-mr/strings.xml
index fc7811f..963956f 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन-अप पूर्ण होत आहे…"</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">"हे नेटवर्क डिव्हाइसच्या स्थानाचा माग घेण्यासाठी वापरता येणारा युनिक आयडी मिळवते. "<annotation id="url">"अधिक जाणून घ्या"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"हे नेटवर्क डिव्हाइसच्या स्थानाचा माग ठेवण्यासाठी वापरता येणारा सिम आयडी मिळवते. "<annotation id="url">"अधिक जाणून घ्या"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"खूप हळू"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"हळू"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ठीक आहे"</string>
diff --git a/libs/WifiTrackerLib/res/values-ms/strings.xml b/libs/WifiTrackerLib/res/values-ms/strings.xml
index 81b0ce3..8d06b42 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Menyelesaikan pendaftaran…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Tidak dapat menyelesaikan pendaftaran. Ketik untuk mencuba lagi."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Pendaftaran selesai. Menyambung…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Rangkaian ini menerima ID unik yang boleh digunakan untuk menjejaki lokasi peranti. "<annotation id="url">"Ketahui lebih lanjut"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Rangkaian ini menerima ID SIM yang boleh digunakan untuk menjejak lokasi peranti. "<annotation id="url">"Ketahui lebih lanjut"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Sangat Perlahan"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Perlahan"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-my/strings.xml b/libs/WifiTrackerLib/res/values-my/strings.xml
index a3f67e1..524fbb6 100644
--- a/libs/WifiTrackerLib/res/values-my/strings.xml
+++ b/libs/WifiTrackerLib/res/values-my/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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"အကောင့်ဖွင့်ခြင်း အပြီးသတ်နေသည်…"</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="imsi_protection_warning" msgid="5231726821588271569">"ဤကွန်ရက်က စက်တည်နေရာကို ခြေရာခံရန် အသုံးပြုနိုင်သည့် SIM ID တစ်ခုကို ရရှိပါသည်။ "<annotation id="url">"ပိုမိုလေ့လာရန်"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"အလွန်နှေး"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"နှေး"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-nb/strings.xml b/libs/WifiTrackerLib/res/values-nb/strings.xml
index 8379223..0a670a8 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Fullfører registreringen …"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kunne ikke fullføre registreringen. Trykk for å prøve på nytt."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registreringen er fullført. Kobler til …"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Dette nettverket mottar en unik ID som kan brukes til å spore enhetsposisjonen. "<annotation id="url">"Finn ut mer"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Dette nettverket mottar en SIM-ID som kan brukes til å spore enhetsposisjonen. "<annotation id="url">"Finn ut mer"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Veldig treg"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Treg"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string>
diff --git a/libs/WifiTrackerLib/res/values-ne/strings.xml b/libs/WifiTrackerLib/res/values-ne/strings.xml
index 39e62d8..cc330a5 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"साइन अप गर्ने कार्य सम्पन्न गर्दै…"</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="imsi_protection_warning" msgid="5231726821588271569">"यो नेटवर्कलाई यन्त्रको स्थान पहिल्याउन प्रयोग गर्न मिल्ने एउटा अद्वितीय SIM कार्ड ID उपलब्ध गराइन्छ। "<annotation id="url">"थप जान्नुहोस्"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"धेरै ढिलो"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"बिस्तारै"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ठिक छ"</string>
diff --git a/libs/WifiTrackerLib/res/values-nl/strings.xml b/libs/WifiTrackerLib/res/values-nl/strings.xml
index a026429..3b68fc4 100644
--- a/libs/WifiTrackerLib/res/values-nl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-nl/strings.xml
@@ -24,7 +24,7 @@
     <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Verificatieprobleem"</string>
     <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Controleer het wachtwoord en probeer het opnieuw"</string>
     <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP-configuratie mislukt"</string>
-    <string name="wifi_disabled_generic" msgid="8307050327779256414">"Uitgeschakeld"</string>
+    <string name="wifi_disabled_generic" msgid="8307050327779256414">"Uitgezet"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Toegangspunt tijdelijk vol"</string>
     <string name="wifi_disconnected" msgid="3720926757662831062">"Verbinding verbroken"</string>
     <string name="wifi_remembered" msgid="5126903736498678708">"Opgeslagen"</string>
@@ -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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Aanmelding voltooien…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kan aanmelding niet voltooien. Tik om het opnieuw te proberen."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Aanmelding voltooid. Verbinden…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Dit netwerk ontvangt een unieke ID die kan worden gebruikt om de apparaatlocatie bij te houden. "<annotation id="url">"Meer informatie"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Dit netwerk ontvangt een simkaart-ID die kan worden gebruikt om de apparaatlocatie bij te houden. "<annotation id="url">"Meer informatie"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Zeer langzaam"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Langzaam"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Redelijk"</string>
diff --git a/libs/WifiTrackerLib/res/values-or/strings.xml b/libs/WifiTrackerLib/res/values-or/strings.xml
index cec830b..15b6459 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ସାଇନ୍ ଅପ୍ ଶେଷ ହେଉଛି…"</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="imsi_protection_warning" msgid="5231726821588271569">"ଏହି ନେଟୱାର୍କ ଏକ SIM ID ପ୍ରାପ୍ତ କରେ ଯାହା ଡିଭାଇସ୍ ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାକୁ ବ୍ୟବହାର କରାଯାଇପାରିବ। "<annotation id="url">"ଅଧିକ ଜାଣନ୍ତୁ"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ବହୁତ ମନ୍ଥର"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"କମ୍‌ ବେଗ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ଠିକ୍‌ ଅଛି"</string>
diff --git a/libs/WifiTrackerLib/res/values-pa/strings.xml b/libs/WifiTrackerLib/res/values-pa/strings.xml
index 7966cd7..de3c29f 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</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">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਵਿਲੱਖਣ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ ਜਿਸਨੂੰ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤਿਆ ਦਾ ਸਕਦਾ ਹੈ। "<annotation id="url">"ਹੋਰ ਜਾਣੋ"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਸਿਮ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ ਜਿਸਨੂੰ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। "<annotation id="url">"ਹੋਰ ਜਾਣੋ"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ਬਹੁਤ ਹੌਲੀ"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ਹੌਲੀ"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ਠੀਕ ਹੈ"</string>
diff --git a/libs/WifiTrackerLib/res/values-pl/strings.xml b/libs/WifiTrackerLib/res/values-pl/strings.xml
index f4d5cca..222627d 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kończę rejestrować…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nie udało się dokończyć rejestracji. Kliknij, by spróbować ponownie."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Rejestracja zakończona. Łączę…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ta sieć otrzymuje unikalny identyfikator, który można wykorzystać do śledzenia lokalizacji urządzenia. "<annotation id="url">"Więcej informacji"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ta sieć otrzymuje unikalny identyfikator karty SIM, który można wykorzystać do śledzenia lokalizacji urządzenia. "<annotation id="url">"Więcej informacji"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Bardzo wolna"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Wolna"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
index d3adf52..3b86fa6 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Concluindo inscrição…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. Conectando…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta rede recebe um código exclusivo que pode ser usado para rastrear a localização do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Essa rede recebe um ID de chip que pode ser usado para monitorar o local do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string>
diff --git a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
index bcce991..f96f6f0 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"A concluir a inscrição…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. A estabelecer ligação…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta rede recebe um ID exclusivo que pode ser utilizado para monitorizar a localização do dispositivo. "<annotation id="url">"Saber mais"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Esta rede recebe um ID do SIM que pode ser utilizado para monitorizar a localização do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-pt/strings.xml b/libs/WifiTrackerLib/res/values-pt/strings.xml
index d3adf52..3b86fa6 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Concluindo inscrição…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Não foi possível concluir a inscrição. Toque para tentar novamente."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Inscrição concluída. Conectando…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Esta rede recebe um código exclusivo que pode ser usado para rastrear a localização do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Essa rede recebe um ID de chip que pode ser usado para monitorar o local do dispositivo. "<annotation id="url">"Saiba mais"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Muito lenta"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lenta"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Ok"</string>
diff --git a/libs/WifiTrackerLib/res/values-ro/strings.xml b/libs/WifiTrackerLib/res/values-ro/strings.xml
index e4d24eb..219e4c4 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Se finalizează înscrierea…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Nu s-a putut finaliza înscrierea. Atingeți pentru a încerca din nou."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Înscrierea a fost finalizată. Se conectează…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Această rețea primește un ID unic care se poate folosi pentru a urmări locația dispozitivului. "<annotation id="url">"Aflați mai multe"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Această rețea primește un cod SIM care se poate folosi pentru a urmări locația dispozitivului. "<annotation id="url">"Aflați mai multe"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Foarte lentă"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Lentă"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Bine"</string>
diff --git a/libs/WifiTrackerLib/res/values-ru/strings.xml b/libs/WifiTrackerLib/res/values-ru/strings.xml
index f8dc5c8..672781b 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Завершение регистрации…"</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">"Эта сеть получает уникальный идентификатор, с помощью которого можно отследить местоположение устройства. "<annotation id="url">"Подробнее…"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Этой сети будет передан идентификатор SIM-карты, с помощью которого можно отследить местоположение устройства. "<annotation id="url">"Подробнее…"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Очень медленная"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Медленная"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string>
diff --git a/libs/WifiTrackerLib/res/values-si/strings.xml b/libs/WifiTrackerLib/res/values-si/strings.xml
index 16a0501..cee255f 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"ලියාපදිංචිය සම්පූර්ණ කරමින්…"</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="imsi_protection_warning" msgid="5231726821588271569">"උපාංග ස්ථානය නිරීක්ෂණය කිරීමට භාවිත කළ හැකි SIM ID එකක් මෙම ජාලයට ලැබේ. "<annotation id="url">"තව දැන ගන්න"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ඉතා මන්දගාමී"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"මන්දගාමී"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"හරි"</string>
diff --git a/libs/WifiTrackerLib/res/values-sk/strings.xml b/libs/WifiTrackerLib/res/values-sk/strings.xml
index d432ef6..11fd338 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončuje sa registrácia…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registráciu sa nepodarilo dokončiť. Klepnutím to skúste znova."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrácia je dokončená. Pripája sa…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Táto sieť prijíma jedinečný identifikátor, pomocou ktorého je možné sledovať polohu zariadenia. "<annotation id="url">"Ďalšie informácie"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Táto sieť dostáva jedinečný identifikátor SIM karty, pomocou ktorého je možné sledovať polohu zariadenia. "<annotation id="url">"Ďalšie informácie"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Veľmi pomalá"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Pomalá"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-sl/strings.xml b/libs/WifiTrackerLib/res/values-sl/strings.xml
index 4501d82..8cd9ef5 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Dokončevanje registracije …"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registracije ni bilo mogoče dokončati. Če želite poskusiti znova, se dotaknite."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registracija je končana. Povezovanje …"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"To omrežje prejme enolični ID, s katerim je mogoče spremljati lokacijo naprave. "<annotation id="url">"Več o tem"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"To omrežje prejme ID kartice SIM, s katerim je mogoče spremljati lokacijo naprave. "<annotation id="url">"Več o tem"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Zelo počasna"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Počasna"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"V redu"</string>
diff --git a/libs/WifiTrackerLib/res/values-sq/strings.xml b/libs/WifiTrackerLib/res/values-sq/strings.xml
index dde5ee0..90c72ac 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Po përfundon regjistrimin…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Regjistrimi nuk mund të përfundonte. Trokit për të provuar përsëri."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Regjistrimi përfundoi. Po lidhet…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Ky rrjet merr një ID unike që mund të përdoret për të monitoruar vendndodhjen e pajisjes. "<annotation id="url">"Mëso më shumë"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ky rrjet merr një ID karte SIM që mund të përdoret për të monitoruar vendndodhjen e pajisjes. "<annotation id="url">"Mëso më shumë"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Shumë e ulët"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"E ngadaltë"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Në rregull"</string>
diff --git a/libs/WifiTrackerLib/res/values-sr/strings.xml b/libs/WifiTrackerLib/res/values-sr/strings.xml
index 1d133e3..007e58e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Регистрација се довршава…"</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">"Ова мрежа захтева јединствени ИД који може да се користи за праћење локације уређаја. "<annotation id="url">"Сазнајте више"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ова мрежа добија ИД SIM картице који може да се користи за праћење локације уређаја. "<annotation id="url">"Сазнајте више"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Веома спора"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Спора"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Потврди"</string>
diff --git a/libs/WifiTrackerLib/res/values-sv/strings.xml b/libs/WifiTrackerLib/res/values-sv/strings.xml
index 589ab84..af1f0c4 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registreringen slutförs …"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Det gick inte att slutföra registreringen. Tryck för att försöka igen."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registrering har slutförts. Ansluter …"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Det här nätverket får ett unikt id som kan användas till att spåra enhetens plats. "<annotation id="url">"Läs mer"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Det här nätverket får ett SIM-id som kan användas till att spåra enhetens plats. "<annotation id="url">"Läs mer"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Mycket långsam"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Långsam"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Okej"</string>
diff --git a/libs/WifiTrackerLib/res/values-sw/strings.xml b/libs/WifiTrackerLib/res/values-sw/strings.xml
index 573ba22..a4bc8aa 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Inakamilisha usajili…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Imeshindwa kukamilisha usajili. Gusa ili ujaribu tena."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Imekamilisha usajili. Inaunganisha…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Mtandao huu hupokea kitambulisho cha kipekee ambacho kinaweza kutumiwa kufuatilia mahali kifaa kilipo. "<annotation id="url">"Pata maelezo zaidi"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Mtandao huu hupokea kitambulisho cha SIM ambacho kinaweza kutumiwa kufuatilia mahali kifaa kilipo. "<annotation id="url">"Pata maelezo zaidi"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Polepole Sana"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Polepole"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Sawa"</string>
diff --git a/libs/WifiTrackerLib/res/values-ta/strings.xml b/libs/WifiTrackerLib/res/values-ta/strings.xml
index 5b2f258..7206981 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"பதிவு செய்தல் நிறைவடைகிறது…"</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">"இந்த நெட்வொர்க்கானது சாதன இருப்பிடத்தை டிராக் செய்யப் பயன்படுத்தப்படும் தனித்துவமான ஐடியைப் பெறும். "<annotation id="url">"மேலும் அறிக"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"சாதன இருப்பிடத்தைக் கண்காணிக்கப் பயன்படுத்தப்படும் சிம் ஐடியை இந்த நெட்வொர்க் பெறும். "<annotation id="url">"மேலும் அறிக"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"மிகவும் வேகம் குறைவானது"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"வேகம் குறைவு"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"சரி"</string>
diff --git a/libs/WifiTrackerLib/res/values-te/strings.xml b/libs/WifiTrackerLib/res/values-te/strings.xml
index aef857d..ede7edf 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"సైన్ అప్ పూర్తవుతోంది…"</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="imsi_protection_warning" msgid="5231726821588271569">"పరికరం లొకేషన్‌ను ట్రాక్ చేయడానికి ఉపయోగపడే SIM IDని ఈ నెట్‌వర్క్ అందుకుంటుంది. "<annotation id="url">"మరింత తెలుసుకోండి"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"చాలా నెమ్మది"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"నెమ్మది"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"సరే"</string>
diff --git a/libs/WifiTrackerLib/res/values-th/strings.xml b/libs/WifiTrackerLib/res/values-th/strings.xml
index 716d232..cc18e7f 100644
--- a/libs/WifiTrackerLib/res/values-th/strings.xml
+++ b/libs/WifiTrackerLib/res/values-th/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"จุดเข้าใช้งานเต็มชั่วคราว"</string>
     <string name="wifi_disconnected" msgid="3720926757662831062">"ยกเลิกการเชื่อมต่อแล้ว"</string>
     <string name="wifi_remembered" msgid="5126903736498678708">"บันทึกแล้ว"</string>
-    <string name="wifi_metered_label" msgid="1362621600006544014">"มีการวัดปริมาณอินเทอร์เน็ต"</string>
+    <string name="wifi_metered_label" msgid="1362621600006544014">"แบบจำกัดปริมาณ"</string>
     <string name="wifi_unmetered_label" msgid="499466875639448350">"ไม่มีการวัดปริมาณอินเทอร์เน็ต"</string>
     <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>
@@ -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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"กำลังลงชื่อสมัครใช้ให้เสร็จสิ้น…"</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">"เครือข่ายนี้ได้รับรหัสที่ไม่ซ้ำกันซึ่งใช้ติดตามตำแหน่งอุปกรณ์ได้ "<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"เครือข่ายนี้จะได้รับรหัส SIM ซึ่งใช้ติดตามตำแหน่งอุปกรณ์ได้ "<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"ช้ามาก"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"ช้า"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ตกลง"</string>
diff --git a/libs/WifiTrackerLib/res/values-tl/strings.xml b/libs/WifiTrackerLib/res/values-tl/strings.xml
index a55511e..ccb973a 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kinukumpleto ang pag-sign up…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Hindi makumpleto ang pag-sign up. I-tap para subukan ulit."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Kumpleto na ang pag-sign up. Kumokonekta…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Tumatanggap ang network na ito ng natatanging ID na magagamit sa pag-track ng lokasyon ng device. "<annotation id="url">"Matuto pa"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Tumatanggap ang network na ito ng SIM ID na magagamit sa pagsubaybay ng lokasyon ng device. "<annotation id="url">"Matuto pa"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Napakabagal"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Mabagal"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-tr/strings.xml b/libs/WifiTrackerLib/res/values-tr/strings.xml
index 6673fff..a480a3d 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Kayıt işlemi tamamlanıyor…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Kayıt işlemi tamamlanamadı. Tekrar denemek için dokunun."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Kayıt tamamlandı. Bağlanıyor…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Bu ağ, cihaz konumunu izlemek için kullanılabilecek benzersiz bir kimlik alır. "<annotation id="url">"Daha fazla bilgi"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu ağ, cihaz konumunu izlemek için kullanılabilecek bir SIM kimliği alır. "<annotation id="url">"Daha fazla bilgi"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Çok Yavaş"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Yavaş"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Tamam"</string>
diff --git a/libs/WifiTrackerLib/res/values-uk/strings.xml b/libs/WifiTrackerLib/res/values-uk/strings.xml
index 94b9852..8a69658 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Завершення реєстрації…"</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">"Ця мережа отримує унікальний ідентифікатор, за допомогою якого можна відстежити місцезнаходження пристрою. "<annotation id="url">"Докладніше"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Ця мережа отримує ідентифікатор SIM-карти, за допомогою якого можна відстежити місцезнаходження пристрою. "<annotation id="url">"Докладніше"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Дуже повільна"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Повільна"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ОК"</string>
diff --git a/libs/WifiTrackerLib/res/values-ur/strings.xml b/libs/WifiTrackerLib/res/values-ur/strings.xml
index 84ae38d..2bc36a5 100644
--- a/libs/WifiTrackerLib/res/values-ur/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ur/strings.xml
@@ -22,7 +22,7 @@
     <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_check_password_try_again" msgid="2643230209986217827">"پاسورڈ چیک کر کے دوبارہ کوشش کریں"</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>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"رسائی پوائنٹ عارضی طور پر فُل ہے"</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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"سائن اپ مکمل ہو رہا ہے…"</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="imsi_protection_warning" msgid="5231726821588271569">"‏اس نیٹ ورک کو ایک SIM ID موصول ہوتی ہے جو آلہ کے مقام کو ٹریک کرنے کیلئے استعمال ہو سکتی ہے۔ "<annotation id="url">"مزید جانیں"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"بہت سست"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"سست"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"ٹھیک ہے"</string>
diff --git a/libs/WifiTrackerLib/res/values-uz/strings.xml b/libs/WifiTrackerLib/res/values-uz/strings.xml
index c2a17db..f19791e 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Registratsiya tamomlanmoqda…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Registratsiya tamomlanmadi. Qayta urinish uchun tegining."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Registratsiya qilindi. Ulanmoqda…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Bu tarmoqqa qurilma joylashuvini aniqlash imkonini beruvchi maxsus identifikator beriladi. "<annotation id="url">"Batafsil"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Bu tarmoqqa qurilma joylashuvini aniqlash imkonini beruvchi SIM identifikator beriladi. "<annotation id="url">"Batafsil"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Juda sekin"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Sekin"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"OK"</string>
diff --git a/libs/WifiTrackerLib/res/values-vi/strings.xml b/libs/WifiTrackerLib/res/values-vi/strings.xml
index 18f7693..90a0a10 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Đang hoàn tất việc đăng ký…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Không thể hoàn tất việc đăng ký. Hãy nhấn để thử lại."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Đã đăng ký xong. Đang kết nối…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Mạng này nhận được một mã nhận dạng duy nhất có thể dùng để theo dõi vị trí của thiết bị. "<annotation id="url">"Tìm hiểu thêm"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Mạng này nhận được một mã nhận dạng SIM có thể dùng để theo dõi vị trí của thiết bị. "<annotation id="url">"Tìm hiểu thêm"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Rất chậm"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Chậm"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"Khá tốt"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
index 2011a15..f3bf193 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成注册…"</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="imsi_protection_warning" msgid="5231726821588271569">"此网络会收到可用于跟踪设备位置的 SIM 卡 ID。"<annotation id="url">"了解详情"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"很慢"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"良好"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
index eb8007d..e063970 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成申請…"</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="imsi_protection_warning" msgid="5231726821588271569">"此網絡會接收可用於追蹤裝置位置的 SIM 卡 ID。"<annotation id="url">"瞭解詳情"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"非常慢"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"良好"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
index d5721fe..35f21eb 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"正在完成註冊程序…"</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="imsi_protection_warning" msgid="5231726821588271569">"這個網路會收到可用於追蹤裝置位置的 SIM 卡 ID。"<annotation id="url">"瞭解詳情"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"非常慢"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"慢"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"確定"</string>
diff --git a/libs/WifiTrackerLib/res/values-zu/strings.xml b/libs/WifiTrackerLib/res/values-zu/strings.xml
index 9a56c40..b0a54ce 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>
@@ -46,7 +47,7 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Iqedela ukubhalisa…"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"Ayikwazanga ukuqedelela ukubhalisa. Thepha ukuze uzame futhi."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Ukubhalisa kuqediwe. Iyaxhuma…"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"Le nethiwekhi ithola i-ID ehlukile engasetshenziselwa ukulandelela indawo yedivayisi. "<annotation id="url">"Funda kabanzi"</annotation></string>
+    <string name="imsi_protection_warning" msgid="5231726821588271569">"Le nethiwekhi ithola i-SIM ID engasetshenziselwa ukulandelela indawo yedivayisi. "<annotation id="url">"Funda kabanzi"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Phansi kakhulu"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"Phansi"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"KULUNGILE"</string>
diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml
index c238f66..c47e289 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>
 
@@ -170,7 +173,7 @@
     <string name="osu_sign_up_complete">Sign-up complete. Connecting\u2026</string>
 
     <!-- IMSI protection warning for non-protection network [CHAR LIMIT=NONE] -->
-    <string name="imsi_protection_warning">This network receives a unique ID that can be used to track device location. <annotation id="url">Learn more</annotation></string>
+    <string name="imsi_protection_warning">This network receives a SIM ID that can be used to track device location. <annotation id="url">Learn more</annotation></string>
 
     <!-- Help URL, IMSI protection [DO NOT TRANSLATE] -->
     <string name="help_url_imsi_protection" translatable="false"></string>
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
index 18611e2..2633bc3 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;
@@ -111,6 +113,12 @@
                         .filter(mRequestedScoreKeys::add)
                         .collect(toList()));
                 handleScanResultsAvailableAction(intent);
+            } else if (WifiManager.PARTIAL_SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
+                mNetworkScoreManager.requestScores(mWifiManager.getScanResults().stream()
+                        .map(NetworkKey::createFromScanResult)
+                        .filter(mRequestedScoreKeys::add)
+                        .collect(toList()));
+                handleScanResultsAvailableAction(intent);
             } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)) {
                 handleConfiguredNetworksChangedAction(intent);
             } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
@@ -133,6 +141,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 +154,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();
+                }
             };
 
     /**
@@ -213,6 +265,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        filter.addAction(WifiManager.PARTIAL_SCAN_RESULTS_AVAILABLE_ACTION);
         filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
@@ -220,6 +273,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 +310,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 +396,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 +472,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..9b02446 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,11 +279,15 @@
         }
 
         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;
         }
+        updateWifiGenerationInfo(mCurrentScanResults);
         notifyOnUpdated();
     }
 
@@ -336,7 +352,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..48bd37a 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
@@ -543,13 +555,16 @@
             ScanResult bestScanResult = null;
             if (homeScanResults != null && !homeScanResults.isEmpty()) {
                 currentScanResults.addAll(homeScanResults);
+                updateWifiGenerationInfo(homeScanResults);
             } else if (roamingScanResults != null && !roamingScanResults.isEmpty()) {
                 currentScanResults.addAll(roamingScanResults);
                 mIsRoaming = true;
+                updateWifiGenerationInfo(roamingScanResults);
             }
             bestScanResult = getBestScanResultByLevel(currentScanResults);
             if (bestScanResult != null) {
                 mWifiConfig.SSID = "\"" + bestScanResult.SSID + "\"";
+                updateTransitionModeCapa(bestScanResult);
             }
             if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
                 mLevel = bestScanResult != null
@@ -614,7 +629,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..acfc16c 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) {
@@ -685,6 +719,7 @@
         if (bestScanResult != null) {
             updateEapType(bestScanResult);
             updatePskType(bestScanResult);
+            updateTransitionModeCapa(bestScanResult);
         }
 
         if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
@@ -696,6 +731,9 @@
                 mSpeed = getAverageSpeedFromScanResults(mScoreCache, mCurrentScanResults);
             }
         }
+
+        updateWifiGenerationInfo(mCurrentScanResults);
+
         notifyOnUpdated();
     }
 
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index 62bbe0f..5a14ec4 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..89c7417 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -28,6 +28,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -223,6 +224,17 @@
     protected boolean mCalledConnect = false;
     protected boolean mCalledDisconnect = false;
 
+    private boolean mIsValidated;
+    private boolean mIsDefaultNetwork;
+    protected boolean mIsLowQuality;
+
+    private int mDeviceWifiStandard;
+    private int mWifiStandard = ScanResult.WIFI_STANDARD_LEGACY;
+    private boolean mHe8ssCapableAp;
+    private boolean mVhtMax8SpatialStreamsSupport;
+    private boolean mIsPskSaeTransitionMode;
+    private boolean mIsOweTransitionMode;
+
     WifiEntry(@NonNull Handler callbackHandler, @NonNull WifiManager wifiManager,
             @NonNull WifiNetworkScoreCache scoreCache,
             boolean forSavedNetworksPage) throws IllegalArgumentException {
@@ -232,6 +244,7 @@
         mForSavedNetworksPage = forSavedNetworksPage;
         mWifiManager = wifiManager;
         mScoreCache = scoreCache;
+        updatetDeviceWifiGenerationInfo();
     }
 
     // Info available for all WifiEntries //
@@ -289,6 +302,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 +473,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 +662,9 @@
             mNetworkInfo = null;
             mNetworkCapabilities = null;
             mConnectedInfo = null;
+            mIsValidated = false;
+            mIsDefaultNetwork = false;
+            mIsLowQuality = false;
             if (mCalledDisconnect) {
                 mCalledDisconnect = false;
                 mCallbackHandler.post(() -> {
@@ -686,10 +724,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 +858,103 @@
                 .append(isSuggestion())
                 .append(",level:")
                 .append(getLevel())
+                .append(shouldShowXLevelIcon() ? "X" : "")
                 .append(",security:")
                 .append(getSecurity())
+                .append(",standard:")
+                .append(getWifiStandard())
+                .append(",he8ssAp:")
+                .append(isHe8ssCapableAp())
+                .append(",vhtMax8ssCapa:")
+                .append(isVhtMax8SpatialStreamsSupported())
                 .append(",connected:")
                 .append(getConnectedState() == CONNECTED_STATE_CONNECTED ? "true" : "false")
                 .append(",connectedInfo:")
                 .append(getConnectedInfo())
+                .append(",isValidated:")
+                .append(mIsValidated)
+                .append(",isDefaultNetwork:")
+                .append(mIsDefaultNetwork)
                 .toString();
     }
+
+    protected void updateTransitionModeCapa(ScanResult scanResult) {
+        mIsPskSaeTransitionMode = scanResult.capabilities.contains("PSK")
+                                      && scanResult.capabilities.contains("SAE");
+        mIsOweTransitionMode = scanResult.capabilities.contains("OWE_TRANSITION");
+    }
+
+    public boolean isPskSaeTransitionMode() {
+        return mIsPskSaeTransitionMode;
+    }
+
+    public boolean isOweTransitionMode() {
+        return mIsOweTransitionMode;
+    }
+
+    private void updatetDeviceWifiGenerationInfo() {
+        if (mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX))
+            mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11AX;
+        else if (mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC))
+            mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11AC;
+        else if (mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N))
+            mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11N;
+        else
+            mDeviceWifiStandard = ScanResult.WIFI_STANDARD_LEGACY;
+
+        mVhtMax8SpatialStreamsSupport = mWifiManager.isVht8ssCapableDevice();
+    }
+
+    /**
+     * Returns Wi-Fi standard of the connection/AP
+     */
+    public int getWifiStandard() {
+        if (getConnectedInfo() == null || mWifiInfo == null ||
+                getConnectedState() != CONNECTED_STATE_CONNECTED)
+            return mWifiStandard;
+
+        return mWifiInfo.getWifiStandard();
+    }
+
+    /**
+     * Returns true if AP is HE 8SS capable connection/AP
+     */
+    public boolean isHe8ssCapableAp() {
+        if (getConnectedInfo() == null || mWifiInfo == null ||
+                getConnectedState() != CONNECTED_STATE_CONNECTED)
+            return mHe8ssCapableAp;
+
+        return mWifiInfo.isHe8ssCapableAp();
+    }
+
+    /**
+     * Returns true if VHT 8SS capable connection/AP
+     */
+    public boolean isVhtMax8SpatialStreamsSupported() {
+        if (getConnectedInfo() == null || mWifiInfo == null ||
+                getConnectedState() != CONNECTED_STATE_CONNECTED)
+            return mVhtMax8SpatialStreamsSupport;
+
+        return mWifiInfo.isVhtMax8SpatialStreamsSupported();
+    }
+
+    protected void updateWifiGenerationInfo(@Nullable List<ScanResult> scanResults) {
+        int currResultWifiStandard;
+        int minConnectionCapability = mDeviceWifiStandard;
+
+        // Capture minimum possible connection capability of all scan results
+        mHe8ssCapableAp = true;
+        for (ScanResult result : scanResults) {
+            currResultWifiStandard = result.getWifiStandard();
+
+            // Check if atleast one bssid present without HE and 8SS support
+            if (!result.capabilities.contains("WFA-HE-READY") && mHe8ssCapableAp)
+                mHe8ssCapableAp = false;
+
+            if (currResultWifiStandard < minConnectionCapability)
+                minConnectionCapability = currResultWifiStandard;
+        }
+
+        mWifiStandard = minConnectionCapability;
+    }
 }
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/libwifi_hal/Android.mk b/libwifi_hal/Android.mk
index 7bdbc32..6335352 100644
--- a/libwifi_hal/Android.mk
+++ b/libwifi_hal/Android.mk
@@ -91,8 +91,10 @@
   LIB_WIFI_HAL := libwifi-hal-bcm
   VENDOR_LOCAL_SHARED_LIBRARIES := libcrypto
 else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
+ifneq ($(TARGET_DEVICE),qssi)
   LIB_WIFI_HAL := libwifi-hal-qcom
   VENDOR_LOCAL_SHARED_LIBRARIES := libcld80211
+endif #End of Check for qssi target
 else ifeq ($(BOARD_WLAN_DEVICE), mrvl)
   # this is commented because none of the nexus devices
   # that sport Marvell's wifi have support for HAL
diff --git a/libwifi_hal/wifi_hal_common.cpp b/libwifi_hal/wifi_hal_common.cpp
index 0d8e0fb..f0a1674 100644
--- a/libwifi_hal/wifi_hal_common.cpp
+++ b/libwifi_hal/wifi_hal_common.cpp
@@ -19,11 +19,13 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <time.h>
 
 #include <android-base/logging.h>
 #include <cutils/misc.h>
 #include <cutils/properties.h>
 #include <sys/syscall.h>
+#include <android-base/properties.h>
 
 extern "C" int init_module(void *, unsigned long, const char *);
 extern "C" int delete_module(const char *, unsigned int);
@@ -52,8 +54,12 @@
 static const char MODULE_FILE[] = "/proc/modules";
 #endif
 
+#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+int kDriverStateAccessRetrySleepMillis = 200;
+#endif
+
 static int insmod(const char *filename, const char *args) {
-  int ret;
+  int ret = 0;
   int fd;
 
   fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
@@ -62,13 +68,13 @@
     return -1;
   }
 
-  ret = syscall(__NR_finit_module, fd, args, 0);
-
-  close(fd);
-  if (ret < 0) {
+  if (syscall(__NR_finit_module, fd, args, 0) < 0) {
+    ret = -errno;
     PLOG(ERROR) << "finit_module return: " << ret;
   }
 
+  close(fd);
+
   return ret;
 }
 
@@ -76,6 +82,12 @@
   int ret = -1;
   int maxtry = 10;
 
+  std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
+  if (!powerCtl.empty()) {
+    PLOG(ERROR) << powerCtl<<" :skipping rmmod";
+    return ret;
+  }
+
   while (maxtry-- > 0) {
     ret = delete_module(modname, O_NONBLOCK | O_EXCL);
     if (ret < 0 && errno == EAGAIN)
@@ -94,8 +106,22 @@
   int len;
   int fd;
   int ret = 0;
+  struct timespec req;
+  req.tv_sec = 0;
+  req.tv_nsec = kDriverStateAccessRetrySleepMillis * 1000000L;
+  int count = 5; /* wait at most 1 second for completion. */
 
   if (!state) return -1;
+  do {
+    if (access(WIFI_DRIVER_STATE_CTRL_PARAM, R_OK|W_OK) == 0)
+      break;
+    nanosleep(&req, (struct timespec *)NULL);
+  } while (--count > 0);
+  if (count == 0) {
+    PLOG(ERROR) << "Failed to access driver state control param "
+                << strerror(errno) << ", " << errno;
+    return -1;
+  }
   fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
   if (fd < 0) {
     PLOG(ERROR) << "Failed to open driver state control param";
@@ -164,7 +190,25 @@
     return 0;
   }
 
-  if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
+  /*
+   * Sometimes the wifi HAL can get into a state where the module is already
+   * loaded in a broken state and the wifi HAL isn't aware of this. In this
+   * case try unloading and reloading the kernel module.
+   */
+  int err = insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG);
+  if (err == -EEXIST) {
+    if (rmmod(DRIVER_MODULE_NAME) != 0) {
+      LOG(ERROR) << "After module load failure tried rmmod but failed.";
+      return -1;
+    }
+    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) {
+      LOG(ERROR) << "After module load failure tried rmmod and insmod but failed.";
+      return -1;
+    }
+    LOG(INFO) << "After module load failure tried rmmod and insmod and succeeded.";
+  } else if (err < 0) {
+    return -1;
+  }
 #endif
 
 #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
diff --git a/libwifi_system/Android.bp b/libwifi_system/Android.bp
index a3aa703..03e5836 100644
--- a/libwifi_system/Android.bp
+++ b/libwifi_system/Android.bp
@@ -42,6 +42,7 @@
     srcs: [
         "hostapd_manager.cpp",
         "supplicant_manager.cpp",
+        "wifi_fst.cpp",
     ],
 }
 
diff --git a/libwifi_system/hostapd_manager.cpp b/libwifi_system/hostapd_manager.cpp
index 3f2e27f..159ab6f 100644
--- a/libwifi_system/hostapd_manager.cpp
+++ b/libwifi_system/hostapd_manager.cpp
@@ -18,14 +18,36 @@
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
+#include "wifi_fst.h"
 
 namespace android {
 namespace wifi_system {
 const char kHostapdServiceName[] = "hostapd";
+const char kHostapdFSTServiceName[] = "hostapd_fst";
+const char kHostapdFullServiceName[] = "init.svc.hostapd";
+const char kHostapdFSTFullServiceName[] = "init.svc.hostapd_fst";
 
 bool HostapdManager::StartHostapd() {
-  if (property_set("ctl.start", kHostapdServiceName) != 0) {
+
+  // Check if hostapd already started
+  char hostapd_status[PROPERTY_VALUE_MAX];
+  property_get(is_fst_softap_enabled() ? kHostapdFSTFullServiceName :
+    kHostapdFullServiceName, hostapd_status, "");
+
+  if (strcmp(hostapd_status, "running") == 0) {
+    LOG(DEBUG) << "SoftAP already started. Skip another start";
+    return true;
+  }
+
+  if (wifi_start_fstman(1)) {
+    return false;
+  }
+
+  if (property_set("ctl.start",
+                   is_fst_softap_enabled() ?
+                     kHostapdFSTServiceName : kHostapdServiceName) != 0) {
     LOG(ERROR) << "Failed to start SoftAP";
+    wifi_stop_fstman(1);
     return false;
   }
 
@@ -36,11 +58,26 @@
 bool HostapdManager::StopHostapd() {
   LOG(DEBUG) << "Stopping the SoftAP service...";
 
-  if (property_set("ctl.stop", kHostapdServiceName) < 0) {
+  // Check if hostapd already stopped
+  char hostapd_status[PROPERTY_VALUE_MAX];
+  property_get(is_fst_softap_enabled() ? kHostapdFSTFullServiceName :
+    kHostapdFullServiceName, hostapd_status, "");
+
+  if (!strlen(hostapd_status) || strcmp(hostapd_status, "stopped") == 0) {
+    LOG(DEBUG) << "SoftAP already stopped. Skip another stop";
+    wifi_stop_fstman(1);
+    return true;
+  }
+
+  if (property_set("ctl.stop",
+                   is_fst_softap_enabled() ?
+                     kHostapdFSTServiceName : kHostapdServiceName) < 0) {
     LOG(ERROR) << "Failed to stop hostapd service!";
+    wifi_stop_fstman(1);
     return false;
   }
 
+  wifi_stop_fstman(1);
   LOG(DEBUG) << "SoftAP stopped successfully";
   return true;
 }
diff --git a/libwifi_system/supplicant_manager.cpp b/libwifi_system/supplicant_manager.cpp
index 60720d4..064256d 100644
--- a/libwifi_system/supplicant_manager.cpp
+++ b/libwifi_system/supplicant_manager.cpp
@@ -28,12 +28,15 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
+#include "wifi_fst.h"
+
 namespace android {
 namespace wifi_system {
 namespace {
 
 const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";
 const char kSupplicantServiceName[] = "wpa_supplicant";
+const char kMigrationServiceName[] = "vendor.move_wifi_data";
 
 }  // namespace
 
@@ -43,6 +46,10 @@
   const prop_info* pi;
   unsigned serial = 0;
 
+  if (wifi_start_fstman(0)) {
+    return -1;
+  }
+
   /* Check whether already running */
   if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
       strcmp(supp_status, "running") == 0) {
@@ -61,6 +68,7 @@
     serial = __system_property_serial(pi);
   }
 
+  property_set("ctl.start", kMigrationServiceName);
   property_set("ctl.start", kSupplicantServiceName);
   sched_yield();
 
@@ -78,12 +86,14 @@
         if (strcmp(supp_status, "running") == 0) {
           return true;
         } else if (strcmp(supp_status, "stopped") == 0) {
+          wifi_stop_fstman(0);
           return false;
         }
       }
     }
     usleep(100000);
   }
+  wifi_stop_fstman(0);
   return false;
 }
 
@@ -94,19 +104,25 @@
   /* Check whether supplicant already stopped */
   if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
       strcmp(supp_status, "stopped") == 0) {
+    wifi_stop_fstman(0);
     return true;
   }
 
+  property_set("ctl.stop", kMigrationServiceName);
   property_set("ctl.stop", kSupplicantServiceName);
   sched_yield();
 
   while (count-- > 0) {
     if (property_get(kSupplicantInitProperty, supp_status, NULL)) {
-      if (strcmp(supp_status, "stopped") == 0) return true;
+      if (strcmp(supp_status, "stopped") == 0) {
+        wifi_stop_fstman(0);
+        return true;
+      }
     }
     usleep(100000);
   }
   LOG(ERROR) << "Failed to stop supplicant";
+  wifi_stop_fstman(0);
   return false;
 }
 
diff --git a/libwifi_system/wifi_fst.cpp b/libwifi_system/wifi_fst.cpp
new file mode 100644
index 0000000..e3def4d
--- /dev/null
+++ b/libwifi_system/wifi_fst.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution.
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <android-base/logging.h>
+#define LOG_TAG "WifiFST"
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include "cutils/properties.h"
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+#include <private/android_filesystem_config.h>
+
+using android::base::StringPrintf;
+using android::base::WriteStringToFile;
+using std::string;
+
+static const char FSTMAN_IFNAME[] = "wlan0";
+static const char FSTMAN_NAME[] = "fstman";
+static const char FST_RATE_UPGRADE_ENABLED_PROP_NAME[] = "persist.vendor.fst.rate.upgrade.en";
+static const char FST_SOFTAP_ENABLED_PROP_NAME[] = "persist.vendor.fst.softap.en";
+
+namespace android {
+namespace wifi_system {
+
+int is_fst_enabled()
+{
+    char prop_value[PROPERTY_VALUE_MAX] = { '\0' };
+
+    if (property_get(FST_RATE_UPGRADE_ENABLED_PROP_NAME, prop_value, NULL) &&
+        strcmp(prop_value, "1") == 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+int is_fst_softap_enabled() {
+    char prop_value[PROPERTY_VALUE_MAX] = { '\0' };
+
+    if (is_fst_enabled() &&
+        property_get(FST_SOFTAP_ENABLED_PROP_NAME, prop_value, NULL) &&
+        strcmp(prop_value, "1") == 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void get_fstman_props(int softap_mode,
+			     char *fstman_svc_name, int fstman_svc_name_len,
+			     char *fstman_init_prop, int fstman_init_prop_len)
+{
+    if (softap_mode)
+        strlcpy(fstman_svc_name, FSTMAN_NAME, fstman_svc_name_len);
+    else
+        snprintf(fstman_svc_name, fstman_svc_name_len, "%s_%s",
+                 FSTMAN_NAME, FSTMAN_IFNAME);
+    snprintf(fstman_init_prop, fstman_init_prop_len, "init.svc.%s",
+             fstman_svc_name);
+}
+
+int wifi_start_fstman(int softap_mode)
+{
+    char fstman_status[PROPERTY_VALUE_MAX] = { '\0' };
+    char fstman_svc_name[PROPERTY_VALUE_MAX] = { '\0' };
+    char fstman_init_prop[PROPERTY_VALUE_MAX] = { '\0' };
+    int count = 50; /* wait at most 5 seconds for completion */
+
+    if (!is_fst_enabled() ||
+        (softap_mode && !is_fst_softap_enabled())) {
+        return 0;
+    }
+
+    get_fstman_props(softap_mode, fstman_svc_name, sizeof(fstman_svc_name),
+                     fstman_init_prop, sizeof(fstman_init_prop));
+
+    /* Check whether already running */
+    if (property_get(fstman_init_prop, fstman_status, NULL) &&
+        strcmp(fstman_status, "running") == 0)
+        return 0;
+
+    LOG(DEBUG) << "Starting FST Manager";
+    property_set("ctl.start", fstman_svc_name);
+    sched_yield();
+
+    while (count-- > 0) {
+        if (property_get(fstman_init_prop, fstman_status, NULL) &&
+            strcmp(fstman_status, "running") == 0)
+                return 0;
+        usleep(100000);
+    }
+
+    LOG(ERROR) << "Failed to start FST Manager";
+    return -1;
+}
+
+int wifi_stop_fstman(int softap_mode)
+{
+    char fstman_status[PROPERTY_VALUE_MAX] = { '\0' };
+    char fstman_svc_name[PROPERTY_VALUE_MAX] = { '\0' };
+    char fstman_init_prop[PROPERTY_VALUE_MAX] = { '\0' };
+    int count = 50; /* wait at most 5 seconds for completion */
+
+    if (!is_fst_enabled() ||
+        (softap_mode && !is_fst_softap_enabled())) {
+        return 0;
+    }
+
+    get_fstman_props(softap_mode, fstman_svc_name, sizeof(fstman_svc_name),
+                     fstman_init_prop, sizeof(fstman_init_prop));
+
+    /* Check whether already stopped */
+    if (property_get(fstman_init_prop, fstman_status, NULL) &&
+        strcmp(fstman_status, "stopped") == 0)
+        return 0;
+
+    LOG(DEBUG) << "Stopping FST Manager";
+    property_set("ctl.stop", fstman_svc_name);
+    sched_yield();
+
+    while (count-- > 0) {
+        if (property_get(fstman_init_prop, fstman_status, NULL) &&
+            strcmp(fstman_status, "stopped") == 0)
+                return 0;
+        usleep(100000);
+    }
+
+    LOG(ERROR) << "Failed to stop fstman";
+    return -1;
+}
+
+}  // namespace wifi_system
+}  // namespace android
diff --git a/libwifi_system/wifi_fst.h b/libwifi_system/wifi_fst.h
new file mode 100644
index 0000000..7ff6daa
--- /dev/null
+++ b/libwifi_system/wifi_fst.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution.
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIFI_FST_H
+#define _WIFI_FST_H
+
+namespace android {
+namespace wifi_system {
+
+/**
+ * returns whether FST is enabled or not according to
+ * persist.vendor.fst.rate.upgrade.en system property
+ *
+ * @return 1 if FST enabled.
+ */
+int is_fst_enabled();
+
+/**
+* returns whether FST Soft AP is enabled or not according to
+* persist.vendor.fst.softap.en system property
+*
+* @return 1 if FST Soft AP enabled.
+*/
+int is_fst_softap_enabled();
+
+/**
+ * Start FST Manager.
+ *
+ * @return 0 on success, < 0 on failure.
+ */
+int wifi_start_fstman(int softap_mode);
+
+/**
+ * Stop FST Manager.
+ *
+ * @return 0 on success, < 0 on failure.
+ */
+int wifi_stop_fstman(int softap_mode);
+
+}  // namespace wifi_system
+}  // namespace android
+
+#endif  // _WIFI_FST_H
diff --git a/service/Android.bp b/service/Android.bp
index 71cf728..07befdf 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -81,6 +81,12 @@
         "android.hardware.wifi.supplicant-V1.2-java",
         "android.hardware.wifi.supplicant-V1.3-java",
         "android.hidl.manager-V1.2-java",
+        "vendor.qti.hardware.wifi.hostapd-V1.0-java",
+        "vendor.qti.hardware.wifi.hostapd-V1.1-java",
+        "vendor.qti.hardware.wifi.hostapd-V1.2-java",
+        "vendor.qti.hardware.wifi.supplicant-V2.0-java",
+        "vendor.qti.hardware.wifi.supplicant-V2.1-java",
+        "vendor.qti.hardware.wifi.supplicant-V2.2-java",
         "androidx.annotation_annotation",
         "bouncycastle-unbundled",
         "ksoap2",
diff --git a/service/AndroidManifest_Resources.xml b/service/AndroidManifest_Resources.xml
index 6d637cb..04ba1d3 100644
--- a/service/AndroidManifest_Resources.xml
+++ b/service/AndroidManifest_Resources.xml
@@ -22,6 +22,7 @@
           coreApp="true"
           android:versionCode="1"
           android:versionName="R-initial">
+    <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_CLICKED" />
     <application
         android:label="@string/wifiResourcesAppLabel"
         android:defaultToDeviceProtectedStorage="true"
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index cf54e32..2b975916 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -18,7 +18,8 @@
 
 import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
 import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
-
+import static android.net.wifi.WifiManager.STA_PRIMARY;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -28,10 +29,14 @@
 import android.net.wifi.SoftApCapability;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiManager;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
 import android.os.BatteryStatsManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -42,6 +47,7 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 import com.android.server.wifi.util.WifiPermissionsUtil;
+import com.android.internal.util.AsyncChannel;
 import com.android.wifi.resources.R;
 
 import java.io.FileDescriptor;
@@ -76,6 +82,7 @@
 
     private WifiManager.SoftApCallback mSoftApCallback;
     private WifiManager.SoftApCallback mLohsCallback;
+    private QtiClientModeManager.Listener mQtiClientModeCallback;
 
     private boolean mCanRequestMoreClientModeManagers = false;
     private boolean mCanRequestMoreSoftApManagers = false;
@@ -96,6 +103,13 @@
         mLohsCallback = callback;
     }
 
+    /**
+     * Called from WifiServiceImpl to register a callback for notification from QtiClientModeManager
+     */
+    public void registerQtiClientModeCallback(@NonNull QtiClientModeManager.Listener callback) {
+       mQtiClientModeCallback = callback;
+    }
+
     ActiveModeWarden(WifiInjector wifiInjector,
                      Looper looper,
                      WifiNative wifiNative,
@@ -180,6 +194,13 @@
         return mWifiNative.isStaApConcurrencySupported();
     }
 
+    /**
+     * @return Returns whether the device can support two client mode managers
+     */
+    public boolean isDualStaSupported() {
+        return mWifiNative.isDualStaSupported();
+    }
+
     /** Begin listening to broadcasts and start the internal state machine. */
     public void start() {
         mWifiController.start();
@@ -199,9 +220,14 @@
     }
 
     /** Wifi has been toggled. */
+    public void qtiWifiToggled(int staId, boolean enable) {
+        mWifiController.sendMessage(WifiController.CMD_ADD_WIFI_SET, staId, enable ? 1 : 0);
+    }
+
     public void wifiToggled() {
         mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);
-    }
+	}
+
 
     /** Airplane Mode has been toggled. */
     public void airplaneModeToggled() {
@@ -388,6 +414,7 @@
         listener.setActiveModeManager(manager);
         manager.start();
         if (!switchClientModeManagerRole(manager)) {
+            manager.stop();
             return false;
         }
         mActiveModeManagers.add(manager);
@@ -399,6 +426,7 @@
      */
     private void stopAllClientModeManagers() {
         Log.d(TAG, "Shutting down all client mode managers");
+        disableStation(0);
         for (ActiveModeManager manager : mActiveModeManagers) {
             if (!(manager instanceof ClientModeManager)) continue;
             ClientModeManager clientModeManager = (ClientModeManager) manager;
@@ -444,6 +472,7 @@
      */
     private void shutdownWifi() {
         Log.d(TAG, "Shutting down all mode managers");
+        disableStation(0);
         for (ActiveModeManager manager : mActiveModeManagers) {
             manager.stop();
         }
@@ -595,6 +624,7 @@
      */
     private class WifiController extends StateMachine {
         private static final String TAG = "WifiController";
+        private boolean mWifiControllerReady = false;
 
         // Maximum limit to use for timeout delay if the value from overlay setting is too large.
         private static final int MAX_RECOVERY_TIMEOUT_DELAY_MS = 4000;
@@ -621,10 +651,13 @@
         static final int CMD_AP_START_FAILURE                       = BASE + 23;
         static final int CMD_UPDATE_AP_CAPABILITY                   = BASE + 24;
         static final int CMD_UPDATE_AP_CONFIG                       = BASE + 25;
+        static final int CMD_ADD_WIFI_SET                           = BASE + 31;
 
         private final EnabledState mEnabledState = new EnabledState();
         private final DisabledState mDisabledState = new DisabledState();
 
+        private WifiApConfigStore mWifiApConfigStore;
+
         private boolean mIsInEmergencyCall = false;
         private boolean mIsInEmergencyCallbackMode = false;
 
@@ -649,6 +682,10 @@
             boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
             boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();
 
+            // Due to cyclic dependency of ActiveModeWarden and WifiApConfigStore, fetch
+            // WifiConfigStore object later during WifiController.start().
+            mWifiApConfigStore = mWifiInjector.getWifiApConfigStore();
+
             log("isAirplaneModeOn = " + isAirplaneModeOn
                     + ", isWifiEnabled = " + isWifiEnabled
                     + ", isScanningAvailable = " + isScanningAlwaysAvailable
@@ -706,8 +743,7 @@
 
             private void exitEmergencyMode() {
                 if (shouldEnableSta()) {
-                    startClientModeManager();
-                    transitionTo(mEnabledState);
+                    sendMessage(obtainMessage(CMD_WIFI_TOGGLED));
                 } else {
                     transitionTo(mDisabledState);
                 }
@@ -746,6 +782,12 @@
         }
 
         class DefaultState extends State {
+
+            @Override
+            public void enter() {
+                mWifiControllerReady = true;
+            }
+
             @Override
             public boolean processMessage(Message msg) {
                 switch (msg.what) {
@@ -753,11 +795,10 @@
                     case CMD_WIFI_TOGGLED:
                     case CMD_STA_STOPPED:
                     case CMD_STA_START_FAILURE:
-                    case CMD_AP_STOPPED:
-                    case CMD_AP_START_FAILURE:
                     case CMD_RECOVERY_RESTART_WIFI:
                     case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
                     case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
+                    case CMD_ADD_WIFI_SET:
                         break;
                     case CMD_RECOVERY_DISABLE_WIFI:
                         log("Recovery has been throttled, disable wifi");
@@ -784,6 +825,15 @@
                     case CMD_UPDATE_AP_CONFIG:
                         updateConfigurationToSoftApModeManager((SoftApConfiguration) msg.obj);
                         break;
+                    case CMD_AP_STOPPED:
+                    case CMD_AP_START_FAILURE:
+                        // Softap Start Failure (for Dual SAP) arrives in Disabled State.
+                        log("Softap mode disabled, determine next state");
+                        if (shouldEnableSta()) {
+                            startClientModeManager();
+                            transitionTo(mEnabledState);
+                        }
+                        break;
                     default:
                         throw new RuntimeException("WifiController.handleMessage " + msg.what);
                 }
@@ -799,6 +849,7 @@
             @Override
             public void enter() {
                 log("DisabledState.enter()");
+                mWifiControllerReady = true;
                 super.enter();
                 if (hasAnyModeManager()) {
                     Log.e(TAG, "Entered DisabledState, but has active mode managers");
@@ -887,8 +938,20 @@
                             stopAllClientModeManagers();
                         }
                         break;
+                    case CMD_ADD_WIFI_SET:
+                        int staId = msg.arg1;
+                        int enable = msg.arg2;
+                        if (enable == 1)
+                            enableStation(staId);
+                        else
+                            disableStation(staId);
+                        break;
                     case CMD_SET_AP:
                         // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
+                        // If request is to start dual sap, turn off sta.
+                        if (msg.arg1 == 1 && mWifiApConfigStore.getDualSapStatus()) {
+                            stopAllClientModeManagers();
+                        }
                         if (msg.arg1 == 1) {
                             startSoftApModeManager((SoftApModeConfiguration) msg.obj);
                         } else {
@@ -929,6 +992,7 @@
                         } else {
                             log("AP disabled, remain in EnabledState.");
                         }
+                        stopSoftApModeManagers(WifiManager.IFACE_IP_MODE_UNSPECIFIED);
                         break;
                     case CMD_STA_START_FAILURE:
                     case CMD_STA_STOPPED:
@@ -966,4 +1030,126 @@
             }
         }
     }
+    private class WifiCallback extends ModeCallback implements QtiClientModeManager.Listener {
+        @Override
+        public void onStateChanged(int staId, int newState) {
+            if (newState == WifiManager.WIFI_STATE_UNKNOWN
+                || newState == WifiManager.WIFI_STATE_DISABLED) {
+                mActiveModeManagers.remove(getActiveModeManager());
+            }
+            if (mQtiClientModeCallback != null) {
+                mQtiClientModeCallback.onStateChanged(staId, newState);
+            } else {
+                Log.d(TAG, "QtiClientModeCallback is null. Dropping onStateChanged event.");
+            }
+        }
+
+        @Override
+        public void onRssiChanged(int staId, int rssi) {
+            if (mQtiClientModeCallback != null) {
+                mQtiClientModeCallback.onRssiChanged(staId, rssi);
+            } else {
+                Log.d(TAG, "QtiClientModeCallback is null. Dropping onRssiChanged event.");
+            }
+        }
+
+        @Override
+        public void onLinkConfigurationChanged(int staId, LinkProperties lp) {
+            if (mQtiClientModeCallback != null) {
+                mQtiClientModeCallback.onLinkConfigurationChanged(staId, lp);
+            } else {
+                Log.d(TAG, "QtiClientModeCallback is null. Dropping onLinkConfigurationChanged event.");
+            }
+        }
+
+        @Override
+        public void onNetworkStateChanged(int staId, NetworkInfo netInfo) {
+            if (mQtiClientModeCallback != null) {
+                mQtiClientModeCallback.onNetworkStateChanged(staId, netInfo);
+            } else {
+                Log.d(TAG, "QtiClientModeCallback is null. Dropping onNetworkStateChanged event.");
+            }
+        }
+    }
+
+    private QtiClientModeManager getQtiClientModeManager(int staId) {
+        for (ActiveModeManager manager : mActiveModeManagers) {
+            if (!(manager instanceof QtiClientModeManager)) {
+                continue;
+            }
+            QtiClientModeManager qtiClientManager = (QtiClientModeManager) manager;
+            if (qtiClientManager != null) {
+                return qtiClientManager;
+            }
+        }
+        return null;
+    }
+
+    public void enableStation(int staId) {
+        mHandler.post(() -> {
+            Log.d(TAG, "[wifi" + staId +  "] Starting Wi-fi");
+            if (getQtiClientModeManager(staId) == null) {
+                WifiCallback callback = new WifiCallback();
+                ActiveModeManager manager =
+                    mWifiInjector.makeQtiClientModeManager(callback);
+                callback.setActiveModeManager(manager);
+                manager.start();
+                manager.setRole(ActiveModeManager.ROLE_CLIENT_SECONDARY);
+                mActiveModeManagers.add(manager);
+            } else {
+                Log.i(TAG, "[wifi" + staId +  "] is already started.");
+            }
+        });
+    }
+
+    public void disableStation(int staId) {
+        mHandler.post(() -> {
+            Log.d(TAG, "[wifi" + staId +  "] Disable Wi-fi");
+            if (staId == 0 /* disable all */) {
+                for (ActiveModeManager manager : mActiveModeManagers) {
+                    if (!(manager instanceof QtiClientModeManager)) {
+                        continue;
+                    }
+                    if (manager != null) {
+                        manager.stop();
+                        mActiveModeManagers.remove(manager);
+                    }
+                }
+            } else {
+                QtiClientModeManager manager = getQtiClientModeManager(staId);
+                if (manager != null) {
+                    manager.stop();
+                    mActiveModeManagers.remove(manager);
+                } else {
+                    Log.i(TAG, "[wifi" + staId +  "] is already stopped.");
+                }
+            }
+        });
+    }
+
+    public QtiClientModeImpl getQtiClientModeImpl(int staId) {
+        QtiClientModeManager manager = getQtiClientModeManager(staId);
+        if (manager != null) {
+            return manager.getClientModeImpl();
+        }
+        return null;
+    }
+
+    public AsyncChannel getQtiClientImplChannel(int staId) {
+        QtiClientModeManager manager = getQtiClientModeManager(staId);
+        if (manager != null) {
+            return manager.getClientImplChannel();
+        }
+        return null;
+    }
+
+    public void enableVerboseLogging(int verbose) {
+        for (ActiveModeManager manager : mActiveModeManagers) {
+            if (!(manager instanceof QtiClientModeManager)) {
+                continue;
+            }
+            QtiClientModeManager qtiClientManager = (QtiClientModeManager) manager;
+            qtiClientManager.getClientModeImpl().enableVerboseLogging(verbose);
+        }
+    }
 }
diff --git a/service/java/com/android/server/wifi/AutoConnectNewNetworkResultNotifier.java b/service/java/com/android/server/wifi/AutoConnectNewNetworkResultNotifier.java
new file mode 100644
index 0000000..d1ebca6
--- /dev/null
+++ b/service/java/com/android/server/wifi/AutoConnectNewNetworkResultNotifier.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server.wifi;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.provider.Settings;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.server.wifi.util.NativeUtil;
+
+/**
+ * Responsible for notifying user for linked network connection attempt result.
+ */
+public class AutoConnectNewNetworkResultNotifier {
+    // Number of milliseconds to wait before automatically dismiss the notification.
+    private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000;
+
+    // Unique ID associated with the notification.
+    @VisibleForTesting
+    public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_SSID_BRIDGING_AUTO_CONNECTION_RESULT;
+
+    private final WifiContext mContext;
+    private final NotificationManager mNotificationManager;
+    private final FrameworkFacade mFrameworkFacade;
+
+    public AutoConnectNewNetworkResultNotifier(WifiContext context, FrameworkFacade frameworkFacade) {
+        mContext = context;
+        mFrameworkFacade = frameworkFacade;
+        mNotificationManager =
+                mContext.getSystemService(NotificationManager.class);
+    }
+
+    /**
+     * Invoked when a wrong password error for a Wi-Fi network is detected.
+     *
+     * @param ssid The SSID of the Wi-Fi network
+     */
+    public void onWrongPasswordError(String ssid) {
+        showNotification(ssid, false);
+    }
+
+    /**
+     * Invoked when attempting a new Wi-Fi network connection is success.
+     */
+    public void onConnectionAttemptSuccess(String ssid) {
+        showNotification(ssid, true);
+    }
+
+    /**
+     * Display network connection attempt result notification for a given Wi-Fi network (specified by its SSID).
+     *
+     * @param ssid SSID of the Wi-FI network
+     */
+    private void showNotification(String ssid, boolean success) {
+        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
+        intent.putExtra("wifi_auto_connect_new_network_result", NativeUtil.removeEnclosingQuotes(ssid));
+        Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
+                WifiService.NOTIFICATION_NETWORK_ALERTS)
+                .setAutoCancel(true)
+                .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS)
+                .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
+                        com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range))
+                .setContentTitle(success ? "Successfully connected new network" : "Failed to connect new network")
+                .setContentText(ssid)
+                .setContentIntent(mFrameworkFacade.getActivity(
+                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
+                .setColor(mContext.getResources().getColor(
+                        android.R.color.system_notification_accent_color));
+        mNotificationManager.notify(NOTIFICATION_ID, builder.build());
+    }
+
+    /**
+     * Dismiss the notification that was generated by {@link #showNotification}. The notification
+     * might have already been dismissed, either by user or timeout. We'll attempt to dismiss it
+     * regardless if it is been dismissed or not, to reduce code complexity.
+     */
+    private void dismissNotification() {
+        // Notification might have already been dismissed, either by user or timeout. It is
+        // still okay to cancel it if already dismissed.
+        mNotificationManager.cancel(null, NOTIFICATION_ID);
+    }
+}
diff --git a/service/java/com/android/server/wifi/BaseWifiService.java b/service/java/com/android/server/wifi/BaseWifiService.java
index 7614cf6..d6c35b8 100644
--- a/service/java/com/android/server/wifi/BaseWifiService.java
+++ b/service/java/com/android/server/wifi/BaseWifiService.java
@@ -30,11 +30,13 @@
 import android.net.wifi.ISuggestionConnectionStatusListener;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
+import android.net.wifi.IWifiNotificationCallback;
 import android.net.wifi.IWifiConnectedNetworkScorer;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.ScanResult;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiDppConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkSuggestion;
@@ -182,6 +184,11 @@
     }
 
     @Override
+    public void allowConnectOnPartialScanResults(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void allowAutojoin(int netId, boolean choice) {
         throw new UnsupportedOperationException();
     }
@@ -551,6 +558,11 @@
     }
 
     @Override
+    public void enableWifiCoverageExtendFeature(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void stopDppSession() throws RemoteException {
         throw new UnsupportedOperationException();
     }
@@ -677,4 +689,171 @@
     public boolean isAutoWakeupEnabled() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public boolean isWifiCoverageExtendFeatureEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isExtendingWifi() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSoftApOcvFeatureEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSoftApOcvFeatureSupported() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableSoftApOcvFeature(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSoftApBeaconProtFeatureEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSoftApBeaconProtFeatureSupported() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int isConcurrentBandSupported(){
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableSoftApBeaconProtFeature(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getCapabilities(String capaType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppAddBootstrapQrCode(String uri) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppBootstrapGenerate(WifiDppConfig config) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String dppGetUri(int bootstrap_id) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppBootstrapRemove(int bootstrap_id) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppListen(String frequency, int dpp_role, boolean qr_mutual, boolean netrole_ap) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void dppStopListen() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppConfiguratorAdd(String curve, String key, int expiry) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppConfiguratorRemove(int config_id) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int dppStartAuth(WifiDppConfig config) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String dppConfiguratorGetKey(int id) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getSoftApWifiStandard() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isVht8ssCapableDevice() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String doDriverCmd(String command) {
+        throw new UnsupportedOperationException();
+    }
+
+    /* QTI Vendor Dual STA support APIs */
+
+    @Override
+    public boolean setWifiEnabled2(String packageName, int staId, boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean disconnect2(int staId, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WifiInfo getConnectionInfo2(int staId, String callingPackage, String callingFeatureId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ParceledListSlice getConfiguredNetworks2(int staId, String packageName, String callingFeatureId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void registerForWifiNotification(int staId, IBinder binder, IWifiNotificationCallback callback, int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterForWifiNotification(int staId, int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isWhitelistNetworkRoamingEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableWhitelistNetworkRoaming(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isNewNetworkAutoConnectionEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableNewNetworkAutoConnection(boolean enable) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
index dffd774..98570bf 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,
@@ -630,4 +742,58 @@
             return sb.toString();
         }
     }
+
+    /**
+     * Sends the Blocklisted BSSIDs and Whitelisted SSIDs belonging to the input SSID
+     * down to the firmware
+     * to those BSSIDs.
+     * @param ssid
+     * @param ssidWhitelist
+     */
+    public void updateFirmwareRoamingConfiguration(@NonNull String ssid, @NonNull ArrayList<String> ssidWhitelist) {
+        if (!mConnectivityHelper.isFirmwareRoamingSupported()) {
+            return;
+        }
+        ArrayList<String> bssidBlocklist = updateAndGetBssidBlocklistInternal()
+                .filter(entry -> ssid.equals(entry.ssid))
+                .sorted((o1, o2) -> (int) (o2.blocklistEndTimeMs - o1.blocklistEndTimeMs))
+                .map(entry -> entry.bssid)
+                .collect(Collectors.toCollection(ArrayList::new));
+        int fwMaxBlocklistSize = mConnectivityHelper.getMaxNumBlacklistBssid();
+        if (fwMaxBlocklistSize <= 0) {
+            Log.e(TAG, "Invalid max BSSID blocklist size:  " + fwMaxBlocklistSize);
+            return;
+        }
+        // Having the blocklist size exceeding firmware max limit is unlikely because we have
+        // already flitered based on SSID. But just in case this happens, we are prioritizing
+        // sending down BSSIDs blocked for the longest time.
+        if (bssidBlocklist.size() > fwMaxBlocklistSize) {
+            bssidBlocklist = new ArrayList<String>(bssidBlocklist.subList(0,
+                    fwMaxBlocklistSize));
+        }
+
+        int maxWhitelistSize = mConnectivityHelper.getMaxNumWhitelistSsid();
+        if (maxWhitelistSize <= 0) {
+            Log.wtf(TAG, "Invalid max SSID whitelist size:  " + maxWhitelistSize);
+            return;
+        }
+
+        int whitelistSize = ssidWhitelist.size();
+
+        if (whitelistSize > maxWhitelistSize) {
+            Log.wtf(TAG, "Attempt to write " + whitelistSize + " whitelisted SSIDs, max size is "
+                    + maxWhitelistSize);
+
+            ssidWhitelist = new ArrayList<String>(ssidWhitelist.subList(0,
+                    maxWhitelistSize));
+            localLog("Trim down SSID whitelist size from " + whitelistSize + " to "
+                    + ssidWhitelist.size());
+        }
+
+        // plumb down to HAL
+        if (!mConnectivityHelper.setFirmwareRoamingConfiguration(bssidBlocklist,
+                ssidWhitelist)) {  // TODO(b/36488259): SSID whitelist management.
+        }
+    }
+
 }
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 6c31185..e2f895b 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -26,7 +26,12 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
+
+import static android.net.wifi.WifiManager.STA_PRIMARY;
 import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WHITELIST_ROAMING_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.HW_SUPPORTED_FEATURES;
+
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -55,6 +60,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkProvider;
+import android.net.RouteInfo;
 import android.net.SocketKeepalive;
 import android.net.StaticIpConfiguration;
 import android.net.TcpKeepalivePacketData;
@@ -84,6 +90,8 @@
 import android.net.wifi.nl80211.DeviceWiphyCapabilities;
 import android.net.wifi.nl80211.WifiNl80211Manager;
 import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.WifiDppConfig;
+import android.net.wifi.WifiDppConfig.DppResult;
 import android.os.BatteryStatsManager;
 import android.os.Bundle;
 import android.os.ConditionVariable;
@@ -94,9 +102,11 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
+import android.os.SystemProperties;
 import android.provider.Settings;
 import android.system.OsConstants;
 import android.telephony.SubscriptionManager;
@@ -133,6 +143,7 @@
 import com.android.server.wifi.util.ScanResultUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
+import com.android.server.wifi.WifiNative.WifiGenerationStatus;
 import com.android.wifi.resources.R;
 
 import java.io.BufferedReader;
@@ -149,10 +160,12 @@
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.nio.ByteBuffer;
 
 /**
  * Implementation of ClientMode.  Event handling for Client mode logic is done here,
@@ -221,6 +234,7 @@
     private final BssidBlocklistMonitor mBssidBlocklistMonitor;
     private ConnectivityManager mCm;
     private BaseWifiDiagnostics mWifiDiagnostics;
+    private WifiTrafficPoller mTrafficPoller;
     private final boolean mP2pSupported;
     private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
     private boolean mTemporarilyDisconnectWifi = false;
@@ -247,6 +261,8 @@
     private boolean mScreenOn = false;
 
     private String mInterfaceName;
+    /* The interface for ipClient */
+    private String mDataInterfaceName;
 
     private int mLastSignalLevel = -1;
     private String mLastBssid;
@@ -254,9 +270,14 @@
     // The subId used by WifiConfiguration with SIM credential which was connected successfully
     private int mLastSubId;
     private String mLastSimBasedConnectionCarrierName;
+    private String mConcurrentBand = null;
 
     private boolean mIpReachabilityDisconnectEnabled = true;
 
+    /* if set to true then disconnect due to IP Reachability lost only when obtained for the first 10 seconds of L2 connection */
+    private boolean mDisconnectOnlyOnInitialIpReachability = true;
+    private boolean mIpReachabilityMonitorActive = true;
+
     private void processRssiThreshold(byte curRssi, int reason,
             WifiNative.WifiRssiEventHandler rssiHandler) {
         if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) {
@@ -359,6 +380,11 @@
     // wifi connects or fails to connect
     private boolean mIsAutoRoaming = false;
 
+
+    // Indicates that driver is attempting to whitelit roam, set true on whitelist roam BSSID
+    // associated, set false when wifi connects or fails to connect
+    private boolean mIsWhitelistRoaming = false;
+
     // Roaming failure count
     private int mRoamFailCount = 0;
 
@@ -621,7 +647,6 @@
     static final int CMD_PRE_DHCP_ACTION                                = BASE + 255;
     private static final int CMD_PRE_DHCP_ACTION_COMPLETE               = BASE + 256;
     private static final int CMD_POST_DHCP_ACTION                       = BASE + 257;
-
     private static final int CMD_CONNECT_NETWORK                        = BASE + 258;
     private static final int CMD_SAVE_NETWORK                           = BASE + 259;
 
@@ -630,6 +655,34 @@
 
     private static final int CMD_GET_CURRENT_NETWORK                    = BASE + 263;
 
+    /* Take some GAP in numbering, start DPP commands from 301 onwards */
+    /* Add bootstrap info*/
+    public static final int CMD_DPP_GENERATE_BOOTSTRAP                  = BASE + 301;
+    /* Generate QRCODE bootstrap info*/
+    public static final int CMD_DPP_ADD_BOOTSTRAP_QRCODE                = BASE + 302;
+    /* Remove bootstrap info */
+    public static final int CMD_DPP_REMOVE_BOOTSTRAP                    = BASE + 303;
+    /* Get bootstrap URI*/
+    public static final int CMD_DPP_GET_URI                             = BASE + 304;
+    /* Start DPP Listen*/
+    public static final int CMD_DPP_LISTEN_START                        = BASE + 305;
+    /* Stop ongoing DPP Listen*/
+    public static final int CMD_DPP_LISTEN_STOP                         = BASE + 306;
+    /* Add DPP Configuration */
+    public static final int CMD_DPP_CONF_ADD                            = BASE + 307;
+    /* Remove DPP Configuration */
+    public static final int CMD_DPP_CONF_REMOVE                         = BASE + 308;
+    /* Start DPP AUTH*/
+    public static final int CMD_DPP_AUTH_INIT                           = BASE + 309;
+    /* Get Private Key*/
+    public static final int CMD_DPP_CONFIGURATOR_GET_KEY                = BASE + 310;
+
+    /* Vendor specific cmd: To handle IP Reachability session */
+    private static final int CMD_IP_REACHABILITY_SESSION_END            = BASE + 311;
+
+    //Run Driver Command
+    private static final int CMD_DO_DRIVER_CMD                          = BASE + 312;
+
     // For message logging.
     private static final Class[] sMessageClasses = {
             AsyncChannel.class, ClientModeImpl.class };
@@ -734,6 +787,7 @@
     private final EapFailureNotifier mEapFailureNotifier;
     private final SimRequiredNotifier mSimRequiredNotifier;
     private final ConnectionFailureNotifier mConnectionFailureNotifier;
+    private final AutoConnectNewNetworkResultNotifier mAutoConnectNewNetworkResultNotifier;
     private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     // Maximum duration to continue to log Wifi usability stats after a data stall is triggered.
     @VisibleForTesting
@@ -797,6 +851,9 @@
         mConnectionFailureNotifier = mWifiInjector.makeConnectionFailureNotifier(
                 mWifiConnectivityManager);
 
+        mAutoConnectNewNetworkResultNotifier =
+                mWifiInjector.makeAutoConnectNewNetworkResultNotifier();
+
         mLinkProperties = new LinkProperties();
         mMcastLockManagerFilterController = new McastLockManagerFilterController();
         mActivityManager = context.getSystemService(ActivityManager.class);
@@ -811,7 +868,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)
@@ -864,6 +922,10 @@
 
         mWifiConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener());
 
+        mDisconnectOnlyOnInitialIpReachability = SystemProperties
+                .get("persist.vendor.wifi.enableIpReachabilityMonitorPeriod", "1")
+                .equals("1");
+
         // CHECKSTYLE:OFF IndentationCheck
         addState(mDefaultState);
             addState(mConnectModeState, mDefaultState);
@@ -909,8 +971,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,
@@ -935,6 +995,7 @@
                 mWifiMetrics.getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT,
                 mWifiMetrics.getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.DPP_EVENT, getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
                 mWifiInjector.getWifiLastResortWatchdog().getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT,
@@ -1074,8 +1135,19 @@
             }
             mIpClient.stop();
         }
-        mIpClientWithPreConnection = false;
-        mSentHLPs = false;
+	mIpClientWithPreConnection = false;
+	mSentHLPs = false;
+    }
+
+    public void setWifiDiagnostics(BaseWifiDiagnostics WifiDiagnostics) {
+        mWifiDiagnostics = WifiDiagnostics;
+    }
+
+    public void setTrafficPoller(WifiTrafficPoller trafficPoller) {
+        mTrafficPoller = trafficPoller;
+        if (mTrafficPoller != null) {
+            mTrafficPoller.setInterface(mDataInterfaceName);
+        }
     }
 
     private void stopDhcpSetup() {
@@ -1103,6 +1175,8 @@
             if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
                 // Disconnect and let autojoin reselect a new network
                 sendMessage(CMD_DISCONNECT);
+            } else {
+                updateWhitelistNetworksIfRequired(config);
             }
             mWifiNative.removeNetworkCachedData(config.networkId);
         }
@@ -1112,6 +1186,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) {
@@ -1203,6 +1281,51 @@
     }
 
     /**
+     * Enable/Disable SoftAp Ocv Feature
+     *
+     * @param enable true-enable; false-disable
+     */
+    public void enableSoftApOcvFeature(boolean enable) {
+        mWifiNative.enableSoftApOcvFeature(enable);
+    }
+
+    /**
+     * Enable/Disable SoftAp Beacon Protection
+     *
+     * @param enable true-enable; false-disable
+     */
+    public void enableSoftApBeaconProtFeature(boolean enable) {
+        mWifiNative.enableSoftApBeaconProtFeature(enable);
+    }
+
+    private void updateDataInterface() {
+        String dataInterfaceName = mWifiNative.getFstDataInterfaceName();
+        if (TextUtils.isEmpty(dataInterfaceName)) {
+            dataInterfaceName = mInterfaceName;
+        }
+        mDataInterfaceName = dataInterfaceName;
+
+        if (mIpClient != null) {
+            mIpClient.shutdown();
+            // Block to make sure IpClient has really shut down, lest cleanup
+            // race with, say, bringup code over in tethering.
+            mIpClientCallbacks.awaitShutdown();
+        }
+
+        mIpClientCallbacks = new IpClientCallbacksImpl();
+        mFacade.makeIpClient(mContext, mDataInterfaceName, mIpClientCallbacks);
+        if (!mIpClientCallbacks.awaitCreation()) {
+            Log.wtf(getName(), "Timeout waiting for IpClient");
+        }
+
+        setMulticastFilter(true);
+
+        if (mTrafficPoller != null) {
+            mTrafficPoller.setInterface(mDataInterfaceName);
+        }
+    }
+
+    /**
      * Initiates connection to a network specified by the user/app. This method checks if the
      * requesting app holds the NETWORK_SETTINGS permission.
      *
@@ -1310,8 +1433,8 @@
             mRunningBeaconCount = stats.beacon_rx;
             mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate);
         } else {
-            long mTxPkts = mFacade.getTxPackets(mInterfaceName);
-            long mRxPkts = mFacade.getRxPackets(mInterfaceName);
+            long mTxPkts = mFacade.getTxPackets(mDataInterfaceName);
+            long mRxPkts = mFacade.getRxPackets(mDataInterfaceName);
             mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate);
         }
         return stats;
@@ -1993,7 +2116,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));
@@ -2217,6 +2339,15 @@
                     sb.append(" ").append(frameData.toString());
                 }
                 break;
+            case WifiMonitor.DPP_EVENT:
+                sb.append(" type=");
+                sb.append(msg.arg1);
+                break;
+            case CMD_IP_REACHABILITY_SESSION_END:
+                if (msg.obj != null) {
+                    sb.append(" ").append((String) msg.obj);
+                }
+                break;
             default:
                 sb.append(" ");
                 sb.append(Integer.toString(msg.arg1));
@@ -2259,9 +2390,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;
@@ -2479,7 +2607,7 @@
             mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
         }
         if (newFrequency > 0) {
-            mWifiInfo.setFrequency(newFrequency);
+            updateConnectedBand(newFrequency, true);
         }
         mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo);
         /*
@@ -2558,7 +2686,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);
     }
 
@@ -2575,6 +2702,27 @@
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void sendDppEventBroadcast(int dppEventType, DppResult result) {
+        WifiDppConfig config = new WifiDppConfig();
+        config.setDppResult(result);
+        Intent intent = new Intent(WifiManager.DPP_EVENT_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_DPP_EVENT_TYPE, dppEventType);
+        intent.putExtra(WifiManager.EXTRA_DPP_EVENT_DATA, config);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    /**
+     * Send NETWORK_STATE_CHANGED_ACTION with current state info.
+     */
+    private void sendNetworkChangeBroadcast() {
+        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        NetworkInfo networkInfo = makeNetworkInfo();
+        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
     /**
      * Record the detailed state of a network.
      *
@@ -2667,7 +2815,7 @@
             if (scanDetailCache != null) {
                 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID);
                 if (scanDetail != null) {
-                    mWifiInfo.setFrequency(scanDetail.getScanResult().frequency);
+                    updateConnectedBand(scanDetail.getScanResult().frequency, true);
                     NetworkDetail networkDetail = scanDetail.getNetworkDetail();
                     if (networkDetail != null
                             && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) {
@@ -2687,6 +2835,7 @@
         int maxTxLinkSpeedMbps = throughputPredictor.predictMaxTxThroughput(capabilities);
         int maxRxLinkSpeedMbps = throughputPredictor.predictMaxRxThroughput(capabilities);
         mWifiInfo.setWifiStandard(capabilities.wifiStandard);
+        updateQcWifiGenerationInfo();
         mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps);
         mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps);
         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(
@@ -2695,12 +2844,26 @@
         if (mVerboseLoggingEnabled) {
             StringBuilder sb = new StringBuilder();
             logd(sb.append("WifiStandard: ").append(capabilities.wifiStandard)
+                    .append(" vhtMax8SS: ").append(mWifiInfo.isVhtMax8SpatialStreamsSupported())
+                    .append(" he8ssAp: ").append(mWifiInfo.isHe8ssCapableAp())
                     .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps)
                     .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps)
                     .toString());
         }
     }
 
+    public ScanResult getScanResultForBssid(String bssid) {
+      ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(mInterfaceName);
+      ScanResult scanRes;
+          for (ScanDetail result : scanResults) {
+              scanRes = result.getScanResult();
+              Log.e(TAG, "getScanResults scanRes.BSSID = " + scanRes.BSSID);
+              if (scanRes.BSSID.equals(bssid))
+                  return scanRes;
+          }
+          return null;
+    }
+
     /**
      * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore.
      */
@@ -2761,7 +2924,8 @@
         } else {
             stopDhcpSetup();
         }
-
+        // update connected band before WifiInfo reset.
+        updateConnectedBand(mWifiInfo.getFrequency(), false);
         mWifiScoreReport.stopConnectedNetworkScorer();
         /* Reset data structures */
         mWifiScoreReport.reset();
@@ -2791,27 +2955,9 @@
     }
 
     void handlePreDhcpSetup() {
-        if (!mBluetoothConnectionActive) {
-            /*
-             * There are problems setting the Wi-Fi driver's power
-             * mode to active when bluetooth coexistence mode is
-             * enabled or sense.
-             * <p>
-             * We set Wi-Fi to active mode when
-             * obtaining an IP address because we've found
-             * compatibility issues with some routers with low power
-             * mode.
-             * <p>
-             * In order for this active power mode to properly be set,
-             * we disable coexistence mode until we're done with
-             * obtaining an IP address.  One exception is if we
-             * are currently connected to a headset, since disabling
-             * coexistence would interrupt that connection.
-             */
-            // Disable the coexistence mode
-            mWifiNative.setBluetoothCoexistenceMode(
-                    mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
-        }
+        // Disable the coexistence mode
+        mWifiNative.setBluetoothCoexistenceMode(
+            mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
 
         // Disable power save and suspend optimizations during DHCP
         // Note: The order here is important for now. Brcm driver changes
@@ -2863,6 +3009,11 @@
                 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
     }
 
+    public String getCapabilities(String capaType) {
+
+        return mWifiNative.getCapabilities(mInterfaceName, capaType);
+    }
+
     /**
      * Set power save mode
      *
@@ -2903,6 +3054,14 @@
 
     @VisibleForTesting
     public static final long DIAGS_CONNECT_TIMEOUT_MILLIS = 60 * 1000;
+
+    private WifiGenerationStatus getWifiGenerationStatus() {
+         if (mInterfaceName == null)
+             return null;
+
+        return mWifiNative.getWifiGenerationStatus(mInterfaceName);
+    }
+
     /**
      * Inform other components that a new connection attempt is starting.
      */
@@ -2957,6 +3116,7 @@
             ssid = getTargetSsid();
         }
         if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) {
+            updateConnectedBand(mWifiInfo.getFrequency(), false);
             int blocklistReason = convertToBssidBlocklistMonitorFailureReason(
                     level2FailureCode, level2FailureReason);
             if (blocklistReason != -1) {
@@ -2966,13 +3126,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);
             }
         }
 
@@ -3139,6 +3294,15 @@
         mWifiScoreCard.noteIpConfiguration(mWifiInfo);
     }
 
+    /* Do Broadcast WIFI NETWORK DISCONNECTION Intent with message.arg1 and message.arg2 */
+    private void NotifyBroadcastNetworkDisconnection(int arg1, int arg2) {
+        loge("ClientModeImpl: NotifyBroadcastNetworkDisconnection called with" + arg1 + ", " + arg2);
+        Intent intent = new Intent(WifiManager.WIFI_NETWORK_DISCONNECTION);
+        intent.putExtra(WifiManager.EXTRA_WIFI_NETWORK_DISCONNECTION_ARG1, arg1);
+        intent.putExtra(WifiManager.EXTRA_WIFI_NETWORK_DISCONNECTION_ARG2, arg2);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
     private void handleIPv4Failure() {
         // TODO: Move this to provisioning failure, not DHCP failure.
         // DHCPv4 failure is expected on an IPv6-only network.
@@ -3251,6 +3415,11 @@
         if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) {
             return false;
         }
+        Log.i(TAG, "isPermanentWrongPasswordFailure - mIsWhitelistRoaming=" + mIsWhitelistRoaming);
+        if (mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED)
+            && mIsWhitelistRoaming) {
+            return true;
+        }
         WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId);
         if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) {
             return false;
@@ -3294,24 +3463,29 @@
             Log.e(TAG, "No config to change MAC address to");
             return;
         }
-        String currentMacString = mWifiNative.getMacAddress(mInterfaceName);
-        MacAddress currentMac = currentMacString == null ? null :
-                MacAddress.fromString(currentMacString);
-        MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config);
-        if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) {
-            Log.wtf(TAG, "Config generated an invalid MAC address");
-        } else if (newMac.equals(currentMac)) {
-            Log.d(TAG, "No changes in MAC address");
-        } else {
-            mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config);
-            boolean setMacSuccess =
-                    mWifiNative.setMacAddress(mInterfaceName, newMac);
-            if (setMacSuccess) {
-                mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac);
+
+        try {
+            String currentMacString = mWifiNative.getMacAddress(mInterfaceName);
+            MacAddress currentMac = currentMacString == null ? null :
+                    MacAddress.fromString(currentMacString);
+            MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config);
+            if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) {
+                Log.wtf(TAG, "Config generated an invalid MAC address");
+            } else if (currentMac.equals(newMac)) {
+                Log.d(TAG, "No changes in MAC address");
+            } else {
+                mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config);
+                boolean setMacSuccess =
+                        mWifiNative.setMacAddress(mInterfaceName, newMac);
+                if (setMacSuccess) {
+                    mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac);
+                }
+                Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid()
+                        + "). setMacAddress(" + newMac.toString() + ") from "
+                        + currentMacString + " = " + setMacSuccess);
             }
-            Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid()
-                    + "). setMacAddress(" + newMac.toString() + ") from "
-                    + currentMacString + " = " + setMacSuccess);
+        } catch (NullPointerException | IllegalArgumentException e) {
+            Log.e(TAG, "Exception in configureRandomizedMacAddress: " + e.toString());
         }
     }
 
@@ -3441,6 +3615,7 @@
                     break;
                 case CMD_INITIALIZE:
                     mWifiNative.initialize();
+                    mWifiScoreReport.initialize();
                     break;
                 case CMD_BOOT_COMPLETED:
                     // get other services that we need to manage
@@ -3455,7 +3630,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:
@@ -3474,6 +3648,10 @@
                 case CMD_UNWANTED_NETWORK:
                 case CMD_DISCONNECTING_WATCHDOG_TIMER:
                 case CMD_ROAM_WATCHDOG_TIMER:
+                case WifiMonitor.DPP_EVENT:
+                case CMD_IP_REACHABILITY_SESSION_END:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
                 case CMD_SET_OPERATIONAL_MODE:
                     // using the CMD_SET_OPERATIONAL_MODE (sent at front of queue) to trigger the
                     // state transitions performed in setOperationalMode.
@@ -3515,6 +3693,10 @@
                     mTemporarilyDisconnectWifi = (message.arg1 == 1);
                     replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
                     break;
+                case WifiP2pServiceImpl.SET_MIRACAST_MODE:
+                    if (mVerboseLoggingEnabled) logd("SET_MIRACAST_MODE: " + (int)message.arg1);
+                    mWifiConnectivityManager.saveMiracastMode((int)message.arg1);
+                    break;
                 /* Link configuration (IP address, DNS, ...) changes notified via netlink */
                 case CMD_UPDATE_LINKPROPERTIES:
                     updateLinkProperties((LinkProperties) message.obj);
@@ -3574,6 +3756,23 @@
                     mWifiDiagnostics.reportConnectionEvent(
                             BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT);
                     break;
+                case CMD_DPP_GENERATE_BOOTSTRAP:
+                case CMD_DPP_ADD_BOOTSTRAP_QRCODE:
+                case CMD_DPP_REMOVE_BOOTSTRAP:
+                case CMD_DPP_LISTEN_START:
+                case CMD_DPP_CONF_ADD:
+                case CMD_DPP_CONF_REMOVE:
+                case CMD_DPP_AUTH_INIT:
+                    replyToMessage(message, message.what, FAILURE);
+                    break;
+                case CMD_DPP_GET_URI:
+                case CMD_DPP_CONFIGURATOR_GET_KEY:
+                case CMD_DO_DRIVER_CMD:
+                    replyToMessage(message, message.what, "Supplicant Not Started!!");
+                    break;
+                case CMD_DPP_LISTEN_STOP:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
                 case 0:
                     // We want to notice any empty messages (with what == 0) that might crop up.
                     // For example, we may have recycled a message sent to multiple handlers.
@@ -3592,6 +3791,10 @@
         }
     }
 
+    public void registerModeListener(ClientModeManager.Listener clientModeImplListener) {
+        mClientModeCallback = clientModeImplListener;
+    }
+
     /**
      * Helper method to start other services and get state ready for client mode
      */
@@ -3601,13 +3804,8 @@
         setHighPerfModeEnabled(false);
 
         mWifiStateTracker.updateState(WifiStateTracker.INVALID);
-        mIpClientCallbacks = new IpClientCallbacksImpl();
-        mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks);
-        if (!mIpClientCallbacks.awaitCreation()) {
-            Log.wtf(getName(), "Timeout waiting for IpClient");
-        }
 
-        setMulticastFilter(true);
+        updateDataInterface();
         registerForWifiMonitorEvents();
         mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts();
         setSupplicantLogLevel();
@@ -3663,6 +3861,9 @@
         mWifiNative.enableStaAutoReconnect(mInterfaceName, false);
         // STA has higher priority over P2P
         mWifiNative.setConcurrencyPriority(true);
+
+        // Reset Connected band entries
+        mWifiNative.qtiUpdateConnectedBand(STA_PRIMARY, WifiNative.ConnectedBand.BAND_NONE);
     }
 
     /**
@@ -3683,12 +3884,16 @@
         mCountryCode.setReadyForChange(false);
         mInterfaceName = null;
         mWifiScoreReport.setInterfaceName(null);
+        mDataInterfaceName = null;
         // 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();
+        // Reset Connected band entries
+        mWifiNative.qtiUpdateConnectedBand(STA_PRIMARY, WifiNative.ConnectedBand.BAND_NONE);
     }
 
     void registerConnected() {
@@ -3789,6 +3994,10 @@
             if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
                 loge("Failed to remove networks on entering connect mode");
             }
+
+            // update connected band before WifiInfo reset.
+            updateConnectedBand(mWifiInfo.getFrequency(), false);
+
             mWifiInfo.reset();
             mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
 
@@ -3797,6 +4006,7 @@
 
             // Inform WifiConnectivityManager that Wifi is enabled
             mWifiConnectivityManager.setWifiEnabled(true);
+            mWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingEnabled);
             mNetworkFactory.setWifiState(true);
             // Inform metrics that Wifi is Enabled (but not yet connected)
             mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
@@ -3804,6 +4014,16 @@
             mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
             mWifiHealthMonitor.setWifiEnabled(true);
             mWifiDataStall.init();
+
+            if (mClientModeCallback != null) {
+                 mClientModeCallback.onStarted();
+            }
+            mConcurrentBand = mWifiNative.doDriverCmd(mInterfaceName,
+                "GET_DRIVER_SUPPORTED_FEATURES");
+            Log.d(TAG, "output of doDriverCmd for concurrent band = " + mConcurrentBand);
+            if (!TextUtils.isEmpty(mConcurrentBand))
+                mWifiInjector.getSettingsConfigStore().put(HW_SUPPORTED_FEATURES,
+                    Integer.parseInt(mConcurrentBand));
         }
 
         @Override
@@ -3822,6 +4042,10 @@
             if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
                 loge("Failed to remove networks on exiting connect mode");
             }
+
+            // update connected band before WifiInfo reset.
+            updateConnectedBand(mWifiInfo.getFrequency(), false);
+
             mWifiInfo.reset();
             mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
             mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
@@ -3906,8 +4130,13 @@
                         disableReason = WifiConfiguration.NetworkSelectionStatus
                                 .DISABLED_BY_WRONG_PASSWORD;
                         if (targetedNetwork != null) {
-                            mWrongPasswordNotifier.onWrongPasswordError(
-                                    targetedNetwork.SSID);
+                            if (targetedNetwork.isEphemeral() && targetedNetwork.isAutoConnectionEnabled) {
+                                Log.e(TAG, "Auto connection attempt on new network "
+                                                   + targetedNetwork.getPrintableSsid() + " failed");
+                            } else {
+                                mWrongPasswordNotifier.onWrongPasswordError(
+                                        targetedNetwork.SSID);
+                            }
                         }
                     } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) {
                         int errorCode = message.arg2;
@@ -4110,7 +4339,6 @@
                     String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName);
                     mWifiInfo.setMacAddress(currentMacAddress);
                     Log.i(TAG, "Connecting with " + currentMacAddress + " as the mac address");
-
                     mTargetWifiConfiguration = config;
                     /* Check for FILS configuration again after updating the config */
                     if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
@@ -4177,12 +4405,14 @@
                                 // We switched from DHCP to static or from static to DHCP, or the
                                 // static IP address has changed.
                                 log("Reconfiguring IP on connection");
-                                WifiConfiguration currentConfig = getCurrentWifiConfiguration();
-                                if (currentConfig != null) {
-                                    transitionTo(mObtainingIpState);
+                                mWifiNative.disconnect(mInterfaceName);
+                                transitionTo(mDisconnectingState);
+                                // reconnect to the same network
+                                if (mWifiNative.reconnect(mInterfaceName)) {
+                                    log("Reconnecting after IP reconfiguration");
                                 } else {
-                                    Log.w(TAG, "CMD_SAVE_NETWORK Ip change - but no current "
-                                            + "Wi-Fi config");
+                                    loge("Failed to reconnect after IP reconfiguration");
+                                    // we will transition to disconnected state by previous code
                                 }
                             }
                         }
@@ -4191,6 +4421,8 @@
                         logi("CMD_SAVE_NETWORK credential changed for nid="
                                 + netId + " while disconnected. Connecting.");
                         startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
+                    } else if (result.hasCredentialChanged()) {
+                        updateWhitelistNetworksIfRequired(mWifiConfigManager.getConfiguredNetwork(netId));
                     }
                     sendActionListenerSuccess(callbackIdentifier);
                     break;
@@ -4211,12 +4443,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;
@@ -4228,6 +4459,10 @@
                     // network.
                     config = getCurrentWifiConfiguration();
                     if (config != null) {
+                        if (mWifiConfigManager.saveAutoConnectedNewNetwork(config.networkId)) {
+                            Log.i(TAG, "Successfully connected to new network " + config.getPrintableSsid());
+                            mAutoConnectNewNetworkResultNotifier.onConnectionAttemptSuccess(config.SSID);
+                        }
                         mWifiInfo.setBSSID(mLastBssid);
                         mWifiInfo.setNetworkId(mLastNetworkId);
                         mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
@@ -4237,7 +4472,7 @@
                         if (scanDetailCache != null && mLastBssid != null) {
                             ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
                             if (scanResult != null) {
-                                mWifiInfo.setFrequency(scanResult.frequency);
+                                updateConnectedBand(scanResult.frequency, true);
                             }
                         }
 
@@ -4269,6 +4504,7 @@
                             }
                             mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
                         }
+                        mIpReachabilityMonitorActive = true;
                         transitionTo(mObtainingIpState);
                     } else {
                         logw("Connected to unknown networkId " + mLastNetworkId
@@ -4398,6 +4634,60 @@
                 case CMD_IPV4_PROVISIONING_FAILURE:
                     handleStatus = handleL3MessagesWhenNotConnected(message);
                     break;
+                case CMD_DPP_GENERATE_BOOTSTRAP:
+                    int id = mWifiNative.dppBootstrapGenerate(mInterfaceName, (WifiDppConfig)message.obj);
+                    replyToMessage(message, message.what, id);
+                    break;
+                case CMD_DPP_ADD_BOOTSTRAP_QRCODE:
+                    int qrcode_hdl = mWifiNative.dppAddBootstrapQrCode(mInterfaceName, (String) message.obj);
+                    replyToMessage(message, message.what, qrcode_hdl);
+                    break;
+                case CMD_DPP_REMOVE_BOOTSTRAP:
+                    int bootstrap_status = mWifiNative.dppBootstrapRemove(mInterfaceName, message.arg1);
+                    replyToMessage(message, message.what, bootstrap_status);
+                    break;
+                case CMD_DPP_GET_URI:
+                    String uri = mWifiNative.dppGetUri(mInterfaceName, message.arg1);
+                    replyToMessage(message, message.what, uri);
+                    break;
+                case CMD_DPP_LISTEN_START:
+                    int listen_status = mWifiNative.dppListen(mInterfaceName,
+                            ((Bundle) message.obj).getString("freq"),
+                            ((Bundle) message.obj).getInt("dppRole"),
+                            ((Bundle) message.obj).getBoolean("mutual"),
+                            ((Bundle) message.obj).getBoolean("netRoleAp"));
+                    replyToMessage(message, message.what, listen_status);
+                    break;
+                case CMD_DPP_LISTEN_STOP:
+                    mWifiNative.dppStopListen(mInterfaceName);
+                    break;
+                case CMD_DPP_CONF_ADD:
+                    int cfg_add_status = mWifiNative.dppConfiguratorAdd(mInterfaceName,
+                            ((Bundle) message.obj).getString("curve"),
+                            ((Bundle) message.obj).getString("key"),
+                             message.arg1);
+                    replyToMessage(message, message.what, cfg_add_status);
+                    break;
+                case CMD_DPP_CONF_REMOVE:
+                    int cfg_remove_status = mWifiNative.dppConfiguratorRemove(mInterfaceName, message.arg1);
+                    replyToMessage(message, message.what, cfg_remove_status);
+                    break;
+                case CMD_DPP_AUTH_INIT:
+                    int auth_init_status = mWifiNative.dppStartAuth(mInterfaceName, (WifiDppConfig)message.obj);
+                    replyToMessage(message, message.what, auth_init_status);
+                    break;
+                case CMD_DPP_CONFIGURATOR_GET_KEY:
+                    String key = mWifiNative.dppConfiguratorGetKey(mInterfaceName, (int) message.obj);
+                    replyToMessage(message, message.what, key);
+                    break;
+                case WifiMonitor.DPP_EVENT:
+                    Log.d(TAG, "DPP Event received. Type = " + message.arg1);
+                    sendDppEventBroadcast(message.arg1, (DppResult) message.obj);
+                    break;
+                case CMD_DO_DRIVER_CMD:
+                    String reply = mWifiNative.doDriverCmd(mInterfaceName, (String) message.obj);
+                    replyToMessage(message, message.what, reply);
+                    break;
                 default:
                     handleStatus = NOT_HANDLED;
                     break;
@@ -4572,7 +4862,6 @@
                         mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork);
                     }
                     break;
-
                 default:
                     // Do Nothing
             }
@@ -4783,6 +5072,7 @@
             mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo,
                     mNetworkAgent.getNetwork().getNetId());
             mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID());
+            mIsWhitelistRoaming = false;
         }
 
         @Override
@@ -4833,6 +5123,7 @@
                     break;
                 case CMD_IPV4_PROVISIONING_SUCCESS: {
                     handleIPv4Success((DhcpResultsParcelable) message.obj);
+                    sendNetworkChangeBroadcast();
                     break;
                 }
                 case CMD_IPV4_PROVISIONING_FAILURE: {
@@ -4884,7 +5175,12 @@
                     mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
                             WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
                     if (mIpReachabilityDisconnectEnabled) {
+                        if (mDisconnectOnlyOnInitialIpReachability && !mIpReachabilityMonitorActive) {
+                            logd("CMD_IP_REACHABILITY_LOST Connect session is over, skip ip reachability lost indication.");
+                            break;
+                        }
                         handleIpReachabilityLost();
+                        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NUD_FAILURE);
                         transitionTo(mDisconnectingState);
                     } else {
                         logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore");
@@ -4906,14 +5202,20 @@
                     }
                     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;
+                    if (mIsWhitelistRoaming) {
+                        mIsWhitelistRoaming = false;
+                        mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+                        mTargetWifiConfiguration = null;
+                        clearTargetBssid("WhitelistRoamingCompleted");
+                        sendNetworkChangeBroadcast(DetailedState.CONNECTED);
                     }
+                    mIpReachabilityMonitorActive = true;
+                    sendMessageDelayed(obtainMessage(CMD_IP_REACHABILITY_SESSION_END, 0, 0), 10000);
                     break;
                 case CMD_ONESHOT_RSSI_POLL:
                     if (!mEnableRssiPolling) {
@@ -4981,6 +5283,12 @@
                         logw("Associated command w/o BSSID");
                         break;
                     }
+
+                    if (checkAndHandleWhitelistRoaming((String) message.obj)) {
+                        Log.i(TAG, "Driver initiated whitelist SSID roaming");
+                        break;
+                    }
+
                     mLastBssid = (String) message.obj;
                     if (mLastBssid != null && (mWifiInfo.getBSSID() == null
                             || !mLastBssid.equals(mWifiInfo.getBSSID()))) {
@@ -4992,10 +5300,11 @@
                             if (scanDetailCache != null) {
                                 ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
                                 if (scanResult != null) {
-                                    mWifiInfo.setFrequency(scanResult.frequency);
+                                    updateConnectedBand(scanResult.frequency, true);
                                 }
                             }
                         }
+                        sendNetworkChangeBroadcast();
                     }
                     break;
                 case CMD_START_RSSI_MONITORING_OFFLOAD:
@@ -5014,11 +5323,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
@@ -5124,6 +5434,15 @@
     class ObtainingIpState extends State {
         @Override
         public void enter() {
+            // Reset power save mode after association.
+            // Kernel does not forward power save request to driver if power
+            // save state of that interface is same as requested state in
+            // cfg80211. This happens when driver’s power save state not
+            // synchronized with cfg80211 power save state.
+            // By resetting power save state resolves issues of cfg80211
+            // ignoring enable power save request sent in ObtainingIpState.
+            mWifiNative.setPowerSave(mInterfaceName, false);
+
             WifiConfiguration currentConfig = getCurrentWifiConfiguration();
             if (mIpClientWithPreConnection && mIpClient != null) {
                 mIpClient.notifyPreconnectionComplete(mSentHLPs);
@@ -5281,6 +5600,7 @@
                         mLastBssid = (String) message.obj;
                         mWifiInfo.setBSSID(mLastBssid);
                         mWifiInfo.setNetworkId(mLastNetworkId);
+                        sendNetworkChangeBroadcast();
 
                         // Successful framework roam! (probably)
                         mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid,
@@ -5306,6 +5626,7 @@
                         //
                         // mIpClient.confirmConfiguration() is called within
                         // the handling of SupplicantState.COMPLETED.
+                        mIpReachabilityMonitorActive = true;
                         transitionTo(mConnectedState);
                     } else {
                         mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
@@ -5360,6 +5681,10 @@
                     WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
             mWifiConnectivityManager.handleConnectionStateChanged(
                     WifiConnectivityManager.WIFI_STATE_CONNECTED);
+
+            if (mIpReachabilityMonitorActive)
+                sendMessageDelayed(obtainMessage(CMD_IP_REACHABILITY_SESSION_END, 0, 0), 10000);
+
             registerConnected();
             mLastConnectAttemptTimestamp = 0;
             mTargetWifiConfiguration = null;
@@ -5420,15 +5745,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);
                             }
                         }
@@ -5452,6 +5773,9 @@
                                             .DISABLED_NONE);
                             mWifiConfigManager.setNetworkValidatedInternetAccess(
                                     config.networkId, true);
+                            if (getConnectedNetworkDefaultGatewayMacAddress()) {
+                                updateWhitelistNetworks(config);
+                            }
                         }
                     }
                     break;
@@ -5484,13 +5808,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();
 
@@ -5503,6 +5824,7 @@
                                 + " Network Selection Status=" + (config == null ? "Unavailable"
                                     : config.getNetworkSelectionStatus().getNetworkStatusString()));
                     }
+                    NotifyBroadcastNetworkDisconnection(message.arg1, message.arg2);
                     break;
                 case CMD_START_ROAM:
                     // Clear the driver roam indication since we are attempting a framework roam
@@ -5557,6 +5879,19 @@
                 case CMD_GET_CURRENT_NETWORK:
                     replyToMessage(message, message.what, getCurrentNetwork());
                     break;
+                case CMD_START_IP_PACKET_OFFLOAD: {
+                    int slot = message.arg1;
+                    int intervalSeconds = message.arg2;
+                    KeepalivePacketData pkt = (KeepalivePacketData) message.obj;
+                    int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendSocketKeepaliveEvent(slot, result);
+                    }
+                    break;
+                }
+                case CMD_IP_REACHABILITY_SESSION_END:
+                    mIpReachabilityMonitorActive = false;
+                    break;
                 default:
                     handleStatus = NOT_HANDLED;
                     break;
@@ -5668,6 +6003,10 @@
 
             /** clear the roaming state, if we were roaming, we failed */
             mIsAutoRoaming = false;
+            mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+
+            mIpReachabilityMonitorActive = false;
+            removeMessages(CMD_IP_REACHABILITY_SESSION_END);
 
             mWifiConnectivityManager.handleConnectionStateChanged(
                     WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
@@ -5695,6 +6034,7 @@
                     }
                     clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2);
                     mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+                    mWifiInfo.reset();
                     break;
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
@@ -5825,15 +6165,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;
         }
 
@@ -5850,15 +6195,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) {
@@ -5871,20 +6216,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);
@@ -5924,6 +6274,16 @@
     }
 
     /**
+     * Allow quick connect on partial scan results
+     *
+     * @param choice true-enable; false-disable
+     */
+    public void allowConnectOnPartialScanResults(boolean enable) {
+        mWifiConnectivityManager.allowConnectOnPartialScanResults(enable);
+        mWifiNative.allowConnectOnPartialScanResults(enable);
+    }
+
+    /**
      * @param reason reason code from supplicant on network disconnected event
      * @return true if this is a suspicious disconnect
      */
@@ -6080,6 +6440,174 @@
     }
 
     /**
+     * Add the DPP bootstrap info obtained from QR code.
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param uri:The URI obtained from the QR code.
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int syncDppAddBootstrapQrCode(AsyncChannel channel, String uri) {
+        Message resultMsg = channel.sendMessageSynchronously(
+                CMD_DPP_ADD_BOOTSTRAP_QRCODE, 0, 0, uri);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Generate bootstrap URI based on the passed arguments
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param config – bootstrap generate config
+     *
+     * @return: Handle to strored URI info else -1 on failure
+     */
+    public int syncDppBootstrapGenerate(AsyncChannel channel,
+        WifiDppConfig config) {
+        Message resultMsg = channel.sendMessageSynchronously(
+            CMD_DPP_GENERATE_BOOTSTRAP, 0, 0, config);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Get bootstrap URI based on bootstrap ID
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: URI string else -1 on failure
+     */
+    public String syncDppGetUri(AsyncChannel channel, int bootstrap_id) {
+        Message resultMsg = channel.sendMessageSynchronously(
+            CMD_DPP_GET_URI, bootstrap_id);
+        String result = (String)resultMsg.obj;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Remove bootstrap URI based on bootstrap ID.
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: 0 – Success or -1 on failure
+     */
+    public int syncDppBootstrapRemove(AsyncChannel channel, int bootstrap_id) {
+        Message resultMsg = channel.sendMessageSynchronously(
+            CMD_DPP_REMOVE_BOOTSTRAP, bootstrap_id);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * start listen on the channel specified waiting to receive
+     * the DPP Authentication request.
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param frequency: DPP listen frequency
+     * @param dpp_role: Configurator/Enrollee role
+     * @param qr_mutual: Mutual authentication required
+     * @param netrole_ap: network role
+     *
+     * @return: Returns 0 if a DPP-listen work is successfully
+     *  queued and -1 on failure.
+     */
+    public int syncDppListen(AsyncChannel channel, String frequency, int dpp_role,
+                             boolean qr_mutual, boolean netrole_ap) {
+        Bundle bundle = new Bundle();
+        bundle.putString("freq", frequency);
+        bundle.putInt("dppRole", dpp_role);
+        bundle.putBoolean("mutual", qr_mutual);
+        bundle.putBoolean("netRoleAp", netrole_ap);
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DPP_LISTEN_START,
+                            0, 0, bundle);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * stop ongoing dpp listen.
+     */
+    public void dppStopListen(AsyncChannel channel) {
+        sendMessage(CMD_DPP_LISTEN_STOP);
+    }
+
+    /**
+     * Adds the DPP configurator
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param curve curve used for dpp encryption
+     * @param key private key
+     * @param expiry timeout in seconds
+     *
+     * @return: Identifier of the added configurator or -1 on failure
+     */
+    public int syncDppConfiguratorAdd(AsyncChannel channel,
+               String curve, String key, int expiry) {
+        Bundle bundle = new Bundle();
+        bundle.putString("curve", curve);
+        bundle.putString("key", key);
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DPP_CONF_ADD,
+                            expiry, 0, bundle);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Remove the added configurator through dppConfiguratorAdd.
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param config_id: DPP Configurator ID
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int syncDppConfiguratorRemove(AsyncChannel channel, int config_id) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DPP_CONF_REMOVE, config_id);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Start DPP authentication and provisioning with the specified peer
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param config – dpp auth init config
+     *
+     * @return: 0 if DPP Authentication request was transmitted and -1 on failure
+     */
+    public int  syncDppStartAuth(AsyncChannel channel, WifiDppConfig config) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DPP_AUTH_INIT,
+                            0, 0, config);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     *Retrieve Private key to be used for configurator
+     *
+     * @param channel Channel for communicating with the state machine
+     * @param id: id of configurator obj
+     *
+     * @return: KEY string else -1 on failure
+     */
+    public String syncDppConfiguratorGetKey(AsyncChannel channel, int id) {
+        Message resultMsg = channel.sendMessageSynchronously(
+            CMD_DPP_CONFIGURATOR_GET_KEY, 0, 0, id);
+        String result = (String)resultMsg.obj;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
      * Gets the factory MAC address of wlan0 (station interface).
      * @return String representation of the factory MAC address.
      */
@@ -6282,19 +6810,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) {
@@ -6599,4 +7132,235 @@
         return true;
     }
 
+    private void updateQcWifiGenerationInfo() {
+        WifiGenerationStatus wifiGenerationStatus = getWifiGenerationStatus();
+
+        if (wifiGenerationStatus == null)
+            return;
+
+        mWifiInfo.setVhtMax8SpatialStreamsSupport(wifiGenerationStatus.vhtMax8SpatialStreamsSupport);
+        WifiConfiguration config = getCurrentWifiConfiguration();
+
+        if (config == null)
+            return;
+
+        ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+        if (scanDetailCache == null)
+            return;
+
+        ScanResult result = scanDetailCache.getScanResult(mLastBssid);
+        if (result != null) {
+            if (result.capabilities.contains("WFA-HE-READY")) {
+                mWifiInfo.setHe8ssCapableAp(true);
+            } else {
+                mWifiInfo.setHe8ssCapableAp(false);
+            }
+        }
+    }
+
+    /**
+     * Run Driver Command
+     * @param : Command string
+     */
+    public String doDriverCmd(AsyncChannel channel, String command)
+    {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DO_DRIVER_CMD, command);
+        String result = (String)resultMsg.obj;
+        resultMsg.recycle();
+        return result;
+    }
+
+    public List<ScanDetail> qtiGetFilteredScan(List<ScanDetail> scanDetails) {
+        // All Bands are available for use
+        if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_NONE))
+            return scanDetails;
+
+        boolean filter2G = false;
+        boolean filter5G = false;
+
+        if (isDisconnected()) {
+            if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))
+                filter2G = true;
+            if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+                filter5G = true;
+        } else {
+            if (mWifiInfo.is24GHz() &&
+                    mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+                filter5G = true;
+            else if ((mWifiInfo.is5GHz() || mWifiInfo.is6GHz()) &&
+                        mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))
+                filter2G = true;
+        }
+
+        List<ScanDetail> filtered = new ArrayList<ScanDetail>();
+        for (ScanDetail entry : scanDetails) {
+            if (entry.getScanResult().is24GHz() && !filter2G)
+                filtered.add(entry);
+            if (entry.getScanResult().is5GHz() && !filter5G)
+                filtered.add(entry);
+        }
+        if (mVerboseLoggingEnabled)
+            Log.d(TAG, "filtering out " + (scanDetails.size() - filtered.size()) + " scan entries");
+
+        return filtered;
+    }
+
+    private void updateConnectedBand(int freq, boolean set) {
+        if (mVerboseLoggingEnabled)
+            Log.d(TAG, "updateConnectedBand freq="+freq+" set="+set);
+        if (set) {
+            mWifiInfo.setFrequency(freq);
+
+            if (ScanResult.is24GHz(freq)) {
+                mWifiNative.qtiUpdateConnectedBand(STA_PRIMARY, WifiNative.ConnectedBand.BAND_2G);
+            } else if (ScanResult.is5GHz(freq) || ScanResult.is6GHz(freq)) {
+                mWifiNative.qtiUpdateConnectedBand(STA_PRIMARY, WifiNative.ConnectedBand.BAND_5G);
+            }
+        } else {
+             mWifiNative.qtiUpdateConnectedBand(STA_PRIMARY, WifiNative.ConnectedBand.BAND_NONE);
+        }
+    }
+
+    /**
+     * Check for STA+STA in active mode.
+     *
+     * active mode: atleast one of the iface is connected and other is looking for connection
+     */
+    public boolean isActiveDualMode() {
+        if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_NONE)) {
+            return false;
+        }
+
+        if (!isConnected() && (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G)
+                               || mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G)))
+            return true;
+
+        if (isConnected()
+            && ((mWifiInfo.is24GHz() && mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+            || ((mWifiInfo.is5GHz() || mWifiInfo.is6GHz()) && mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))))
+            return true;
+        return false;
+    }
+
+    private boolean getConnectedNetworkDefaultGatewayMacAddress() {
+        WifiConfiguration currentConfig = getCurrentWifiConfiguration();
+        if (currentConfig == null) {
+            logi("can't fetch config of current network id " + mLastNetworkId);
+            return false;
+        }
+
+        // Find IPv4 default gateway.
+        String gatewayIPv4 = null;
+        for (RouteInfo routeInfo : mLinkProperties.getRoutes()) {
+            if (routeInfo.isDefaultRoute() &&
+                routeInfo.getDestination().getAddress() instanceof Inet4Address &&
+                routeInfo.hasGateway()) {
+                gatewayIPv4 = routeInfo.getGateway().getHostAddress();
+                break;
+            }
+        }
+
+        if (TextUtils.isEmpty(gatewayIPv4)) {
+            logi("default gateway ipv4 is null");
+            return false;
+        }
+
+        String gatewayMac = macAddressFromRoute(gatewayIPv4);
+        if (TextUtils.isEmpty(gatewayMac)) {
+            logi("default gateway mac fetch failed for ipv4 addr = " + gatewayIPv4);
+            return false;
+        }
+
+        logi("Default Gateway MAC address of " + mLastBssid + " from routes is : " + gatewayMac);
+        if (!mWifiConfigManager.setNetworkDefaultGwMacAddress(mLastNetworkId, gatewayMac)) {
+            logi("default gateway mac set failed for " + currentConfig.getKey() + " network");
+            return false;
+        }
+
+        mWifiConfigManager.saveToStore(true);
+        return true;
+    }
+
+    private void updateWhitelistNetworks(@NonNull WifiConfiguration currentConfig) {
+        if (!mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED)
+                || !currentConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+            return;
+        }
+
+        // check for FT/PSK
+        ScanDetail scanDetail = getScanDetailForBssid(mLastBssid);
+        if (scanDetail != null) {
+            ScanResult scanResult = scanDetail.getScanResult();
+            String caps = (scanResult != null) ? scanResult.capabilities : "";
+            if (caps.contains("FT/PSK")) {
+                Log.i(TAG, "Linked network - return as current connection is FT-PSK");
+                return;
+            }
+        }
+
+        HashMap<String, Integer>  linkedConfigurations =
+                mWifiConfigManager.updateAndGetLinkedConfiguration(currentConfig.networkId);
+	if (linkedConfigurations != null) {
+            HashMap<String, WifiConfiguration> whitelistNetworkConfigs = new HashMap<>();
+            ArrayList<String> whitelistedSsids = new ArrayList<String>();
+
+            // Generate network configs with passowrds to configure supplicant
+            // and whitelist SSID array list to update firmarware roaming configuration
+            Log.i(TAG, "Current network: " + currentConfig.getKey());
+            if (linkedConfigurations.size() > 0) {
+                whitelistedSsids.add(currentConfig.SSID);
+            }
+            for (String configKey : linkedConfigurations.keySet()) {
+                Log.i(TAG, "Linked network: " + configKey);
+                whitelistNetworkConfigs.put(configKey,
+                        mWifiConfigManager.getConfiguredNetworkWithoutMasking(configKey));
+                whitelistedSsids.add(configKey.substring(0, configKey.lastIndexOf('"') + 1));
+            }
+            if (mWifiNative.updateLinkedNetworks(mInterfaceName, currentConfig.networkId,
+                                    whitelistNetworkConfigs)) {
+                mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(currentConfig.SSID,
+                                               whitelistedSsids);
+            }
+        }
+    }
+
+    private void updateWhitelistNetworksIfRequired(WifiConfiguration updatedConfig) {
+        WifiConfiguration currentConfig = getCurrentWifiConfiguration();
+        if (currentConfig != null && updatedConfig != null
+                && currentConfig.isLinked(updatedConfig)) {
+            logi("current network linked configuration updated. refresh whitelist networks");
+            updateWhitelistNetworks(currentConfig);
+        }
+    }
+
+    private ScanDetail getScanDetailForBssid(String bssid) {
+      ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(mInterfaceName);
+      ScanResult scanRes;
+          for (ScanDetail result : scanResults) {
+              scanRes = result.getScanResult();
+              Log.e(TAG, "getScanResults scanRes.BSSID = " + scanRes.BSSID);
+              if (scanRes.BSSID.equals(bssid))
+                  return result;
+          }
+          return null;
+    }
+
+    private boolean checkAndHandleWhitelistRoaming(String associatedBssid) {
+        ScanDetail scanDetail = getScanDetailForBssid(associatedBssid);
+        if (scanDetail != null) {
+            WifiConfiguration config = mWifiConfigManager.
+                    getConfiguredNetworkForScanDetailAndCache(scanDetail);
+            if (config != null && mLastNetworkId != config.networkId) {
+                mIsWhitelistRoaming = true;
+                setTargetBssid(config, associatedBssid);
+                mTargetNetworkId = config.networkId;
+                mTargetWifiConfiguration = config;
+                mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+                sendNetworkChangeBroadcast(DetailedState.CONNECTING);
+                updateConnectedBand(scanDetail.getScanResult().frequency, true);
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/service/java/com/android/server/wifi/ClientModeManager.java b/service/java/com/android/server/wifi/ClientModeManager.java
old mode 100644
new mode 100755
index 4fb4b87..4a067e0
--- a/service/java/com/android/server/wifi/ClientModeManager.java
+++ b/service/java/com/android/server/wifi/ClientModeManager.java
@@ -25,6 +25,11 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.wifi.WifiManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityManager;
+import android.net.NetworkRequest;
+import android.net.NetworkCapabilities;
+import android.net.Network;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.Looper;
@@ -35,6 +40,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionInfo;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsMmTelManager;
 import android.telephony.ims.ImsReasonInfo;
@@ -60,8 +66,8 @@
  * Manager WiFi in Client Mode where we connect to configured networks.
  */
 public class ClientModeManager implements ActiveModeManager {
-    private static final String TAG = "WifiClientModeManager";
-
+    private static String TAG = "WifiClientModeManager";
+    private static int TAG_COUNT = 0;
     private final ClientModeStateMachine mStateMachine;
 
     private final Context mContext;
@@ -93,6 +99,7 @@
         mClientModeImpl = clientModeImpl;
         mStateMachine = new ClientModeStateMachine(looper);
         mDeferStopHandler = new DeferStopHandler(TAG, looper);
+        TAG = "WifiClientModeManager" + TAG_COUNT++;
     }
 
     /**
@@ -100,6 +107,8 @@
      */
     @Override
     public void start() {
+        Log.d(TAG, "Starting with role ROLE_CLIENT_SCAN_ONLY");
+        mRole = ROLE_CLIENT_SCAN_ONLY;
         mTargetRole = ROLE_CLIENT_SCAN_ONLY;
         mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
     }
@@ -135,6 +144,8 @@
         private long mDeferringStartTimeMillis = 0;
         private NetworkRequest mImsRequest = null;
         private ConnectivityManager mConnectivityManager = null;
+        private boolean mIsImsNetworkLost = false;
+        private boolean mIsImsNetworkUnregistered = false;
 
         private RegistrationManager.RegistrationCallback mImsRegistrationCallback =
                 new RegistrationManager.RegistrationCallback() {
@@ -151,7 +162,8 @@
                     @Override
                     public void onUnregistered(ImsReasonInfo imsReasonInfo) {
                         Log.d(TAG, "on IMS unregistered");
-                        // Wait for onLost in NetworkCallback
+                        mIsImsNetworkUnregistered = true;
+                        checkAndContinueToStopWifi();
                     }
                 };
 
@@ -178,7 +190,8 @@
                         int delay = mContext.getResources()
                                 .getInteger(R.integer.config_wifiDelayDisconnectOnImsLostMs);
                         if (delay == 0 || !postDelayed(mRunnable, delay)) {
-                            continueToStopWifi();
+                            mIsImsNetworkLost = true;
+                            checkAndContinueToStopWifi();
                         }
                     }
                 }
@@ -233,6 +246,11 @@
                                                          new Handler(mLooper));
         }
 
+        private void checkAndContinueToStopWifi() {
+            if (mIsImsNetworkLost && mIsImsNetworkUnregistered)
+                continueToStopWifi();
+        }
+
         private void continueToStopWifi() {
             Log.d(TAG, "The target role " + mTargetRole);
 
@@ -274,6 +292,8 @@
             }
 
             mIsDeferring = false;
+            mIsImsNetworkLost = false;
+            mIsImsNetworkUnregistered = false;
         }
     }
 
@@ -314,13 +334,17 @@
 
         ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId);
         // If no wifi calling, no delay
-        if (!imsMmTelManager.isAvailable(
+        try {
+            if (!imsMmTelManager.isAvailable(
                     MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
                     ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
-            Log.d(TAG, "IMS not registered over IWLAN for subId: " + subId);
+                Log.d(TAG, "IMS not registered over IWLAN for subId: " + subId);
+                return 0;
+            }
+        } catch (RuntimeException e) {
+            Log.e(TAG, "IMS Manager is not available.", e);
             return 0;
         }
-
         CarrierConfigManager configManager =
                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         PersistableBundle config = configManager.getConfigForSubId(subId);
@@ -406,11 +430,26 @@
         public static final int CMD_INTERFACE_DESTROYED = 4;
         public static final int CMD_INTERFACE_DOWN = 5;
         public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE = 6;
+        public static final int CMD_CONNECT_MODE_READY = 10;
+
         private final State mIdleState = new IdleState();
         private final State mStartedState = new StartedState();
         private final State mScanOnlyModeState = new ScanOnlyModeState();
         private final State mConnectModeState = new ConnectModeState();
 
+        private final Listener mClientModeImplListener = new Listener() {
+            @Override
+            public void onStarted() {
+                sendMessage(CMD_CONNECT_MODE_READY);
+            }
+
+            @Override
+            public void onStopped() {}
+
+            @Override
+            public void onStartFailure() {};
+        };
+
         private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() {
             @Override
             public void onDestroyed(String ifaceName) {
@@ -446,9 +485,9 @@
 
             // CHECKSTYLE:OFF IndentationCheck
             addState(mIdleState);
-            addState(mStartedState);
-                addState(mScanOnlyModeState, mStartedState);
-                addState(mConnectModeState, mStartedState);
+                addState(mStartedState, mIdleState);
+                    addState(mScanOnlyModeState, mStartedState);
+                    addState(mConnectModeState, mStartedState);
             // CHECKSTYLE:ON IndentationCheck
 
             setInitialState(mIdleState);
@@ -464,6 +503,11 @@
             }
 
             @Override
+            public void exit() {
+                mModeListener.onStopped();
+            }
+
+            @Override
             public boolean processMessage(Message message) {
                 switch (message.what) {
                     case CMD_START:
@@ -540,16 +584,18 @@
                         Log.e(TAG, "Detected an interface down, reporting failure to "
                                 + "SelfRecovery");
                         mClientModeImpl.failureDetected(SelfRecovery.REASON_STA_IFACE_DOWN);
-                        transitionTo(mIdleState);
+                        // once interface down, nothing else to do...  stop the state machine
+                        quitNow();
                         break;
                     case CMD_INTERFACE_STATUS_CHANGED:
                         boolean isUp = message.arg1 == 1;
                         onUpChanged(isUp);
                         break;
                     case CMD_INTERFACE_DESTROYED:
-                        Log.d(TAG, "interface destroyed - client mode stopping");
+                        Log.e(TAG, "interface destroyed - client mode stopping");
                         mClientInterfaceName = null;
-                        transitionTo(mIdleState);
+                        // once interface destroyed, nothing else to do...  stop the state machine
+                        quitNow();
                         break;
                     default:
                         return NOT_HANDLED;
@@ -570,10 +616,7 @@
                     mIfaceIsUp = false;
                 }
 
-                // once we leave started, nothing else to do...  stop the state machine
                 mRole = ROLE_UNSPECIFIED;
-                mStateMachine.quitNow();
-                mModeListener.onStopped();
             }
         }
 
@@ -615,19 +658,23 @@
             @Override
             public void enter() {
                 Log.d(TAG, "entering ConnectModeState");
+                mClientModeImpl.registerModeListener(mClientModeImplListener);
                 mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
                         mClientInterfaceName);
-                mModeListener.onStarted();
-                updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
-                        WifiManager.WIFI_STATE_ENABLING);
-
-                // Inform sar manager that wifi is Enabled
-                mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
             }
 
             @Override
             public boolean processMessage(Message message) {
                 switch (message.what) {
+                    case CMD_CONNECT_MODE_READY:
+                        Log.d(TAG, "ConnectMode is ready");
+                        mModeListener.onStarted();
+                        updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
+                                WifiManager.WIFI_STATE_ENABLING);
+
+                        // Inform sar manager that wifi is Enabled
+                        mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
+                        break;
                     case CMD_SWITCH_TO_CONNECT_MODE:
                         int newRole = message.arg1;
                         // Already in connect mode, only switching the connectivity roles.
diff --git a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
index 4f7b4e8..053314d 100644
--- a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
+++ b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wifi;
 
+import static android.app.Notification.VISIBILITY_SECRET;
+
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Intent;
@@ -95,6 +97,7 @@
                 .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag))
                 .addAction(connectAction)
                 .addAction(allNetworksAction)
+                .setVisibility(VISIBILITY_SECRET)
                 .build();
     }
 
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/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java
index 1ff8368..57db9f1 100644
--- a/service/java/com/android/server/wifi/HostapdHal.java
+++ b/service/java/com/android/server/wifi/HostapdHal.java
@@ -29,6 +29,7 @@
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.SoftApConfiguration.BandType;
 import android.net.wifi.WifiManager;
+import android.net.wifi.nl80211.NativeWifiClient;
 import android.os.Handler;
 import android.os.IHwBinder.DeathRecipient;
 import android.os.RemoteException;
@@ -39,6 +40,7 @@
 import com.android.server.wifi.WifiNative.HostapdDeathEventHandler;
 import com.android.server.wifi.util.ApConfigUtil;
 import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.WifiNative.SoftApListener;
 import com.android.wifi.resources.R;
 
 import java.util.ArrayList;
@@ -51,6 +53,9 @@
 
 import javax.annotation.concurrent.ThreadSafe;
 
+import vendor.qti.hardware.wifi.hostapd.V1_0.IHostapdVendor;
+import vendor.qti.hardware.wifi.hostapd.V1_0.IHostapdVendorIfaceCallback;
+
 /**
  * To maintain thread-safety, the locking protocol is that every non-static method (regardless of
  * access level) acquires mLock.
@@ -65,6 +70,8 @@
 
     private final Object mLock = new Object();
     private boolean mVerboseLoggingEnabled = false;
+    private boolean mSoftApOcvFeatureEnabled = false;
+    private boolean mSoftApBeaconProtFeatureEnabled = false;
     private final Context mContext;
     private final Handler mEventHandler;
     private boolean mForceApChannel = false;
@@ -77,10 +84,12 @@
     // Hostapd HAL interface objects
     private IServiceManager mIServiceManager = null;
     private IHostapd mIHostapd;
+    private IHostapdVendor mIHostapdVendor;
     private HashMap<String, Runnable> mSoftApFailureListeners = new HashMap<>();
     private HostapdDeathEventHandler mDeathEventHandler;
     private ServiceManagerDeathRecipient mServiceManagerDeathRecipient;
     private HostapdDeathRecipient mHostapdDeathRecipient;
+    private HostapdVendorDeathRecipient mHostapdVendorDeathRecipient;
     // Death recipient cookie registered for current supplicant instance.
     private long mDeathRecipientCookie = 0;
 
@@ -125,11 +134,47 @@
         }
     }
 
+    private class HostapdVendorDeathRecipient implements DeathRecipient {
+        @Override
+        public void serviceDied(long cookie) {
+            mEventHandler.post(() -> {
+                synchronized (mLock) {
+                    Log.w(TAG, "IHostapdVendor died: cookie=" + cookie);
+                    hostapdServiceDiedHandler(cookie);
+                }
+            });
+        }
+    }
+
     public HostapdHal(Context context, Handler handler) {
         mContext = context;
         mEventHandler = handler;
+
         mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient();
         mHostapdDeathRecipient = new HostapdDeathRecipient();
+        mHostapdVendorDeathRecipient = new HostapdVendorDeathRecipient();
+    }
+
+    /**
+     * Enable/Disable SoftAp OCV Feature.
+     *
+     * @param enable true to enable, false to disable.
+     */
+    void enableSoftApOcvFeature(boolean enable) {
+        synchronized (mLock) {
+            mSoftApOcvFeatureEnabled = enable;
+        }
+    }
+
+    /**
+     * Enable/Disable SoftAp Beacon Protection Feature.
+     *
+     * @param enable true to enable, false to disable.
+     */
+    void enableSoftApBeaconProtFeature(boolean enable) {
+        synchronized (mLock) {
+            mSoftApBeaconProtFeatureEnabled = enable;
+        }
     }
 
     /**
@@ -211,7 +256,7 @@
 
     /**
      * Registers a service notification for the IHostapd service, which triggers intialization of
-     * the IHostapd
+     * the IHostapd and IHostapdVendor
      * @return true if the service notification was successfully registered
      */
     public boolean initialize() {
@@ -220,6 +265,7 @@
                 Log.i(TAG, "Registering IHostapd service ready callback.");
             }
             mIHostapd = null;
+            mIHostapdVendor = null;
             if (mIServiceManager != null) {
                 // Already have an IServiceManager and serviceNotification registered, don't
                 // don't register another.
@@ -237,7 +283,7 @@
                 /* TODO(b/33639391) : Use the new IHostapd.registerForNotifications() once it
                    exists */
                 if (!mIServiceManager.registerForNotifications(
-                        IHostapd.kInterfaceName, "", mServiceNotificationCallback)) {
+                        IHostapd.kInterfaceName, "default", mServiceNotificationCallback)) {
                     Log.e(TAG, "Failed to register for notifications to "
                             + IHostapd.kInterfaceName);
                     mIServiceManager = null; // Will need to register a new ServiceNotification
@@ -325,9 +371,14 @@
             // Setup log level
             setLogLevel();
         }
+
+        if (!initHostapdVendorService())
+            Log.e(TAG, "Failed to init HostapdVendor service");
+
         return true;
     }
 
+
     /**
      * Enable force-soft-AP-channel mode which takes effect when soft AP starts next time
      * @param forcedApChannel The forced IEEE channel number
@@ -365,7 +416,7 @@
             mConfig5gChannelList =
                 mContext.getResources().getString(R.string.config_wifiSoftap5gChannelList);
             if (TextUtils.isEmpty(mConfig5gChannelList)) {
-                mConfig5gChannelList = "34-173";
+                mConfig5gChannelList = "34-177";
             } else {
                 retVal = true;
             }
@@ -375,7 +426,7 @@
             mConfig6gChannelList =
                 mContext.getResources().getString(R.string.config_wifiSoftap6gChannelList);
             if (TextUtils.isEmpty(mConfig6gChannelList)) {
-                mConfig6gChannelList = "1-254";
+                mConfig6gChannelList = "1-233";
             } else {
                 retVal = true;
             }
@@ -560,6 +611,7 @@
         }
     }
 
+
     /**
      * Remove a previously connected client.
      *
@@ -638,6 +690,7 @@
     private void clearState() {
         synchronized (mLock) {
             mIHostapd = null;
+            mIHostapdVendor = null;
         }
     }
 
@@ -732,6 +785,28 @@
     }
 
     /**
+     * Terminate the hostapd daemon if already running, otherwise ignore.
+     */
+    public void terminateIfRunning() {
+        synchronized (mLock) {
+            WifiInjector wifiInjector = WifiInjector.getInstance();
+            if (wifiInjector.getPropertyService().get("init.svc.hostapd", "").equals("running") ||
+                     wifiInjector.getPropertyService().get("init.svc.hostapd_fst", "").equals("running")) {
+                try {
+                    Log.i(TAG, "Hostapd daemon is running, Terminate gracefully");
+                    IHostapd.getService().terminate();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "IHostapd.getService.terminate exception: " + e);
+                } catch (NoSuchElementException e) {
+                    // |NoSuchElementException| expected when hostapd is not running
+                    // It shouldn't happen as we are calling getService only when hostapd is running
+                    Log.e(TAG, "NoSuchElementException on calling IHostapd.getService though hostapd service is running.");
+                }
+            }
+        }
+    }
+
+    /**
      * Wrapper functions to access static HAL methods, created to be mockable in unit tests
      */
     @VisibleForTesting
@@ -828,6 +903,33 @@
         return encryptionType;
     }
 
+    private static int getVendorEncryptionType(SoftApConfiguration localConfig) {
+        int encryptionType;
+        switch (localConfig.getSecurityType()) {
+            case SoftApConfiguration.SECURITY_TYPE_OPEN:
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorEncryptionType.NONE;
+                break;
+            case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK:
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorEncryptionType.WPA2;
+                break;
+            case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE:
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorEncryptionType.SAE;
+                break;
+            case SoftApConfiguration.SECURITY_TYPE_OWE:
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorEncryptionType.OWE;
+                break;
+            case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION:
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.VendorEncryptionType.SAE_TRANSITION;
+                break;
+            default:
+                // We really shouldn't default to None, but this was how NetworkManagementService
+                // used to do this.
+                encryptionType = vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorEncryptionType.NONE;
+                break;
+        }
+        return encryptionType;
+    }
+
     private static int getHalBandMask(int apBand) {
         int bandMask = 0;
 
@@ -1036,6 +1138,489 @@
         }
     }
 
+
+    /* ######################### Hostapd Vendor change ###################### */
+    // Keep hostapd vendor changes below this line to have minimal conflicts during merge/upgrade
+
+    /**
+     * Uses the IServiceManager to check if the device is running V1_1 of the hostapd vendor HAL from
+     * the VINTF for the device.
+     * @return true if supported, false otherwise.
+     */
+    private boolean isVendorV1_1() {
+        return checkHalVersionByInterfaceName(
+                vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.kInterfaceName);
+    }
+
+    /**
+     * Uses the IServiceManager to check if the device is running V1_2 of the hostapd vendor HAL from
+     * the VINTF for the device.
+     * @return true if supported, false otherwise.
+     */
+    private boolean isVendorV1_2() {
+        return checkHalVersionByInterfaceName(
+                vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.kInterfaceName);
+    }
+
+    /**
+     * Link to death for IHostapdVendor object.
+     * @return true on success, false otherwise.
+     */
+    private boolean linkToHostapdVendorDeath() {
+        synchronized (mLock) {
+            if (mIHostapdVendor == null) return false;
+            try {
+                if (!mIHostapdVendor.linkToDeath(mHostapdVendorDeathRecipient, mDeathRecipientCookie)) {
+                    Log.wtf(TAG, "Error on linkToDeath on IHostapdVendor");
+                    hostapdServiceDiedHandler(mDeathRecipientCookie);
+                    return false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "IHostapdVendor.linkToDeath exception", e);
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Initialize the IHostapdVendor object.
+     * @return true on success, false otherwise.
+     */
+    public boolean initHostapdVendorService() {
+        synchronized (mLock) {
+            try {
+                mIHostapdVendor = getHostapdVendorMockable();
+            } catch (RemoteException e) {
+                Log.e(TAG, "IHostapdVendor.getService exception: " + e);
+                return false;
+            }
+            if (mIHostapdVendor == null) {
+                Log.e(TAG, "Got null IHostapdVendor service. Stopping hostapdVendor HIDL startup");
+                return false;
+            }
+            if (!linkToHostapdVendorDeath()) {
+                mIHostapdVendor = null;
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Wrapper to Convert IHostapd.AcsFrequencyRange to IHostapdVendor.AcsFrequencyRange
+     */
+    private List<vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.AcsFrequencyRange>
+            toVendorAcsFreqRanges(@BandType int band) {
+        List<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange>
+                acsFrequencyRanges = toAcsFreqRanges(band);
+
+        List<vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.AcsFrequencyRange>
+                vendorAcsFreqRanges = new ArrayList<>();
+
+        for (android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange acsFrequencyRange : acsFrequencyRanges) {
+            vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.AcsFrequencyRange acsFreqRange =
+                    new vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.AcsFrequencyRange();
+            acsFreqRange.start = acsFrequencyRange.start;
+            acsFreqRange.end = acsFrequencyRange.end;
+            vendorAcsFreqRanges.add(acsFreqRange);
+        }
+
+        return vendorAcsFreqRanges;
+    }
+
+    /**
+     * Add and start a new vendor access point.
+     *
+     * @param ifaceName Name of the softap interface.
+     * @param config Configuration to use for the AP.
+     * @param listener Callback for AP events.
+     * @return true on success, false otherwise.
+     */
+    public boolean addVendorAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config, SoftApListener listener) {
+        synchronized (mLock) {
+            final String methodStr = "addVendorAccessPoint";
+            WifiApConfigStore apConfigStore = WifiInjector.getInstance().getWifiApConfigStore();
+            IHostapdVendor.VendorIfaceParams vendorIfaceParams = new IHostapdVendor.VendorIfaceParams();
+            IHostapd.IfaceParams ifaceParams = vendorIfaceParams.ifaceParams;
+            ifaceParams.ifaceName = ifaceName;
+            ifaceParams.hwModeParams.enable80211N = true;
+            ifaceParams.hwModeParams.enable80211AC =
+                    mContext.getResources().getBoolean(
+                            R.bool.config_wifi_softap_ieee80211ac_supported);
+            vendorIfaceParams.bridgeIfaceName = "";
+
+            int band = config.getBand();
+            if (mForceApChannel) {
+                ifaceParams.channelParams.enableAcs = false;
+                ifaceParams.channelParams.channel = mForcedApChannel;
+                band = mForcedApBand;
+            } else if (ApConfigUtil.isAcsSupported(mContext)) {
+                ifaceParams.channelParams.enableAcs = true;
+                ifaceParams.channelParams.acsShouldExcludeDfs = !mContext.getResources()
+                        .getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs);
+            } else {
+                ifaceParams.channelParams.enableAcs = false;
+                ifaceParams.channelParams.channel = config.getChannel();
+            }
+
+            android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 =
+                    prepareNetworkParams(config);
+            if (nwParamsV1_2 == null) return false;
+            if (!checkHostapdVendorAndLogFailure(methodStr)) return false;
+            try {
+                if (apConfigStore.getDualSapStatus()) {
+                    String bridgeIfaceName = apConfigStore.getBridgeInterface();
+                    vendorIfaceParams.bridgeIfaceName = (bridgeIfaceName != null) ? bridgeIfaceName : "";
+                }
+                ifaceParams.channelParams.band = getHalBand(band);
+
+                if (!isVendorV1_1() && !isVendorV1_2()) {
+                    if (mIHostapdVendor == null) {
+                        Log.e(TAG, "Failed to get mIHostapdVendor");
+                        return false;
+                    }
+
+                    IHostapdVendorIfaceCallback vendorcallback =
+                        new HostapdVendorIfaceHalCallback(ifaceName, listener);
+                    if (vendorcallback == null) {
+                        Log.e(TAG, "Failed to create vendorcallback instance");
+                        return false;
+                    }
+
+                    if (!registerVendorCallback(ifaceParams.ifaceName,
+                                                mIHostapdVendor,
+                                                vendorcallback)) {
+                        Log.e(TAG, "Failed to register Hostapd Vendor callback");
+                        return false;
+                    }
+
+                    HostapdStatus status =
+                        mIHostapdVendor.addVendorAccessPoint(vendorIfaceParams,
+                                                             nwParamsV1_2.V1_0);
+                    if (checkVendorStatusAndLogFailure(status, methodStr))
+                        return true;
+                } else {
+                    HostapdStatus status;
+                    vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorIfaceParams
+                         vendorIfaceParams1_1 =
+                            new vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.VendorIfaceParams();
+                    vendorIfaceParams1_1.VendorV1_0 = vendorIfaceParams;
+                    vendorIfaceParams1_1.vendorChannelParams.channelParams = ifaceParams.channelParams;
+                    vendorIfaceParams1_1.vendorEncryptionType = getVendorEncryptionType(config);
+                    vendorIfaceParams1_1.oweTransIfaceName = (config.getOweTransIfaceName() != null) ? config.getOweTransIfaceName() : "";
+                    if (ifaceParams.channelParams.enableAcs) {
+                        if ((band & SoftApConfiguration.BAND_2GHZ) != 0) {
+                            vendorIfaceParams1_1.vendorChannelParams.acsChannelRanges.addAll(
+                                    toVendorAcsChannelRanges(mContext.getResources().getString(
+                                        R.string.config_wifiSoftap2gChannelList)));
+                        }
+                        if ((band & SoftApConfiguration.BAND_5GHZ) != 0) {
+                            vendorIfaceParams1_1.vendorChannelParams.acsChannelRanges.addAll(
+                                    toVendorAcsChannelRanges(mContext.getResources().getString(
+                                        R.string.config_wifiSoftap5gChannelList)));
+                        }
+                    }
+
+                    HostapdVendorIfaceHalCallbackV1_1 vendorcallback_1_1 =
+                        new HostapdVendorIfaceHalCallbackV1_1(ifaceName, listener);
+                    if (vendorcallback_1_1 == null) {
+                        Log.e(TAG, "Failed to create vendorcallback instance");
+                        return false;
+                    }
+
+                    if (!registerVendorCallback_1_1(ifaceParams.ifaceName,
+                                                    vendorcallback_1_1)) {
+                        Log.e(TAG, "Failed to register Hostapd Vendor callback");
+                        return false;
+                    }
+
+                    if (isVendorV1_2()) {
+                        vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.VendorIfaceParams
+                            vendorIfaceParams1_2 =
+                                new vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.VendorIfaceParams();
+                        vendorIfaceParams1_2.VendorV1_1 = vendorIfaceParams1_1;
+
+                        vendorIfaceParams1_2.hwModeParams.enable80211AX =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftapIeee80211axSupported);
+                        vendorIfaceParams1_2.hwModeParams.enable6GhzBand =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftap6ghzSupported);
+                        vendorIfaceParams1_2.hwModeParams.enableHeSingleUserBeamformer =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftapHeSuBeamformerSupported);
+                        vendorIfaceParams1_2.hwModeParams.enableHeSingleUserBeamformee =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftapHeSuBeamformeeSupported);
+                        vendorIfaceParams1_2.hwModeParams.enableHeMultiUserBeamformer =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftapHeMuBeamformerSupported);
+                        vendorIfaceParams1_2.hwModeParams.enableHeTargetWakeTime =
+                                mContext.getResources().getBoolean(
+                                    R.bool.config_wifiSoftapHeTwtSupported);
+                        vendorIfaceParams1_2.channelParams.bandMask = getHalBandMask(band);
+
+                        // Prepare freq ranges/lists if needed
+                        if (ifaceParams.channelParams.enableAcs
+                                && isSendFreqRangesNeeded(band)) {
+                            if ((band & SoftApConfiguration.BAND_2GHZ) != 0) {
+                                vendorIfaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
+                                        toVendorAcsFreqRanges(SoftApConfiguration.BAND_2GHZ));
+                            }
+                            if ((band & SoftApConfiguration.BAND_5GHZ) != 0) {
+                                vendorIfaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
+                                        toVendorAcsFreqRanges(SoftApConfiguration.BAND_5GHZ));
+                            }
+                            if ((band & SoftApConfiguration.BAND_6GHZ) != 0) {
+                                vendorIfaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
+                                        toVendorAcsFreqRanges(SoftApConfiguration.BAND_6GHZ));
+                            }
+                        }
+
+                        vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.VendorNetworkParams
+                            vendorNetworkParams1_2 =
+                                new vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.VendorNetworkParams();
+                        vendorNetworkParams1_2.V1_0 = nwParamsV1_2.V1_0;
+                        vendorNetworkParams1_2.passphrase = nwParamsV1_2.passphrase;
+                        vendorNetworkParams1_2.vendorEncryptionType = getVendorEncryptionType(config);
+                        vendorNetworkParams1_2.enableOCV = mSoftApOcvFeatureEnabled;
+                        vendorNetworkParams1_2.enableBeaconProtection = mSoftApBeaconProtFeatureEnabled;
+
+                        vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor iHostapdVendorV1_2 =
+                            getHostapdVendorMockableV1_2();
+                        if (iHostapdVendorV1_2 == null) {
+                            Log.e(TAG, "Failed to get V1_2.IHostapdVendor");
+                            return false;
+                        }
+                        status = iHostapdVendorV1_2.addVendorAccessPoint_1_2(vendorIfaceParams1_2, vendorNetworkParams1_2);
+                    } else {
+                        vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor iHostapdVendorV1_1 =
+                            getHostapdVendorMockableV1_1();
+                        if (iHostapdVendorV1_1 == null) {
+                            Log.e(TAG, "Failed to get V1_1.IHostapdVendor");
+                            return false;
+                        }
+                        status = iHostapdVendorV1_1.addVendorAccessPoint_1_1(vendorIfaceParams1_1, nwParamsV1_2.V1_0);
+                    }
+
+                    if (checkVendorStatusAndLogFailure(status, methodStr))
+                        return true;
+                }
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Unrecognized apBand: " + band);
+                return false;
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    protected IHostapdVendor getHostapdVendorMockable() throws RemoteException {
+        synchronized (mLock) {
+            return IHostapdVendor.getService();
+        }
+    }
+
+    @VisibleForTesting
+    protected vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor getHostapdVendorMockableV1_1()
+            throws RemoteException {
+        synchronized (mLock) {
+            try {
+                return vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.castFrom(mIHostapdVendor);
+            } catch (NoSuchElementException e) {
+                Log.e(TAG, "Failed to get IHostapdVendorV1_1", e);
+                return null;
+            }
+        }
+    }
+
+    @VisibleForTesting
+    protected vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor getHostapdVendorMockableV1_2()
+            throws RemoteException {
+        synchronized (mLock) {
+            try {
+                return vendor.qti.hardware.wifi.hostapd.V1_2.IHostapdVendor.castFrom(mIHostapdVendor);
+            } catch (NoSuchElementException e) {
+                Log.e(TAG, "Failed to get IHostapdVendorV1_2", e);
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Convert channel list string like '1-6,11' to list of AcsChannelRanges
+     */
+    private List<vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.AcsChannelRange>
+            toVendorAcsChannelRanges(String channelListStr) {
+        ArrayList<vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.AcsChannelRange> acsChannelRanges =
+                new ArrayList<>();
+
+        for (String channelRange : channelListStr.split(",")) {
+            vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.AcsChannelRange acsChannelRange =
+                    new vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor.AcsChannelRange();
+            try {
+                if (channelRange.contains("-")) {
+                    String[] channels  = channelRange.split("-");
+                    if (channels.length != 2) {
+                        Log.e(TAG, "Unrecognized channel range, length is " + channels.length);
+                        continue;
+                    }
+                    int start = Integer.parseInt(channels[0].trim());
+                    int end = Integer.parseInt(channels[1].trim());
+                    if (start > end) {
+                        Log.e(TAG, "Invalid channel range, from " + start + " to " + end);
+                        continue;
+                    }
+                    acsChannelRange.start = start;
+                    acsChannelRange.end = end;
+                } else {
+                    acsChannelRange.start = Integer.parseInt(channelRange.trim());
+                    acsChannelRange.end = acsChannelRange.start;
+                }
+            } catch (NumberFormatException e) {
+                // Ignore malformed value
+                Log.e(TAG, "Malformed channel value detected: " + e);
+                continue;
+            }
+            acsChannelRanges.add(acsChannelRange);
+        }
+        return acsChannelRanges;
+    }
+
+    /**
+     * Check if the device is running hostapd vendor service.
+     * @return
+     */
+    public boolean isVendorHostapdHal() {
+        return mIHostapdVendor != null;
+    }
+
+    /**
+     * Returns false if HostapdVendor is null, and logs failure to call methodStr
+     */
+    private boolean checkHostapdVendorAndLogFailure(String methodStr) {
+        synchronized (mLock) {
+            if (mIHostapdVendor == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", IHostapdVendor is null");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Returns true if provided status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkVendorStatusAndLogFailure(HostapdStatus status,
+            String methodStr) {
+        synchronized (mLock) {
+            if (status.code != HostapdStatusCode.SUCCESS) {
+                Log.e(TAG, "IHostapdVendor." + methodStr + " failed: " + status.code
+                        + ", " + status.debugMessage);
+                return false;
+            } else {
+                if (mVerboseLoggingEnabled) {
+                    Log.e(TAG, "IHostapdVendor." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
+    private class HostapdVendorIfaceHalCallback extends IHostapdVendorIfaceCallback.Stub {
+        private SoftApListener mSoftApListener;
+
+        HostapdVendorIfaceHalCallback(@NonNull String ifaceName, SoftApListener listener) {
+           mSoftApListener = listener;
+        }
+
+        @Override
+        public void onStaConnected(byte[/* 6 */] bssid) {
+            if (bssid == null) return;
+            NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(bssid));
+            Log.d(TAG, "Client " + client.getMacAddress() + " connected.");
+            mSoftApListener.onConnectedClientsChanged(client, true);
+        }
+
+        @Override
+        public void onStaDisconnected(byte[/* 6 */] bssid) {
+            if (bssid == null) return;
+            NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(bssid));
+            Log.d(TAG, "Client " + client.getMacAddress() + " disconnected.");
+            mSoftApListener.onConnectedClientsChanged(client, false);
+        }
+    }
+
+    /** See IHostapdVendor.hal for documentation */
+    private boolean registerVendorCallback(@NonNull String ifaceName,
+            IHostapdVendor service, IHostapdVendorIfaceCallback callback) {
+        synchronized (mLock) {
+            final String methodStr = "registerVendorCallback";
+            if (service == null) return false;
+            try {
+                HostapdStatus status =  service.registerVendorCallback(ifaceName, callback);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+
+    private class HostapdVendorIfaceHalCallbackV1_1 extends
+            vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendorIfaceCallback.Stub {
+        private SoftApListener mSoftApListener;
+
+        HostapdVendorIfaceHalCallbackV1_1(@NonNull String ifaceName, SoftApListener listener) {
+           mSoftApListener = listener;
+        }
+
+        @Override
+        public void onStaConnected(byte[/* 6 */] bssid) {
+            if (bssid == null) return;
+            NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(bssid));
+            Log.d(TAG, "Client " + client.getMacAddress() + " connected.");
+            mSoftApListener.onConnectedClientsChanged(client, true);
+        }
+
+        @Override
+        public void onStaDisconnected(byte[/* 6 */] bssid) {
+            if (bssid == null) return;
+            NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(bssid));
+            Log.d(TAG, "Client " + client.getMacAddress() + " disconnected.");
+            mSoftApListener.onConnectedClientsChanged(client, false);
+        }
+        @Override
+        public void onFailure(String ifaceName) {
+            Log.w(TAG, "Failure on iface " + ifaceName);
+            mSoftApListener.onFailure();
+        }
+    }
+
+    private boolean registerVendorCallback_1_1(@NonNull String ifaceName,
+            vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendorIfaceCallback callback) {
+        synchronized (mLock) {
+            String methodStr = "registerVendorCallback_1_1";
+            try {
+                vendor.qti.hardware.wifi.hostapd.V1_1.IHostapdVendor iHostapdVendorV1_1 =
+                    getHostapdVendorMockableV1_1();
+                if (iHostapdVendorV1_1 == null) return false;
+                HostapdStatus status =  iHostapdVendorV1_1.registerVendorCallback_1_1(
+                    ifaceName, callback);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+
+
     /**
      * Set the debug log level for hostapd.
      *
@@ -1064,4 +1649,12 @@
             return false;
         }
     }
+
+    public boolean is11acSupportEnabled() {
+        return mContext.getResources().getBoolean(R.bool.config_wifi_softap_ieee80211ac_supported);
+    }
+
+    public boolean is11axSupportEnabled() {
+        return mContext.getResources().getBoolean(R.bool.config_wifiSoftapIeee80211axSupported);
+    }
 }
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/NetworkListSharedStoreData.java b/service/java/com/android/server/wifi/NetworkListSharedStoreData.java
index 1b0dc53..7e87e27 100644
--- a/service/java/com/android/server/wifi/NetworkListSharedStoreData.java
+++ b/service/java/com/android/server/wifi/NetworkListSharedStoreData.java
@@ -17,12 +17,12 @@
 package com.android.server.wifi;
 
 import android.content.Context;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 
 /**
  * Serialization & Deserialization of shared WiFi network configurations.
  */
 public class NetworkListSharedStoreData extends NetworkListStoreData {
-
     public NetworkListSharedStoreData(Context context) {
         super(context);
     }
@@ -32,5 +32,12 @@
         // Shared general store.
         return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
     }
+    @Override
+    public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+        // Shared general store.
+        if (staId == STA_SECONDARY)
+            return WifiConfigStore.QTI_STORE_FILE_SHARED_SECONDARY;
+        return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
+    }
 }
 
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/NetworkSuggestionStoreData.java b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java
index 11067f6..eccf5db 100644
--- a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java
+++ b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java
@@ -151,6 +151,12 @@
         return WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS;
     }
 
+    @Override
+    public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+        //Network Suggestion is not applicable for secodary.
+        return WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS;
+    }
+
     /**
      * Serialize the map of package name to network suggestions to an output stream in XML format.
      *
diff --git a/service/java/com/android/server/wifi/QtiClientModeImpl.java b/service/java/com/android/server/wifi/QtiClientModeImpl.java
new file mode 100644
index 0000000..ee3ac57
--- /dev/null
+++ b/service/java/com/android/server/wifi/QtiClientModeImpl.java
@@ -0,0 +1,5925 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT;
+import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
+
+import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.DhcpResultsParcelable;
+import android.net.InvalidPacketException;
+import android.net.IpConfiguration;
+import android.net.KeepalivePacketData;
+import android.net.Layer2PacketParcelable;
+import android.net.LinkProperties;
+import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NattKeepalivePacketData;
+import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
+import android.net.NetworkCapabilities;
+import android.net.NetworkFactory;
+import android.net.NetworkRequest;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkProvider;
+import android.net.SocketKeepalive;
+import android.net.StaticIpConfiguration;
+import android.net.TcpKeepalivePacketData;
+import android.net.Uri;
+import android.net.ip.IIpClient;
+import android.net.ip.IpClientCallbacks;
+import android.net.ip.IpClientManager;
+import com.android.net.module.util.Inet4AddressUtils;
+import android.net.shared.Layer2Information;
+import android.net.shared.ProvisioningConfiguration;
+import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
+import android.net.util.MacAddressUtils;
+import android.net.util.NetUtils;
+import android.net.wifi.IActionListener;
+import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiAnnotations.WifiStandard;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.DeviceMobilityState;
+import android.net.wifi.WifiNetworkAgentSpecifier;
+import android.net.wifi.WifiScanner;
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.nl80211.DeviceWiphyCapabilities;
+import android.net.wifi.nl80211.WifiNl80211Manager;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.os.BatteryStatsManager;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.system.OsConstants;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.MessageUtils;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.server.wifi.MboOceController.BtmFrameData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData;
+import com.android.server.wifi.hotspot2.AnqpEvent;
+import com.android.server.wifi.hotspot2.IconEvent;
+import com.android.server.wifi.hotspot2.NetworkDetail;
+import com.android.server.wifi.hotspot2.PasspointManager;
+import com.android.server.wifi.hotspot2.WnmData;
+import com.android.server.wifi.p2p.WifiP2pServiceImpl;
+import com.android.server.wifi.proto.WifiStatsLog;
+import com.android.server.wifi.proto.nano.WifiMetricsProto;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
+import com.android.server.wifi.util.ExternalCallbackTracker;
+import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.util.RssiUtil;
+import com.android.server.wifi.util.WifiPermissionsUtil;
+import com.android.server.wifi.util.WifiPermissionsWrapper;
+import com.android.server.wifi.util.ScanResultUtil;
+import com.android.server.wifi.WifiNative.WifiGenerationStatus;
+import com.android.wifi.resources.R;
+
+import java.io.BufferedReader;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of ClientMode.  Event handling for Client mode logic is done here,
+ * and all changes in connectivity state are initiated here.
+ *
+ * @hide
+ */
+public class QtiClientModeImpl extends StateMachine {
+
+    private static final String NETWORKTYPE = "WIFI";
+    @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100;
+    @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200;
+    @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000;
+
+    // Association rejection reason codes
+    @VisibleForTesting
+    protected static final int REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
+
+    private static final String TAG = "QtiWifiClientModeImpl";
+
+    private static final int ONE_HOUR_MILLI = 1000 * 60 * 60;
+
+    private static final String GOOGLE_OUI = "DA-A1-19";
+
+    private static final String EXTRA_OSU_ICON_QUERY_BSSID = "BSSID";
+    private static final String EXTRA_OSU_ICON_QUERY_FILENAME = "FILENAME";
+    private static final String EXTRA_OSU_PROVIDER = "OsuProvider";
+    private static final String EXTRA_UID = "uid";
+    private static final String EXTRA_PACKAGE_NAME = "PackageName";
+    private static final String EXTRA_PASSPOINT_CONFIGURATION = "PasspointConfiguration";
+    private static final int IPCLIENT_STARTUP_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes!
+    private static final int IPCLIENT_SHUTDOWN_TIMEOUT_MS = 10_000; // 10 seconds
+
+    private boolean mVerboseLoggingEnabled = false;
+    private final WifiPermissionsWrapper mWifiPermissionsWrapper;
+
+    /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blocklisting
+     * the corresponding BSSID.
+     */
+    private boolean mDidBlockListBSSID = false;
+
+    /**
+     * Log with error attribute
+     *
+     * @param s is string log
+     */
+    @Override
+    protected void loge(String s) {
+        Log.e(getName(), s);
+    }
+    @Override
+    protected void logd(String s) {
+        Log.d(getName(), s);
+    }
+    @Override
+    protected void log(String s) {
+        Log.d(getName(), s);
+    }
+    private final WifiMetrics mWifiMetrics;
+    private final WifiInjector mWifiInjector;
+    private final WifiMonitor mWifiMonitor;
+    private final WifiNative mWifiNative;
+    private final WifiPermissionsUtil mWifiPermissionsUtil;
+    private final WifiConfigManager mWifiConfigManager;
+    private final QtiWifiConnectivityManager mQtiWifiConnectivityManager;
+    private final BssidBlocklistMonitor mBssidBlocklistMonitor;
+    private final boolean mP2pSupported;
+    private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
+    private boolean mTemporarilyDisconnectWifi = false;
+    private final Clock mClock;
+    private final PropertyService mPropertyService;
+    private final BuildProperties mBuildProperties;
+    private final WifiScoreCard mWifiScoreCard;
+    private final WifiHealthMonitor mWifiHealthMonitor;
+    private final WifiScoreReport mWifiScoreReport;
+    private final WifiTrafficPoller mWifiTrafficPoller;
+    public WifiScoreReport getWifiScoreReport() {
+        return mWifiScoreReport;
+    }
+    private final PasspointManager mPasspointManager;
+    private final WifiDataStall mWifiDataStall;
+    private final LinkProbeManager mLinkProbeManager;
+    private final MboOceController mMboOceController;
+
+    private final McastLockManagerFilterController mMcastLockManagerFilterController;
+    private final ActivityManager mActivityManager;
+
+    private boolean mScreenOn = false;
+
+    private String mInterfaceName;
+
+    private int mLastSignalLevel = -1;
+    private String mLastBssid;
+    private int mLastNetworkId; // The network Id we successfully joined
+    // The subId used by WifiConfiguration with SIM credential which was connected successfully
+    private int mLastSubId;
+    private String mLastSimBasedConnectionCarrierName;
+
+    private boolean mIpReachabilityDisconnectEnabled = true;
+
+    /* if set to true then disconnect due to IP Reachability lost only when obtained for the first 10 seconds of L2 connection */
+    private boolean mDisconnectOnlyOnInitialIpReachability = true;
+    private boolean mIpReachabilityMonitorActive = true;
+
+    private void processRssiThreshold(byte curRssi, int reason,
+            WifiNative.WifiRssiEventHandler rssiHandler) {
+        if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) {
+            Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi);
+            return;
+        }
+        for (int i = 0; i < mRssiRanges.length; i++) {
+            if (curRssi < mRssiRanges[i]) {
+                // Assume sorted values(ascending order) for rssi,
+                // bounded by high(127) and low(-128) at extremeties
+                byte maxRssi = mRssiRanges[i];
+                byte minRssi = mRssiRanges[i - 1];
+                // This value of hw has to be believed as this value is averaged and has breached
+                // the rssi thresholds and raised event to host. This would be eggregious if this
+                // value is invalid
+                mWifiInfo.setRssi(curRssi);
+                updateCapabilities();
+                int ret = startRssiMonitoringOffload(maxRssi, minRssi, rssiHandler);
+                Log.d(TAG, "Re-program RSSI thresholds for " + getWhatToString(reason)
+                        + ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi
+                        + " ret=" + ret);
+                break;
+            }
+        }
+    }
+
+    private boolean mEnableRssiPolling = false;
+    // Accessed via Binder thread ({get,set}PollRssiIntervalMsecs), and the main Wifi thread.
+    private volatile int mPollRssiIntervalMsecs = -1;
+    private int mRssiPollToken = 0;
+    private int mOperationalMode = ClientModeImpl.DISABLED_MODE;
+
+    // variable indicating we are expecting a mode switch - do not attempt recovery for failures
+    private boolean mModeChange = false;
+
+    private boolean mBluetoothConnectionActive = false;
+
+    private PowerManager.WakeLock mSuspendWakeLock;
+
+    /**
+     * Maximum allowable interval in milliseconds between polling for RSSI and linkspeed
+     * information. This is also used as the polling interval for WifiTrafficPoller, which updates
+     * its data activity on every CMD_RSSI_POLL.
+     */
+    private static final int MAXIMUM_POLL_RSSI_INTERVAL_MSECS = 6000;
+
+    /**
+     * Interval in milliseconds between receiving a disconnect event
+     * while connected to a good AP, and handling the disconnect proper
+     */
+    private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000;
+
+    /**
+     * Delay between supplicant restarts upon failure to establish connection
+     */
+    private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000;
+
+    /**
+     * Number of times we attempt to restart supplicant
+     */
+    private static final int SUPPLICANT_RESTART_TRIES = 5;
+
+    /**
+     * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to
+     * a specific AP.
+     */
+    public static final String SUPPLICANT_BSSID_ANY = "any";
+
+    /**
+     * The link properties of the wifi interface.
+     * Do not modify this directly; use updateLinkProperties instead.
+     */
+    private LinkProperties mLinkProperties;
+
+    /* Tracks sequence number on a periodic scan message */
+    private int mPeriodicScanToken = 0;
+
+    private Context mContext;
+
+    private final Object mDhcpResultsParcelableLock = new Object();
+    @NonNull
+    private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable();
+
+    // NOTE: Do not return to clients - see syncRequestConnectionInfo()
+    private final ExtendedWifiInfo mWifiInfo;
+    private NetworkInfo mNetworkInfo;
+    private DetailedState mNetworkAgentState;
+    private SupplicantStateTracker mSupplicantStateTracker;    //TODO: UT: pass identity to supplicant tracker to announce station id and different broadcast msg.
+
+    // Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when
+    // wifi connects or fails to connect
+    private boolean mIsAutoRoaming = false;
+
+    // Roaming failure count
+    private int mRoamFailCount = 0;
+
+    // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY
+    // if we havent selected a BSSID for joining.
+    private String mTargetBssid = SUPPLICANT_BSSID_ANY;
+    // This one is used to track the current target network ID. This is used for error
+    // handling during connection setup since many error message from supplicant does not report
+    // SSID Once connected, it will be set to invalid
+    private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+    private long mLastDriverRoamAttempt = 0;
+    private WifiConfiguration mTargetWifiConfiguration = null;
+
+    int getPollRssiIntervalMsecs() {
+        if (mPollRssiIntervalMsecs > 0) {
+            return mPollRssiIntervalMsecs;
+        }
+        return Math.min(mContext.getResources().getInteger(
+                R.integer.config_wifiPollRssiIntervalMilliseconds),
+                        MAXIMUM_POLL_RSSI_INTERVAL_MSECS);
+    }
+
+    void setPollRssiIntervalMsecs(int newPollIntervalMsecs) {
+        mPollRssiIntervalMsecs = newPollIntervalMsecs;
+    }
+
+    /**
+     * Method to clear {@link #mTargetBssid} and reset the current connected network's
+     * bssid in wpa_supplicant after a roam/connect attempt.
+     */
+    public boolean clearTargetBssid(String dbg) {
+        WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
+        if (config == null) {
+            return false;
+        }
+        String bssid = SUPPLICANT_BSSID_ANY;
+        if (config.BSSID != null) {
+            bssid = config.BSSID;
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "force BSSID to " + bssid + "due to config");
+            }
+        }
+        if (mVerboseLoggingEnabled) {
+            logd(dbg + " clearTargetBssid " + bssid + " key=" + config.getKey());
+        }
+        mTargetBssid = bssid;
+        return mWifiNative.setConfiguredNetworkBSSID(mInterfaceName, bssid);
+    }
+
+    /**
+     * Set Config's default BSSID (for association purpose) and {@link #mTargetBssid}
+     * @param config config need set BSSID
+     * @param bssid  default BSSID to assocaite with when connect to this network
+     * @return false -- does not change the current default BSSID of the configure
+     *         true -- change the  current default BSSID of the configur
+     */
+    private boolean setTargetBssid(WifiConfiguration config, String bssid) {
+        if (config == null || bssid == null) {
+            return false;
+        }
+        if (config.BSSID != null) {
+            bssid = config.BSSID;
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "force BSSID to " + bssid + "due to config");
+            }
+        }
+        if (mVerboseLoggingEnabled) {
+            Log.d(TAG, "setTargetBssid set to " + bssid + " key=" + config.getKey());
+        }
+        mTargetBssid = bssid;
+        config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid);
+        return true;
+    }
+
+    private volatile IpClientManager mIpClient;
+    private IpClientCallbacksImpl mIpClientCallbacks;
+
+    // Channel for sending replies.
+    private AsyncChannel mReplyChannel = new AsyncChannel();
+
+    // Used to initiate a connection with WifiP2pService
+    private AsyncChannel mWifiP2pChannel;
+
+    @GuardedBy("mNetworkAgentLock")
+    private WifiNetworkAgent mNetworkAgent;
+    private final Object mNetworkAgentLock = new Object();
+
+    private byte[] mRssiRanges;
+
+    // Used to filter out requests we couldn't possibly satisfy.
+    private final NetworkCapabilities mNetworkCapabilitiesFilter;
+
+    private final ExternalCallbackTracker<IActionListener> mProcessingActionListeners;
+
+    /* The base for wifi message types */
+    static final int BASE = Protocol.BASE_WIFI;
+    /* BT state change, e.g., on or off */
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE                 = BASE + 31;
+    /* BT connection state change, e.g., connected or disconnected */
+    static final int CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE      = BASE + 32;
+
+    /* Get adaptors */
+    static final int CMD_GET_SUPPORTED_FEATURES                         = BASE + 61;
+    /* Get Link Layer Stats thru HAL */
+    static final int CMD_GET_LINK_LAYER_STATS                           = BASE + 63;
+    /* Supplicant commands after driver start*/
+    /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */
+    static final int CMD_SET_OPERATIONAL_MODE                           = BASE + 72;
+    /* Disconnect from a network */
+    static final int CMD_DISCONNECT                                     = BASE + 73;
+    /* Reconnect to a network */
+    static final int CMD_RECONNECT                                      = BASE + 74;
+
+    /* Controls suspend mode optimizations
+     *
+     * When high perf mode is enabled, suspend mode optimizations are disabled
+     *
+     * When high perf mode is disabled, suspend mode optimizations are enabled
+     *
+     * Suspend mode optimizations include:
+     * - packet filtering
+     * - turn off roaming
+     * - DTIM wake up settings
+     */
+    static final int CMD_SET_HIGH_PERF_MODE                             = BASE + 77;
+    /* Enables RSSI poll */
+    static final int CMD_ENABLE_RSSI_POLL                               = BASE + 82;
+    /* RSSI poll */
+    static final int CMD_RSSI_POLL                                      = BASE + 83;
+    /** Runs RSSI poll once */
+    static final int CMD_ONESHOT_RSSI_POLL                              = BASE + 84;
+    /* Enable suspend mode optimizations in the driver */
+    static final int CMD_SET_SUSPEND_OPT_ENABLED                        = BASE + 86;
+
+    /**
+     * Watchdog for protecting against b/16823537
+     * Leave time for 4-way handshake to succeed
+     */
+    static final int ROAM_GUARD_TIMER_MSEC = 15000;
+
+    int mRoamWatchdogCount = 0;
+    /* Roam state watchdog */
+    static final int CMD_ROAM_WATCHDOG_TIMER                            = BASE + 94;
+    /* Screen change intent handling */
+    static final int CMD_SCREEN_STATE_CHANGED                           = BASE + 95;
+
+    /* Disconnecting state watchdog */
+    static final int CMD_DISCONNECTING_WATCHDOG_TIMER                   = BASE + 96;
+
+    /* SIM is removed; reset any cached data for it */
+    static final int CMD_RESET_SIM_NETWORKS                             = BASE + 101;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"RESET_SIM_REASON_"},
+            value = {
+                    RESET_SIM_REASON_SIM_REMOVED,
+                    RESET_SIM_REASON_SIM_INSERTED,
+                    RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED})
+    @interface ResetSimReason {}
+    static final int RESET_SIM_REASON_SIM_REMOVED              = 0;
+    static final int RESET_SIM_REASON_SIM_INSERTED             = 1;
+    static final int RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED = 2;
+
+    /* OSU APIs */
+    static final int CMD_QUERY_OSU_ICON                                 = BASE + 104;
+
+    /* Commands from/to the SupplicantStateTracker */
+    /* Reset the supplicant state tracker */
+    static final int CMD_RESET_SUPPLICANT_STATE                         = BASE + 111;
+
+    int mDisconnectingWatchdogCount = 0;
+    static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000;
+
+    /* We now have a valid IP configuration. */
+    static final int CMD_IP_CONFIGURATION_SUCCESSFUL                    = BASE + 138;
+    /* We no longer have a valid IP configuration. */
+    static final int CMD_IP_CONFIGURATION_LOST                          = BASE + 139;
+    /* Link configuration (IP address, DNS, ...) changes notified via netlink */
+    static final int CMD_UPDATE_LINKPROPERTIES                          = BASE + 140;
+
+    static final int CMD_START_CONNECT                                  = BASE + 143;
+
+    private static final int NETWORK_STATUS_UNWANTED_DISCONNECT         = 0;
+    private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED  = 1;
+    private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN   = 2;
+
+    static final int CMD_UNWANTED_NETWORK                               = BASE + 144;
+
+    static final int CMD_START_ROAM                                     = BASE + 145;
+
+    static final int CMD_NETWORK_STATUS                                 = BASE + 148;
+
+    /* A layer 3 neighbor on the Wi-Fi link became unreachable. */
+    static final int CMD_IP_REACHABILITY_LOST                           = BASE + 149;
+
+    static final int CMD_ACCEPT_UNVALIDATED                             = BASE + 153;
+
+    /* used to offload sending IP packet */
+    static final int CMD_START_IP_PACKET_OFFLOAD                        = BASE + 160;
+
+    /* used to stop offload sending IP packet */
+    static final int CMD_STOP_IP_PACKET_OFFLOAD                         = BASE + 161;
+
+    /* used to start rssi monitoring in hw */
+    static final int CMD_START_RSSI_MONITORING_OFFLOAD                  = BASE + 162;
+
+    /* used to stop rssi moniroting in hw */
+    static final int CMD_STOP_RSSI_MONITORING_OFFLOAD                   = BASE + 163;
+
+    /* used to indicated RSSI threshold breach in hw */
+    static final int CMD_RSSI_THRESHOLD_BREACHED                        = BASE + 164;
+
+    /**
+     * Used to handle messages bounced between ClientModeImpl and IpClient.
+     */
+    static final int CMD_IPV4_PROVISIONING_SUCCESS                      = BASE + 200;
+    static final int CMD_IPV4_PROVISIONING_FAILURE                      = BASE + 201;
+
+    /* Push a new APF program to the HAL */
+    static final int CMD_INSTALL_PACKET_FILTER                          = BASE + 202;
+
+    /* Enable/disable fallback packet filtering */
+    static final int CMD_SET_FALLBACK_PACKET_FILTERING                  = BASE + 203;
+
+    /* Enable/disable Neighbor Discovery offload functionality. */
+    static final int CMD_CONFIG_ND_OFFLOAD                              = BASE + 204;
+
+    /* Read the APF program & data buffer */
+    static final int CMD_READ_PACKET_FILTER                             = BASE + 208;
+
+    /** Used to add packet filter to apf. */
+    static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = BASE + 209;
+
+    /** Used to remove packet filter from apf. */
+    static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = BASE + 210;
+
+    // Start subscription provisioning with a given provider
+    private static final int CMD_START_SUBSCRIPTION_PROVISIONING        = BASE + 254;
+
+    @VisibleForTesting
+    static final int CMD_PRE_DHCP_ACTION                                = BASE + 255;
+    private static final int CMD_PRE_DHCP_ACTION_COMPLETE               = BASE + 256;
+    private static final int CMD_POST_DHCP_ACTION                       = BASE + 257;
+    /* Take some GAP in numbering, start from 301 onwards */
+    /* Vendor specific cmd: To handle IP Reachability session */
+    private static final int CMD_IP_REACHABILITY_SESSION_END            = BASE + 311;
+
+    private static final int CMD_CONNECT_NETWORK                        = BASE + 258;
+    private static final int CMD_SAVE_NETWORK                           = BASE + 259;
+
+    /* Start connection to FILS AP*/
+    static final int CMD_START_FILS_CONNECTION                          = BASE + 262;
+    // For message logging.
+    private static final Class[] sMessageClasses = {
+            AsyncChannel.class, QtiClientModeImpl.class };
+    private static final SparseArray<String> sGetWhatToString =
+            MessageUtils.findMessageNames(sMessageClasses);
+
+    private static final int SUCCESS = 1;
+    private static final int FAILURE = -1;
+
+    /* Tracks if suspend optimizations need to be disabled by DHCP,
+     * screen or due to high perf mode.
+     * When any of them needs to disable it, we keep the suspend optimizations
+     * disabled
+     */
+    private int mSuspendOptNeedsDisabled = 0;
+
+    private static final int SUSPEND_DUE_TO_DHCP = 1;
+    private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1;
+    private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2;
+
+    /**
+     * Time window in milliseconds for which we send
+     * {@link NetworkAgent#explicitlySelected(boolean, boolean)}
+     * after connecting to the network which the user last selected.
+     */
+    @VisibleForTesting
+    public static final int LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS = 30 * 1000;
+
+    /* Tracks if user has enabled Connected Mac Randomization through settings */
+
+    /**
+     * Supplicant scan interval in milliseconds.
+     * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
+     * from the default config if the setting is not set
+     */
+    private long mSupplicantScanIntervalMs;
+
+    int mRunningBeaconCount = 0;
+
+    /* Default parent state */
+    private State mDefaultState = new DefaultState();
+    /* Connecting to an access point */
+    private State mConnectModeState = new ConnectModeState();
+    /* Connected at 802.11 (L2) level */
+    private State mL2ConnectedState = new L2ConnectedState();
+    /* fetching IP after connection to access point (assoc+auth complete) */
+    private State mObtainingIpState = new ObtainingIpState();
+    /* Connected with IP addr */
+    private State mConnectedState = new ConnectedState();
+    /* Roaming */
+    private State mRoamingState = new RoamingState();
+    /* disconnect issued, waiting for network disconnect confirmation */
+    private State mDisconnectingState = new DisconnectingState();
+    /* Network is not connected, supplicant assoc+auth is not complete */
+    private State mDisconnectedState = new DisconnectedState();
+
+    /*
+     * FILS connection related variables.
+     */
+    /* To indicate to IpClient whether HLP IEs were included or not in assoc request */
+    private boolean mSentHLPs = false;
+    /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */
+    private boolean mIpClientWithPreConnection = false;
+
+    /**
+     * One of  {@link WifiManager#WIFI_STATE_DISABLED},
+     * {@link WifiManager#WIFI_STATE_DISABLING},
+     * {@link WifiManager#WIFI_STATE_ENABLED},
+     * {@link WifiManager#WIFI_STATE_ENABLING},
+     * {@link WifiManager#WIFI_STATE_UNKNOWN}
+     */
+    private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
+
+    /**
+     * Work source to use to blame usage on the WiFi service
+     */
+    public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID);
+
+    private final BatteryStatsManager mBatteryStatsManager;
+
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
+
+
+    // Used for debug and stats gathering
+    private static int sScanAlarmIntentCount = 0;
+
+    private FrameworkFacade mFacade;
+    private WifiStateTracker mWifiStateTracker;
+    private final WrongPasswordNotifier mWrongPasswordNotifier; //TODO: UT: check if wrong password notification sent on secondary is needed or not?
+    private final SimRequiredNotifier mSimRequiredNotifier;
+    private boolean mConnectedMacRandomzationSupported;
+    private final int mIdentity;
+    private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
+    private final QtiClientModeManager.Listener mListener;
+
+    public QtiClientModeImpl(Context context, FrameworkFacade facade, Looper looper,
+                            WifiInjector wifiInjector, WifiNative wifiNative,
+                            WrongPasswordNotifier wrongPasswordNotifier,
+                            WifiTrafficPoller wifiTrafficPoller,
+                            LinkProbeManager linkProbeManager, int identity,
+                            BatteryStatsManager batteryStatsManager,
+                            SupplicantStateTracker supplicantStateTracker,
+                            MboOceController mboOceController,
+                            WifiCarrierInfoManager wifiCarrierInfoManager,
+                            EapFailureNotifier eapFailureNotifier,
+                            SimRequiredNotifier simRequiredNotifier,
+                            QtiClientModeManager.Listener listener, WifiConfigManager wifiConfigManager,
+                            DeviceConfigFacade deviceConfigFacade) {
+        super(TAG, looper);
+        mWifiInjector = wifiInjector;
+        mWifiMetrics = mWifiInjector.getWifiMetrics();
+        mClock = wifiInjector.getClock();
+        mPropertyService = wifiInjector.getPropertyService();
+        mBuildProperties = wifiInjector.getBuildProperties();
+        mWifiScoreCard = wifiInjector.getWifiScoreCard();
+        mContext = context;
+        mFacade = facade;
+        mListener = listener;
+        mWifiNative = wifiNative;
+        mWrongPasswordNotifier = wrongPasswordNotifier;
+        mSimRequiredNotifier = simRequiredNotifier;
+        mWifiTrafficPoller = wifiTrafficPoller;
+        mLinkProbeManager = linkProbeManager;
+        mMboOceController = mboOceController;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
+        mNetworkAgentState = DetailedState.DISCONNECTED;
+        mIdentity = identity;
+        mBatteryStatsManager = batteryStatsManager;
+        mWifiStateTracker = wifiInjector.getWifiStateTracker();
+        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
+        mP2pSupported = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WIFI_DIRECT);
+
+        mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();
+        mWifiConfigManager = wifiConfigManager;
+
+        mPasspointManager = mWifiInjector.getPasspointManager();
+
+        mWifiMonitor = mWifiInjector.getWifiMonitor();
+        mWifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper();
+        mWifiDataStall = mWifiInjector.getWifiDataStall();
+
+        mWifiInfo = new ExtendedWifiInfo(context);
+        mSupplicantStateTracker = supplicantStateTracker;
+        mQtiWifiConnectivityManager = mWifiInjector.makeQtiWifiConnectivityManager(this, mWifiConfigManager);
+        mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor();
+
+        mLinkProperties = new LinkProperties();
+        mMcastLockManagerFilterController = new McastLockManagerFilterController();
+        mActivityManager = context.getSystemService(ActivityManager.class);
+
+        mLastBssid = null;
+        mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+        mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        mLastSimBasedConnectionCarrierName = null;
+        mLastSignalLevel = -1;
+
+        mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock,
+                mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor,
+                mWifiInjector.getWifiThreadRunner(), deviceConfigFacade, context,
+                getHandler().getLooper(), mFacade);
+
+        mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+                // TODO - needs to be a bit more dynamic
+                .setLinkUpstreamBandwidthKbps(1024 * 1024)
+                .setLinkDownstreamBandwidthKbps(1024 * 1024)
+                .setNetworkSpecifier(new MatchAllNetworkSpecifier())
+                .build();
+
+        mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager();
+        mProcessingActionListeners = new ExternalCallbackTracker<>(getHandler());
+        mWifiHealthMonitor = mWifiInjector.getWifiHealthMonitor();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        mContext.registerReceiver(
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        String action = intent.getAction();
+
+                        if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                            sendMessage(CMD_SCREEN_STATE_CHANGED, 1);
+                        } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                            sendMessage(CMD_SCREEN_STATE_CHANGED, 0);
+                        }
+                    }
+                }, filter);
+
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+        mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
+        mSuspendWakeLock.setReferenceCounted(false);
+
+        mWifiConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener());
+
+        mDisconnectOnlyOnInitialIpReachability = SystemProperties
+                .get("persist.vendor.wifi.enableIpReachabilityMonitorPeriod", "1")
+                .equals("1");
+
+        // CHECKSTYLE:OFF IndentationCheck
+        addState(mDefaultState);
+            addState(mConnectModeState, mDefaultState);
+                addState(mL2ConnectedState, mConnectModeState);
+                    addState(mObtainingIpState, mL2ConnectedState);
+                    addState(mConnectedState, mL2ConnectedState);
+                    addState(mRoamingState, mL2ConnectedState);
+                addState(mDisconnectingState, mConnectModeState);
+                addState(mDisconnectedState, mConnectModeState);
+        // CHECKSTYLE:ON IndentationCheck
+
+        setInitialState(mDefaultState);
+
+        setLogRecSize(NUM_LOG_RECS_NORMAL);
+        setLogOnlyTransitions(false);
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+        // Learn the initial state of whether the screen is on.
+        // We update this field when we receive broadcasts from the system.
+        handleScreenStateChanged(powerManager.isInteractive());
+    }
+
+    private void registerForWifiMonitorEvents()  {
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.TARGET_BSSID_EVENT, getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATED_BSSID_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH,
+                getHandler());
+        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE,
+                getHandler());
+    }
+
+    private void setMulticastFilter(boolean enabled) {
+        if (mIpClient != null) {
+            mIpClient.setMulticastFilter(enabled);
+        }
+    }
+
+    /**
+     * Class to implement the MulticastLockManager.FilterController callback.
+     */
+    class McastLockManagerFilterController implements WifiMulticastLockManager.FilterController {
+        /**
+         * Start filtering Multicast v4 packets
+         */
+        public void startFilteringMulticastPackets() {
+            setMulticastFilter(true);
+        }
+
+        /**
+         * Stop filtering Multicast v4 packets
+         */
+        public void stopFilteringMulticastPackets() {
+            setMulticastFilter(false);
+        }
+    }
+
+    class IpClientCallbacksImpl extends IpClientCallbacks {
+        private final ConditionVariable mWaitForCreationCv = new ConditionVariable(false);
+        private final ConditionVariable mWaitForStopCv = new ConditionVariable(false);
+
+        @Override
+        public void onIpClientCreated(IIpClient ipClient) {
+            mIpClient = new IpClientManager(ipClient, getName());
+            mWaitForCreationCv.open();
+        }
+
+        @Override
+        public void onPreDhcpAction() {
+            sendMessage(CMD_PRE_DHCP_ACTION);
+        }
+
+        @Override
+        public void onPostDhcpAction() {
+            sendMessage(CMD_POST_DHCP_ACTION);
+        }
+
+        @Override
+        public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
+            if (dhcpResults != null) {
+                sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults);
+            } else {
+                sendMessage(CMD_IPV4_PROVISIONING_FAILURE);
+            }
+        }
+
+        @Override
+        public void onProvisioningSuccess(LinkProperties newLp) {
+            mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL);
+            sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
+            sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
+        }
+
+        @Override
+        public void onProvisioningFailure(LinkProperties newLp) {
+            sendMessage(CMD_IP_CONFIGURATION_LOST);
+        }
+
+        @Override
+        public void onLinkPropertiesChange(LinkProperties newLp) {
+            sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
+        }
+
+        @Override
+        public void onReachabilityLost(String logMsg) {
+            sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
+        }
+
+        @Override
+        public void installPacketFilter(byte[] filter) {
+            sendMessage(CMD_INSTALL_PACKET_FILTER, filter);
+        }
+
+        @Override
+        public void startReadPacketFilter() {
+            sendMessage(CMD_READ_PACKET_FILTER);
+        }
+
+        @Override
+        public void setFallbackMulticastFilter(boolean enabled) {
+            sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled);
+        }
+
+        @Override
+        public void setNeighborDiscoveryOffload(boolean enabled) {
+            sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0));
+        }
+
+        @Override
+        public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
+            sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets);
+        }
+
+        @Override
+        public void onQuit() {
+            mWaitForStopCv.open();
+        }
+
+        boolean awaitCreation() {
+            return mWaitForCreationCv.block(IPCLIENT_STARTUP_TIMEOUT_MS);
+        }
+
+        boolean awaitShutdown() {
+            return mWaitForStopCv.block(IPCLIENT_SHUTDOWN_TIMEOUT_MS);
+        }
+    }
+
+    private void stopIpClient() {
+        if (mVerboseLoggingEnabled) {
+            log("stopIpClient IpClientWithPreConnection: " + mIpClientWithPreConnection);
+        }
+        if (mIpClient != null) {
+            if (mIpClientWithPreConnection) {
+                mIpClient.notifyPreconnectionComplete(false);
+            }
+            mIpClient.stop();
+        }
+    }
+
+    private void stopDhcpSetup() {
+        /* Restore power save and suspend optimizations */
+        handlePostDhcpSetup();
+        stopIpClient();
+    }
+
+    /**
+     * Listener for config manager network config related events.
+     * TODO (b/117601161) : Move some of the existing handling in WifiConnectivityManager's listener
+     * for the same events.
+     */
+    private class OnNetworkUpdateListener implements
+            WifiConfigManager.OnNetworkUpdateListener {
+        @Override
+        public void onNetworkAdded(WifiConfiguration config) { }
+
+        @Override
+        public void onNetworkEnabled(WifiConfiguration config) { }
+
+        @Override
+        public void onNetworkRemoved(WifiConfiguration config) {
+            // The current connected or connecting network has been removed, trigger a disconnect.
+            if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
+                // Disconnect and let autojoin reselect a new network
+                sendMessage(CMD_DISCONNECT);
+            }
+            mWifiNative.removeNetworkCachedData(config.networkId);
+        }
+
+        @Override
+        public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) {
+            // Check if user/app change meteredOverride for connected network.
+            if (newConfig.networkId != mLastNetworkId
+                    || newConfig.meteredOverride == oldConfig.meteredOverride) {
+                // nothing to do.
+                return;
+            }
+            boolean isMetered = WifiConfiguration.isMetered(newConfig, mWifiInfo);
+            boolean wasMetered = WifiConfiguration.isMetered(oldConfig, mWifiInfo);
+            if (isMetered == wasMetered) {
+                // no meteredness change, nothing to do.
+                if (mVerboseLoggingEnabled) {
+                    Log.v(TAG, "User/app changed meteredOverride, but no change in meteredness");
+                }
+                return;
+            }
+            // If unmetered->metered trigger a disconnect.
+            // If metered->unmetered update capabilities.
+            if (isMetered) {
+                Log.w(TAG, "Network marked metered, triggering disconnect");
+                sendMessage(CMD_DISCONNECT);
+            } else {
+                Log.i(TAG, "Network marked unmetered, triggering capabilities update");
+                updateCapabilities(newConfig);
+            }
+        }
+
+        @Override
+        public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) {
+            if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return;
+            if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
+                // Disconnect and let autojoin reselect a new network
+                sendMessage(CMD_DISCONNECT);
+            }
+
+        }
+
+        @Override
+        public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) {
+            // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network
+            // because supplicant won't be trying to reconnect. If this is due to a
+            // preventAutomaticReconnect request from ConnectivityService, that service
+            // will disconnect as appropriate.
+            if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return;
+            if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
+                // Disconnect and let autojoin reselect a new network
+                sendMessage(CMD_DISCONNECT);
+            }
+        }
+    }
+
+    /**
+     * Set wpa_supplicant log level using |mVerboseLoggingLevel| flag.
+     */
+    void setSupplicantLogLevel() {
+        mWifiNative.setSupplicantLogLevel(mVerboseLoggingEnabled);
+    }
+
+    /**
+     * Method to update logging level in wifi service related classes.
+     *
+     * @param verbose int logging level to use
+     */
+    public void enableVerboseLogging(int verbose) {
+        if (verbose > 0) {
+            mVerboseLoggingEnabled = true;
+            setLogRecSize(mActivityManager.isLowRamDevice()
+                    ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE);
+        } else {
+            mVerboseLoggingEnabled = false;
+            setLogRecSize(NUM_LOG_RECS_NORMAL);
+        }
+    }
+
+
+    /**
+     * Initiates connection to a network specified by the user/app. This method checks if the
+     * requesting app holds the NETWORK_SETTINGS permission.
+     *
+     * @param netId Id network to initiate connection.
+     * @param uid UID of the app requesting the connection.
+     * @param forceReconnect Whether to force a connection even if we're connected to the same
+     *                       network currently.
+     */
+    private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) {
+        logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid
+                + ", forceReconnect = " + forceReconnect);
+        if (!forceReconnect && mWifiInfo.getNetworkId() == netId) {
+            // We're already connected to the user specified network, don't trigger a
+            // reconnection unless it was forced.
+            logi("connectToUserSelectNetwork already connecting/connected=" + netId);
+        } else {
+            mQtiWifiConnectivityManager.prepareForForcedConnection(netId);
+            startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY);
+        }
+    }
+
+    /**
+     * ******************************************************
+     * Methods exposed for public use
+     * ******************************************************
+     */
+
+    /**
+     * Retrieve a Messenger for the QtiClientModeImpl Handler
+     *
+     * @return Messenger
+     */
+    public Messenger getMessenger() {
+        return new Messenger(getHandler());
+    }
+
+    // Last connect attempt is used to prevent scan requests:
+    //  - for a period of 10 seconds after attempting to connect
+    private long mLastConnectAttemptTimestamp = 0;
+
+    // For debugging, keep track of last message status handling
+    // TODO, find an equivalent mechanism as part of parent class
+    private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2;
+    private static final int MESSAGE_HANDLING_STATUS_OK = 1;
+    private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0;
+    private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1;
+    private static final int MESSAGE_HANDLING_STATUS_FAIL = -2;
+    private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3;
+    private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4;
+    private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5;
+    private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6;
+    private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7;
+
+    private int mMessageHandlingStatus = 0;
+
+    private int mOnTime = 0;
+    private int mTxTime = 0;
+    private int mRxTime = 0;
+
+    private int mOnTimeScreenStateChange = 0;
+    private long mLastOntimeReportTimeStamp = 0;
+    private long mLastScreenStateChangeTimeStamp = 0;
+    private int mOnTimeLastReport = 0;
+    private int mTxTimeLastReport = 0;
+    private int mRxTimeLastReport = 0;
+
+    private WifiLinkLayerStats mLastLinkLayerStats;
+    private long mLastLinkLayerStatsUpdate = 0;
+
+    String reportOnTime() {
+        long now = mClock.getWallClockMillis();
+        StringBuilder sb = new StringBuilder();
+        // Report stats since last report
+        int on = mOnTime - mOnTimeLastReport;
+        mOnTimeLastReport = mOnTime;
+        int tx = mTxTime - mTxTimeLastReport;
+        mTxTimeLastReport = mTxTime;
+        int rx = mRxTime - mRxTimeLastReport;
+        mRxTimeLastReport = mRxTime;
+        int period = (int) (now - mLastOntimeReportTimeStamp);
+        mLastOntimeReportTimeStamp = now;
+        sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period));
+        // Report stats since Screen State Changed
+        on = mOnTime - mOnTimeScreenStateChange;
+        period = (int) (now - mLastScreenStateChangeTimeStamp);
+        sb.append(String.format(" from screen [on:%d period:%d]", on, period));
+        return sb.toString();
+    }
+
+    WifiLinkLayerStats getWifiLinkLayerStats() {
+        if (mInterfaceName == null) {
+            loge("getWifiLinkLayerStats called without an interface");
+            return null;
+        }
+        mLastLinkLayerStatsUpdate = mClock.getWallClockMillis();
+        WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName);
+        if (stats != null) {
+            mOnTime = stats.on_time;
+            mTxTime = stats.tx_time;
+            mRxTime = stats.rx_time;
+            mRunningBeaconCount = stats.beacon_rx;
+            mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate);
+        } else {
+            long mTxPkts = mFacade.getTxPackets(mInterfaceName);
+            long mRxPkts = mFacade.getRxPackets(mInterfaceName);
+            mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate);
+        }
+        return stats;
+    }
+
+    /**
+     * Check if a Wi-Fi band is supported
+     *
+     * @param band A value from {@link WifiScanner.WIFI_BAND_5_GHZ} or
+     *        {@link WifiScanner.WIFI_BAND_6_GHZ}
+     * @return {@code true} if band is supported, {@code false} otherwise.
+     */
+    public boolean isWifiBandSupported(int band) {
+        if (band == WifiScanner.WIFI_BAND_5_GHZ) {
+            // In some cases, devices override the value by the overlay configs
+            if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) {
+                return true;
+            }
+            return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0);
+        }
+
+        if (band == WifiScanner.WIFI_BAND_6_GHZ) {
+            if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) {
+                return true;
+            }
+            return (mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0);
+        }
+
+        return false;
+    }
+
+    /**
+     * Update interface capabilities
+     * This method is used to update some of interface capabilities defined in overlay
+     *
+     * @param ifaceName name of interface to update
+     */
+    private void updateInterfaceCapabilities(@NonNull String ifaceName) {
+        DeviceWiphyCapabilities cap = mWifiNative.getDeviceWiphyCapabilities(ifaceName);
+        if (cap != null) {
+            // Some devices don't have support of 11ax indicated by the chip,
+            // so an override config value is used
+            if (mContext.getResources().getBoolean(R.bool.config_wifi11axSupportOverride)) {
+                cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, true);
+            }
+
+            mWifiNative.setDeviceWiphyCapabilities(ifaceName, cap);
+        }
+    }
+
+    /**
+     * Check if a Wi-Fi standard is supported
+     *
+     * @param standard A value from {@link ScanResult}'s {@code WIFI_STANDARD_}
+     * @return {@code true} if standard is supported, {@code false} otherwise.
+     */
+    public boolean isWifiStandardSupported(@WifiStandard int standard) {
+        return mWifiNative.isWifiStandardSupported(mInterfaceName, standard);
+    }
+
+    private byte[] getDstMacForKeepalive(KeepalivePacketData packetData)
+            throws InvalidPacketException {
+        try {
+            InetAddress gateway = NetUtils.selectBestRoute(
+                    mLinkProperties.getRoutes(), packetData.getDstAddress()).getGateway();
+            String dstMacStr = macAddressFromRoute(gateway.getHostAddress());
+            return NativeUtil.macAddressToByteArray(dstMacStr);
+        } catch (NullPointerException | IllegalArgumentException e) {
+            throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS);
+        }
+    }
+
+    private static int getEtherProtoForKeepalive(KeepalivePacketData packetData)
+            throws InvalidPacketException {
+        if (packetData.getDstAddress() instanceof Inet4Address) {
+            return OsConstants.ETH_P_IP;
+        } else if (packetData.getDstAddress() instanceof Inet6Address) {
+            return OsConstants.ETH_P_IPV6;
+        } else {
+            throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS);
+        }
+    }
+
+    private int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData,
+            int intervalSeconds) {
+        byte[] packet = null;
+        byte[] dstMac = null;
+        int proto = 0;
+
+        try {
+            packet = packetData.getPacket();
+            dstMac = getDstMacForKeepalive(packetData);
+            proto = getEtherProtoForKeepalive(packetData);
+        } catch (InvalidPacketException e) {
+            return e.getError();
+        }
+
+        int ret = mWifiNative.startSendingOffloadedPacket(
+                mInterfaceName, slot, dstMac, packet, proto, intervalSeconds * 1000);
+        if (ret != 0) {
+            loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds
+                    + "): hardware error " + ret);
+            return SocketKeepalive.ERROR_HARDWARE_ERROR;
+        } else {
+            return SocketKeepalive.SUCCESS;
+        }
+    }
+
+    private int stopWifiIPPacketOffload(int slot) {
+        int ret = mWifiNative.stopSendingOffloadedPacket(mInterfaceName, slot);
+        if (ret != 0) {
+            loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret);
+            return SocketKeepalive.ERROR_HARDWARE_ERROR;
+        } else {
+            return SocketKeepalive.SUCCESS;
+        }
+    }
+
+    private int startRssiMonitoringOffload(byte maxRssi, byte minRssi,
+            WifiNative.WifiRssiEventHandler rssiHandler) {
+        return mWifiNative.startRssiMonitoring(mInterfaceName, maxRssi, minRssi, rssiHandler);
+    }
+
+    private int stopRssiMonitoringOffload() {
+        return mWifiNative.stopRssiMonitoring(mInterfaceName);
+    }
+
+    /**
+     * Temporary method that allows the active ClientModeManager to set the wifi state that is
+     * retrieved by API calls. This will be removed when WifiServiceImpl no longer directly calls
+     * this class (b/31479117).
+     *
+     * @param newState new state to set, invalid states are ignored.
+     */
+    public void setWifiStateForApiCalls(int newState) {
+        switch (newState) {
+            case WIFI_STATE_DISABLING:
+            case WIFI_STATE_DISABLED:
+            case WIFI_STATE_ENABLING:
+            case WIFI_STATE_ENABLED:
+            case WIFI_STATE_UNKNOWN:
+                if (mVerboseLoggingEnabled) {
+                    Log.d(TAG, "setting wifi state to: " + newState);
+                }
+                mWifiState.set(newState);
+                return;
+            default:
+                Log.d(TAG, "attempted to set an invalid state: " + newState);
+                return;
+        }
+    }
+
+    /**
+     * Method used by WifiServiceImpl to get the current state of Wifi (in client mode) for API
+     * calls.  This will be removed when WifiService no longer directly calls this class
+     * (b/31479117).
+     */
+    public int syncGetWifiState() {
+        return mWifiState.get();
+    }
+
+    /**
+     * Converts the current wifi state to a printable form.
+     */
+    public String syncGetWifiStateByName() {
+        switch (mWifiState.get()) {
+            case WIFI_STATE_DISABLING:
+                return "disabling";
+            case WIFI_STATE_DISABLED:
+                return "disabled";
+            case WIFI_STATE_ENABLING:
+                return "enabling";
+            case WIFI_STATE_ENABLED:
+                return "enabled";
+            case WIFI_STATE_UNKNOWN:
+                return "unknown state";
+            default:
+                return "[invalid state]";
+        }
+    }
+
+    public boolean isConnected() {
+        return getCurrentState() == mConnectedState;
+    }
+
+    public boolean isDisconnected() {
+        return getCurrentState() == mDisconnectedState;
+    }
+
+    /**
+     * Method checking if supplicant is in a transient state
+     *
+     * @return boolean true if in transient state
+     */
+    public boolean isSupplicantTransientState() {
+        SupplicantState supplicantState = mWifiInfo.getSupplicantState();
+        if (supplicantState == SupplicantState.ASSOCIATING
+                || supplicantState == SupplicantState.AUTHENTICATING
+                || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE
+                || supplicantState == SupplicantState.GROUP_HANDSHAKE) {
+
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Supplicant is under transient state: " + supplicantState);
+            }
+            return true;
+        } else {
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Supplicant is under steady state: " + supplicantState);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get status information for the current connection, if any.
+     *
+     * @return a {@link WifiInfo} object containing information about the current connection
+     */
+    public WifiInfo syncRequestConnectionInfo() {
+        WifiInfo result = new WifiInfo(mWifiInfo);
+        return result;
+    }
+
+    /**
+     * Method to retrieve the current WifiInfo
+     *
+     * @returns WifiInfo
+     */
+    public WifiInfo getWifiInfo() {
+        return mWifiInfo;
+    }
+
+    /**
+     * When the underlying interface is destroyed, we must immediately tell connectivity service to
+     * mark network agent as disconnected and stop the ip client.
+     */
+    public void handleIfaceDestroyed() {
+        handleNetworkDisconnect();
+    }
+
+    /**
+     * TODO: doc
+     */
+    public void setOperationalMode(int mode, String ifaceName) {
+        if (mVerboseLoggingEnabled) {
+            log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName);
+        }
+        mModeChange = true;
+        if (mode != ClientModeImpl.CONNECT_MODE) {
+            // we are disabling client mode...   need to exit connect mode now
+            transitionTo(mDefaultState);
+        } else {
+            // do a quick sanity check on the iface name, make sure it isn't null
+            if (ifaceName != null) {
+                mInterfaceName = ifaceName;
+                updateInterfaceCapabilities(ifaceName);
+                transitionTo(mDisconnectedState);
+                mWifiScoreReport.setInterfaceName(ifaceName);
+            } else {
+                Log.e(TAG, "supposed to enter connect mode, but iface is null -> DefaultState");
+                transitionTo(mDefaultState);
+            }
+        }
+        // use the CMD_SET_OPERATIONAL_MODE to force the transitions before other messages are
+        // handled.
+        sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE);
+    }
+
+    /**
+     * Allow tests to confirm the operational mode for QtiClientModeImpl for testing.
+     */
+    @VisibleForTesting
+    protected int getOperationalModeForTest() {
+        return mOperationalMode;
+    }
+
+    /**
+     * Retrieve the WifiMulticastLockManager.FilterController callback for registration.
+     */
+    protected WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() {
+        return mMcastLockManagerFilterController;
+    }
+
+    /**
+     * Blocking method to retrieve the passpoint icon.
+     *
+     * @param channel AsyncChannel for the response
+     * @param bssid representation of the bssid as a long
+     * @param fileName name of the file
+     *
+     * @return boolean returning the result of the call
+     */
+    public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) {
+        Bundle bundle = new Bundle();
+        bundle.putLong(EXTRA_OSU_ICON_QUERY_BSSID, bssid);
+        bundle.putString(EXTRA_OSU_ICON_QUERY_FILENAME, fileName);
+        Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result == 1;
+    }
+
+    /**
+     * Deauthenticate and set the re-authentication hold off time for the current network
+     * @param holdoff hold off time in milliseconds
+     * @param ess set if the hold off pertains to an ESS rather than a BSS
+     */
+    public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) {
+        // TODO: This needs an implementation
+    }
+
+    /**
+     * Disconnect from Access Point
+     */
+    public void disconnectCommand() {
+        sendMessage(CMD_DISCONNECT);
+    }
+
+    /**
+     * Method to trigger a disconnect.
+     *
+     * @param uid UID of requesting caller
+     * @param reason disconnect reason
+     */
+    public void disconnectCommand(int uid, int reason) {
+        sendMessage(CMD_DISCONNECT, uid, reason);
+    }
+
+    /**
+     * Initiate a reconnection to AP
+     */
+    public void reconnectCommand(WorkSource workSource) {
+        sendMessage(CMD_RECONNECT, workSource);
+    }
+
+    /**
+     * Checks for a null Message.
+     *
+     * This can happen with sendMessageSynchronously, for example if an
+     * InterruptedException occurs. If this just happens once, silently
+     * ignore it, because it is probably a side effect of shutting down.
+     * If it happens a second time, generate a WTF.
+     */
+    private boolean messageIsNull(Message resultMsg) {
+        if (resultMsg != null) return false;
+        if (mNullMessageCounter.getAndIncrement() > 0) {
+            Log.wtf(TAG, "Persistent null Message", new RuntimeException());
+        }
+        return true;
+    }
+    private AtomicInteger mNullMessageCounter = new AtomicInteger(0);
+
+    /**
+     * Start subscription provisioning synchronously
+     *
+     * @param provider {@link OsuProvider} the provider to provision with
+     * @param callback {@link IProvisioningCallback} callback for provisioning status
+     * @return boolean true indicates provisioning was started, false otherwise
+     */
+    public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider,
+            IProvisioningCallback callback, AsyncChannel channel) {
+        Message msg = Message.obtain();
+        msg.what = CMD_START_SUBSCRIPTION_PROVISIONING;
+        msg.arg1 = callingUid;
+        msg.obj = callback;
+        msg.getData().putParcelable(EXTRA_OSU_PROVIDER, provider);
+        Message resultMsg = channel.sendMessageSynchronously(msg);
+        if (messageIsNull(resultMsg)) return false;
+        boolean result = resultMsg.arg1 != 0;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Get the supported feature set synchronously
+     */
+    public long syncGetSupportedFeatures(AsyncChannel channel) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES);
+        if (messageIsNull(resultMsg)) return 0;
+        long supportedFeatureSet = ((Long) resultMsg.obj).longValue();
+        resultMsg.recycle();
+        return supportedFeatureSet;
+    }
+
+    /**
+     * Get link layers stats for adapter synchronously
+     */
+    public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS);
+        if (messageIsNull(resultMsg)) return null;
+        WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj;
+        resultMsg.recycle();
+        return result;
+    }
+
+    /**
+     * Method to enable/disable RSSI polling
+     * @param enabled boolean idicating if polling should start
+     */
+    public void enableRssiPolling(boolean enabled) {
+        sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
+    }
+
+    /**
+     * Set high performance mode of operation.
+     * Enabling would set active power mode and disable suspend optimizations;
+     * disabling would set auto power mode and enable suspend optimizations
+     *
+     * @param enable true if enable, false otherwise
+     */
+    public void setHighPerfModeEnabled(boolean enable) {
+        sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0);
+    }
+
+
+    /**
+     * reset cached SIM credential data
+     */
+    public synchronized void resetSimAuthNetworks(@ResetSimReason int resetReason) {
+        sendMessage(CMD_RESET_SIM_NETWORKS, resetReason);
+    }
+
+    /**
+     * Get Network object of current wifi network
+     * @return Network object of current wifi network
+     */
+    public Network getCurrentNetwork() {
+        synchronized (mNetworkAgentLock) {
+            if (mNetworkAgent != null) {
+                return mNetworkAgent.getNetwork();
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Send a message indicating bluetooth adapter connection state changed
+     */
+    public void sendBluetoothAdapterStateChange(int state) {
+        sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0);
+    }
+
+    /**
+     * Send a message indicating bluetooth adapter connection state changed, e.g., connected
+     * or disconnected. Note that turning off BT after pairing success keeps connection state in
+     * connected state.
+     */
+    public void sendBluetoothAdapterConnectionStateChange(int state) {
+        sendMessage(CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE, state, 0);
+    }
+
+    /**
+     * Trigger dump on the class IpClient object.
+     */
+    public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mIpClient != null) {
+            // All dumpIpClient does is print this log message.
+            // TODO: consider deleting this, since it's not useful.
+            pw.println("IpClient logs have moved to dumpsys network_stack");
+        }
+    }
+
+    private static String dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults) {
+        return new StringBuilder()
+                .append("baseConfiguration ").append(dhcpResults.baseConfiguration)
+                .append("leaseDuration ").append(dhcpResults.leaseDuration)
+                .append("mtu ").append(dhcpResults.mtu)
+                .append("serverAddress ").append(dhcpResults.serverAddress)
+                .append("serverHostName ").append(dhcpResults.serverHostName)
+                .append("vendorInfo ").append(dhcpResults.vendorInfo)
+                .toString();
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        super.dump(fd, pw, args);
+        mSupplicantStateTracker.dump(fd, pw, args);
+        pw.println("mLinkProperties " + mLinkProperties);
+        pw.println("mWifiInfo " + mWifiInfo);
+        pw.println("mDhcpResultsParcelable "
+                + dhcpResultsParcelableToString(mDhcpResultsParcelable));
+        pw.println("mLastSignalLevel " + mLastSignalLevel);
+        pw.println("mLastBssid " + mLastBssid);
+        pw.println("mLastNetworkId " + mLastNetworkId);
+        pw.println("mLastSubId " + mLastSubId);
+        pw.println("mLastSimBasedConnectionCarrierName " + mLastSimBasedConnectionCarrierName);
+        pw.println("mOperationalMode " + mOperationalMode);
+        pw.println("mSuspendOptimizationsEnabled " + mContext.getResources().getBoolean(
+                R.bool.config_wifiSuspendOptimizationsEnabled));
+        pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
+        pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount());
+        pw.println();
+
+        mWifiConfigManager.dump(fd, pw, args);
+        pw.println();
+        mPasspointManager.dump(pw);
+        pw.println();
+        dumpIpClient(fd, pw, args);
+        mWifiHealthMonitor.dump(fd, pw, args);
+        mLinkProbeManager.dump(fd, pw, args);
+    }
+
+    /**
+     * ******************************************************
+     * Internal private functions
+     * ******************************************************
+     */
+
+    private void logStateAndMessage(Message message, State state) {
+        mMessageHandlingStatus = 0;
+        if (mVerboseLoggingEnabled) {
+            logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message));
+        }
+    }
+
+    @Override
+    protected boolean recordLogRec(Message msg) {
+        switch (msg.what) {
+            case CMD_RSSI_POLL:
+                return mVerboseLoggingEnabled;
+            default:
+                return true;
+        }
+    }
+
+    /**
+     * Return the additional string to be logged by LogRec, default
+     *
+     * @param msg that was processed
+     * @return information to be logged as a String
+     */
+    @Override
+    protected String getLogRecString(Message msg) {
+        WifiConfiguration config;
+        Long now;
+        String report;
+        String key;
+        StringBuilder sb = new StringBuilder();
+        sb.append("screen=").append(mScreenOn ? "on" : "off");
+        if (mMessageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) {
+            sb.append("(").append(mMessageHandlingStatus).append(")");
+        }
+        if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) {
+            sb.append(" uid=" + msg.sendingUid);
+        }
+        switch (msg.what) {
+            case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
+                if (stateChangeResult != null) {
+                    sb.append(stateChangeResult.toString());
+                }
+                break;
+            case CMD_CONNECT_NETWORK:
+            case CMD_SAVE_NETWORK: {
+                NetworkUpdateResult result = (NetworkUpdateResult) msg.obj;
+                sb.append(" ");
+                sb.append(Integer.toString(result.netId));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                config = mWifiConfigManager.getConfiguredNetwork(result.netId);
+                if (config != null) {
+                    sb.append(" ").append(config.getKey());
+                    sb.append(" nid=").append(config.networkId);
+                    if (config.hiddenSSID) {
+                        sb.append(" hidden");
+                    }
+                    if (config.preSharedKey != null
+                            && !config.preSharedKey.equals("*")) {
+                        sb.append(" hasPSK");
+                    }
+                    if (config.ephemeral) {
+                        sb.append(" ephemeral");
+                    }
+                    sb.append(" cuid=").append(config.creatorUid);
+                    sb.append(" suid=").append(config.lastUpdateUid);
+                }
+                break;
+            }
+            case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+                sb.append(" ");
+                sb.append(" timedOut=" + Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                String bssid = (String) msg.obj;
+                if (bssid != null && bssid.length() > 0) {
+                    sb.append(" ");
+                    sb.append(bssid);
+                }
+                sb.append(" blocklist=" + Boolean.toString(mDidBlockListBSSID));
+                break;
+            case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                sb.append(" ").append(mLastBssid);
+                sb.append(" nid=").append(mLastNetworkId);
+                config = getCurrentWifiConfiguration();
+                if (config != null) {
+                    sb.append(" ").append(config.getKey());
+                }
+                key = mWifiConfigManager.getLastSelectedNetworkConfigKey();
+                if (key != null) {
+                    sb.append(" last=").append(key);
+                }
+                break;
+            case WifiMonitor.TARGET_BSSID_EVENT:
+            case WifiMonitor.ASSOCIATED_BSSID_EVENT:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                if (msg.obj != null) {
+                    sb.append(" BSSID=").append((String) msg.obj);
+                }
+                if (mTargetBssid != null) {
+                    sb.append(" Target=").append(mTargetBssid);
+                }
+                sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
+                break;
+            case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                if (msg.obj != null) {
+                    sb.append(" ").append((String) msg.obj);
+                }
+                sb.append(" nid=").append(msg.arg1);
+                sb.append(" reason=").append(msg.arg2);
+                if (mLastBssid != null) {
+                    sb.append(" lastbssid=").append(mLastBssid);
+                }
+                if (mWifiInfo.getFrequency() != -1) {
+                    sb.append(" freq=").append(mWifiInfo.getFrequency());
+                    sb.append(" rssi=").append(mWifiInfo.getRssi());
+                }
+                break;
+            case CMD_RSSI_POLL:
+            case CMD_ONESHOT_RSSI_POLL:
+            case CMD_UNWANTED_NETWORK:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                if (mWifiInfo.getSSID() != null) {
+                    if (mWifiInfo.getSSID() != null) {
+                        sb.append(" ").append(mWifiInfo.getSSID());
+                    }
+                }
+                if (mWifiInfo.getBSSID() != null) {
+                    sb.append(" ").append(mWifiInfo.getBSSID());
+                }
+                sb.append(" rssi=").append(mWifiInfo.getRssi());
+                sb.append(" f=").append(mWifiInfo.getFrequency());
+                sb.append(" sc=").append(mWifiInfo.getScore());
+                sb.append(" link=").append(mWifiInfo.getLinkSpeed());
+                sb.append(String.format(" tx=%.1f,", mWifiInfo.getSuccessfulTxPacketsPerSecond()));
+                sb.append(String.format(" %.1f,", mWifiInfo.getRetriedTxPacketsPerSecond()));
+                sb.append(String.format(" %.1f ", mWifiInfo.getLostTxPacketsPerSecond()));
+                sb.append(String.format(" rx=%.1f", mWifiInfo.getSuccessfulRxPacketsPerSecond()));
+                sb.append(String.format(" bcn=%d", mRunningBeaconCount));
+                report = reportOnTime();
+                if (report != null) {
+                    sb.append(" ").append(report);
+                }
+                sb.append(String.format(" score=%d", mWifiInfo.getScore()));
+                break;
+            case CMD_START_CONNECT:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                config = mWifiConfigManager.getConfiguredNetwork(msg.arg1);
+                if (config != null) {
+                    sb.append(" targetConfigKey=").append(config.getKey());
+                    sb.append(" BSSID=" + config.BSSID);
+                }
+                if (mTargetBssid != null) {
+                    sb.append(" targetBssid=").append(mTargetBssid);
+                }
+                sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
+                config = getCurrentWifiConfiguration();
+                if (config != null) {
+                    sb.append(" currentConfigKey=").append(config.getKey());
+                }
+                break;
+            case CMD_START_ROAM:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                ScanResult result = (ScanResult) msg.obj;
+                if (result != null) {
+                    now = mClock.getWallClockMillis();
+                    sb.append(" bssid=").append(result.BSSID);
+                    sb.append(" rssi=").append(result.level);
+                    sb.append(" freq=").append(result.frequency);
+                    if (result.seen > 0 && result.seen < now) {
+                        sb.append(" seen=").append(now - result.seen);
+                    } else {
+                        // Somehow the timestamp for this scan result is inconsistent
+                        sb.append(" !seen=").append(result.seen);
+                    }
+                }
+                if (mTargetBssid != null) {
+                    sb.append(" ").append(mTargetBssid);
+                }
+                sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
+                sb.append(" fail count=").append(Integer.toString(mRoamFailCount));
+                break;
+            case CMD_PRE_DHCP_ACTION:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                sb.append(" txpkts=").append(mWifiInfo.txSuccess);
+                sb.append(",").append(mWifiInfo.txBad);
+                sb.append(",").append(mWifiInfo.txRetries);
+                break;
+            case CMD_POST_DHCP_ACTION:
+                if (mLinkProperties != null) {
+                    sb.append(" ");
+                    sb.append(getLinkPropertiesSummary(mLinkProperties));
+                }
+                break;
+            case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                if (msg.obj != null) {
+                    NetworkInfo info = (NetworkInfo) msg.obj;
+                    NetworkInfo.State state = info.getState();
+                    NetworkInfo.DetailedState detailedState = info.getDetailedState();
+                    if (state != null) {
+                        sb.append(" st=").append(state);
+                    }
+                    if (detailedState != null) {
+                        sb.append("/").append(detailedState);
+                    }
+                }
+                break;
+            case CMD_IP_CONFIGURATION_LOST:
+                int count = -1;
+                WifiConfiguration c = getCurrentWifiConfiguration();
+                if (c != null) {
+                    count = c.getNetworkSelectionStatus().getDisableReasonCounter(
+                            WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
+                }
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                sb.append(" failures: ");
+                sb.append(Integer.toString(count));
+                sb.append("/");
+                sb.append(Integer.toString(mFacade.getIntegerSetting(
+                        mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0)));
+                if (mWifiInfo.getBSSID() != null) {
+                    sb.append(" ").append(mWifiInfo.getBSSID());
+                }
+                sb.append(String.format(" bcn=%d", mRunningBeaconCount));
+                break;
+            case CMD_UPDATE_LINKPROPERTIES:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                if (mLinkProperties != null) {
+                    sb.append(" ");
+                    sb.append(getLinkPropertiesSummary(mLinkProperties));
+                }
+                break;
+            case CMD_IP_REACHABILITY_LOST:
+                if (msg.obj != null) {
+                    sb.append(" ").append((String) msg.obj);
+                }
+                break;
+            case CMD_INSTALL_PACKET_FILTER:
+                sb.append(" len=" + ((byte[]) msg.obj).length);
+                break;
+            case CMD_SET_FALLBACK_PACKET_FILTERING:
+                sb.append(" enabled=" + (boolean) msg.obj);
+                break;
+            case CMD_ROAM_WATCHDOG_TIMER:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                sb.append(" cur=").append(mRoamWatchdogCount);
+                break;
+            case CMD_DISCONNECTING_WATCHDOG_TIMER:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                sb.append(" cur=").append(mDisconnectingWatchdogCount);
+                break;
+            case CMD_START_RSSI_MONITORING_OFFLOAD:
+            case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+            case CMD_RSSI_THRESHOLD_BREACHED:
+                sb.append(" rssi=");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" thresholds=");
+                sb.append(Arrays.toString(mRssiRanges));
+                break;
+            case CMD_IPV4_PROVISIONING_SUCCESS:
+                sb.append(" ");
+                sb.append(/* DhcpResultsParcelable */ msg.obj);
+                break;
+            case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE:
+                BtmFrameData frameData = (BtmFrameData) msg.obj;
+                if (frameData != null) {
+                    sb.append(" ").append(frameData.toString());
+                }
+                break;
+            case CMD_IP_REACHABILITY_SESSION_END:
+                if (msg.obj != null) {
+                    sb.append(" ").append((String) msg.obj);
+                }
+                break;
+            default:
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg1));
+                sb.append(" ");
+                sb.append(Integer.toString(msg.arg2));
+                break;
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected String getWhatToString(int what) {
+        String s = sGetWhatToString.get(what);
+        if (s != null) {
+            return s;
+        }
+        switch (what) {
+            case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                s = "CMD_CHANNEL_HALF_CONNECTED";
+                break;
+            case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                s = "CMD_CHANNEL_DISCONNECTED";
+                break;
+            case CMD_CONNECT_NETWORK:
+                s = "CMD_CONNECT_NETWORK";
+                break;
+            case CMD_SAVE_NETWORK:
+                s = "CMD_SAVE_NETWORK";
+                break;
+            case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                s = "SUPPLICANT_STATE_CHANGE_EVENT";
+                break;
+            case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                s = "AUTHENTICATION_FAILURE_EVENT";
+                break;
+            case WifiMonitor.SUP_REQUEST_IDENTITY:
+                s = "SUP_REQUEST_IDENTITY";
+                break;
+            case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                s = "NETWORK_CONNECTION_EVENT";
+                break;
+            case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                s = "NETWORK_DISCONNECTION_EVENT";
+                break;
+            case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+                s = "ASSOCIATION_REJECTION_EVENT";
+                break;
+            case WifiMonitor.ANQP_DONE_EVENT:
+                s = "ANQP_DONE_EVENT";
+                break;
+            case WifiMonitor.RX_HS20_ANQP_ICON_EVENT:
+                s = "RX_HS20_ANQP_ICON_EVENT";
+                break;
+            case WifiMonitor.GAS_QUERY_DONE_EVENT:
+                s = "GAS_QUERY_DONE_EVENT";
+                break;
+            case WifiMonitor.HS20_REMEDIATION_EVENT:
+                s = "HS20_REMEDIATION_EVENT";
+                break;
+            case WifiMonitor.GAS_QUERY_START_EVENT:
+                s = "GAS_QUERY_START_EVENT";
+                break;
+            case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE:
+                s = "MBO_OCE_BSS_TM_HANDLING_DONE";
+                break;
+            case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT:
+                s = "GROUP_CREATING_TIMED_OUT";
+                break;
+            case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
+                s = "P2P_CONNECTION_CHANGED";
+                break;
+            case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
+                s = "DISCONNECT_WIFI_REQUEST";
+                break;
+            case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE:
+                s = "DISCONNECT_WIFI_RESPONSE";
+                break;
+            case WifiP2pServiceImpl.SET_MIRACAST_MODE:
+                s = "SET_MIRACAST_MODE";
+                break;
+            case WifiP2pServiceImpl.BLOCK_DISCOVERY:
+                s = "BLOCK_DISCOVERY";
+                break;
+            default:
+                s = "what:" + Integer.toString(what);
+                break;
+        }
+        return s;
+    }
+
+    private void handleScreenStateChanged(boolean screenOn) {
+        mScreenOn = screenOn;
+        if (mVerboseLoggingEnabled) {
+            logd(" handleScreenStateChanged Enter: screenOn=" + screenOn
+                    + " mSuspendOptimizationsEnabled="
+                    + mContext.getResources().getBoolean(
+                            R.bool.config_wifiSuspendOptimizationsEnabled)
+                    + " state " + getCurrentState().getName());
+        }
+        enableRssiPolling(screenOn);
+        if (mContext.getResources().getBoolean(R.bool.config_wifiSuspendOptimizationsEnabled)) {
+            int shouldReleaseWakeLock = 0;
+            if (screenOn) {
+                sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock);
+            } else {
+                if (isConnected()) {
+                    // Allow 2s for suspend optimizations to be set
+                    mSuspendWakeLock.acquire(2000);
+                    shouldReleaseWakeLock = 1;
+                }
+                sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock);
+            }
+        }
+
+        getWifiLinkLayerStats();
+        mOnTimeScreenStateChange = mOnTime;
+        mLastScreenStateChangeTimeStamp = mLastLinkLayerStatsUpdate;
+
+        if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn);
+    }
+
+    private void setSuspendOptimizationsNative(int reason, boolean enabled) {
+        if (mVerboseLoggingEnabled) {
+            log("setSuspendOptimizationsNative: " + reason + " " + enabled
+                    + " -want " + mContext.getResources().getBoolean(
+                            R.bool.config_wifiSuspendOptimizationsEnabled)
+                    + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
+        }
+        //mWifiNative.setSuspendOptimizations(enabled);
+
+        if (enabled) {
+            mSuspendOptNeedsDisabled &= ~reason;
+            /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
+            if (mSuspendOptNeedsDisabled == 0
+                    && mContext.getResources().getBoolean(
+                            R.bool.config_wifiSuspendOptimizationsEnabled)) {
+                if (mVerboseLoggingEnabled) {
+                    log("setSuspendOptimizationsNative do it " + reason + " " + enabled
+                            + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
+                            + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
+                            + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
+                            + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
+                }
+                mWifiNative.setSuspendOptimizations(mInterfaceName, true);
+            }
+        } else {
+            mSuspendOptNeedsDisabled |= reason;
+            mWifiNative.setSuspendOptimizations(mInterfaceName, false);
+        }
+    }
+
+    /**
+     * Makes a record of the user intent about suspend optimizations.
+     */
+    private void setSuspendOptimizations(int reason, boolean enabled) {
+        if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled);
+        if (enabled) {
+            mSuspendOptNeedsDisabled &= ~reason;
+        } else {
+            mSuspendOptNeedsDisabled |= reason;
+        }
+        if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
+    }
+
+    /*
+     * Fetch RSSI, linkspeed, and frequency on current connection
+     */
+    private void fetchRssiLinkSpeedAndFrequencyNative() {
+        WifiNl80211Manager.SignalPollResult pollResult = mWifiNative.signalPoll(mInterfaceName);
+        if (pollResult == null) {
+            return;
+        }
+
+        int newRssi = pollResult.currentRssiDbm;
+        int newTxLinkSpeed = pollResult.txBitrateMbps;
+        int newFrequency = pollResult.associationFrequencyMHz;
+        int newRxLinkSpeed = pollResult.rxBitrateMbps;
+
+        if (mVerboseLoggingEnabled) {
+            logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi
+                    + " TxLinkspeed=" + newTxLinkSpeed + " freq=" + newFrequency
+                    + " RxLinkSpeed=" + newRxLinkSpeed);
+        }
+
+        if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
+            /*
+             * Positive RSSI is possible when devices are close(~0m apart) to each other.
+             * And there are some driver/firmware implementation, where they avoid
+             * reporting large negative rssi values by adding 256.
+             * so adjust the valid rssi reports for such implementations.
+             */
+            if (newRssi > (WifiInfo.INVALID_RSSI + 256)) {
+                Log.wtf(TAG, "Error! +ve value RSSI: " + newRssi);
+                newRssi -= 256;
+            }
+            mWifiInfo.setRssi(newRssi);
+            /*
+             * Rather then sending the raw RSSI out every time it
+             * changes, we precalculate the signal level that would
+             * be displayed in the status bar, and only send the
+             * broadcast if that much more coarse-grained number
+             * changes. This cuts down greatly on the number of
+             * broadcasts, at the cost of not informing others
+             * interested in RSSI of all the changes in signal
+             * level.
+             */
+            int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi);
+            if (newSignalLevel != mLastSignalLevel) {
+                updateCapabilities();
+                sendRssiChangeBroadcast(newRssi);
+            }
+            mLastSignalLevel = newSignalLevel;
+        } else {
+            mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
+            updateCapabilities();
+        }
+        /*
+         * set Tx link speed only if it is valid
+         */
+        if (newTxLinkSpeed > 0) {
+            mWifiInfo.setLinkSpeed(newTxLinkSpeed);
+            mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed);
+        }
+        /*
+         * set Rx link speed only if it is valid
+         */
+        if (newRxLinkSpeed > 0) {
+            mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
+        }
+        if (newFrequency > 0) {
+            updateConnectedBand(newFrequency, true);
+        }
+        mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo);
+    }
+
+    // Polling has completed, hence we won't have a score anymore
+    private void cleanWifiScore() {
+        mWifiInfo.setLostTxPacketsPerSecond(0);
+        mWifiInfo.setSuccessfulTxPacketsPerSecond(0);
+        mWifiInfo.setRetriedTxPacketsRate(0);
+        mWifiInfo.setSuccessfulRxPacketsPerSecond(0);
+        mWifiScoreReport.reset();
+        mLastLinkLayerStats = null;
+    }
+
+    private void updateLinkProperties(LinkProperties newLp) {
+        if (mVerboseLoggingEnabled) {
+            log("Link configuration changed for netId: " + mLastNetworkId
+                    + " old: " + mLinkProperties + " new: " + newLp);
+        }
+        // We own this instance of LinkProperties because IpClient passes us a copy.
+        mLinkProperties = newLp;
+        if (mNetworkAgent != null) {
+            mNetworkAgent.sendLinkProperties(mLinkProperties);
+        }
+
+        if (mNetworkAgentState == DetailedState.CONNECTED) {
+            // If anything has changed and we're already connected, send out a notification.
+            // TODO: Update all callers to use NetworkCallbacks and delete this.
+            sendLinkConfigurationChangedBroadcast();
+        }
+
+        if (mVerboseLoggingEnabled) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("updateLinkProperties nid: " + mLastNetworkId);
+            sb.append(" state: " + mNetworkAgentState);
+
+            if (mLinkProperties != null) {
+                sb.append(" ");
+                sb.append(getLinkPropertiesSummary(mLinkProperties));
+            }
+            logd(sb.toString());
+        }
+    }
+
+    /**
+     * Clears all our link properties.
+     */
+    private void clearLinkProperties() {
+        // Clear the link properties obtained from DHCP. The only caller of this
+        // function has already called IpClient#stop(), which clears its state.
+        synchronized (mDhcpResultsParcelableLock) {
+            mDhcpResultsParcelable = new DhcpResultsParcelable();
+        }
+
+        // Now clear the merged link properties.
+        mLinkProperties.clear();
+        if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
+    }
+
+    private void sendRssiChangeBroadcast(final int newRssi) {
+        mBatteryStatsManager.reportWifiRssiChanged(newRssi);
+        WifiStatsLog.write(WifiStatsLog.WIFI_SIGNAL_STRENGTH_CHANGED,
+        RssiUtil.calculateSignalLevel(mContext, newRssi));
+        mListener.onRssiChanged(mIdentity, newRssi);
+    }
+
+    private void sendNetworkStateChangeBroadcast() {
+        mListener.onNetworkStateChanged(mIdentity, mNetworkInfo);
+    }
+
+    private void sendLinkConfigurationChangedBroadcast() {
+        mListener.onLinkConfigurationChanged(mIdentity, new LinkProperties(mLinkProperties));
+    }
+
+    private NetworkInfo makeNetworkInfo() {
+        final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
+        ni.setDetailedState(mNetworkAgentState, null, null);
+        return ni;
+    }
+
+    private SupplicantState handleSupplicantStateChange(Message message) {
+        StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+        SupplicantState state = stateChangeResult.state;
+        mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, state);
+        // Supplicant state change
+        // [31-13] Reserved for future use
+        // [8 - 0] Supplicant state (as defined in SupplicantState.java)
+        // 50023 supplicant_state_changed (custom|1|5)
+        mWifiInfo.setSupplicantState(state);
+        // Network id and SSID are only valid when we start connecting
+        if (SupplicantState.isConnecting(state)) {
+            mWifiInfo.setNetworkId(stateChangeResult.networkId);
+            mWifiInfo.setBSSID(stateChangeResult.BSSID);
+            mWifiInfo.setSSID(stateChangeResult.wifiSsid);
+            if (state == SupplicantState.ASSOCIATED) {
+                updateWifiInfoAfterAssociation();
+            }
+        } else {
+            // Reset parameters according to WifiInfo.reset()
+            mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
+            mWifiInfo.setBSSID(null);
+            mWifiInfo.setSSID(null);
+            mWifiInfo.setWifiStandard(ScanResult.WIFI_STANDARD_UNKNOWN);
+        }
+        updateLayer2Information();
+        // SSID might have been updated, so call updateCapabilities
+        updateCapabilities();
+
+        WifiConfiguration config = getCurrentWifiConfiguration();
+        if (config == null) {
+            // If not connected, this should be non-null.
+            config = getTargetWifiConfiguration();
+        }
+        if (config != null && config.networkId == mWifiInfo.getNetworkId()) {
+            mWifiInfo.setEphemeral(config.ephemeral);
+            mWifiInfo.setTrusted(config.trusted);
+            mWifiInfo.setOsuAp(config.osu);
+            if (config.fromWifiNetworkSpecifier || config.fromWifiNetworkSuggestion) {
+                mWifiInfo.setRequestingPackageName(config.creatorName);
+            }
+
+            // Set meteredHint if scan result says network is expensive
+            ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(
+                    config.networkId);
+            if (scanDetailCache != null) {
+                ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID);
+                if (scanDetail != null) {
+                    updateConnectedBand(scanDetail.getScanResult().frequency, true);
+                    NetworkDetail networkDetail = scanDetail.getNetworkDetail();
+                    if (networkDetail != null
+                            && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) {
+                        mWifiInfo.setMeteredHint(true);
+                    }
+                }
+            }
+        }
+        mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
+        return state;
+    }
+
+    private void updateWifiInfoAfterAssociation() {
+        WifiNative.ConnectionCapabilities capabilities =
+                mWifiNative.getConnectionCapabilities(mInterfaceName);
+        ThroughputPredictor throughputPredictor = mWifiInjector.getThroughputPredictor();
+        int maxTxLinkSpeedMbps = throughputPredictor.predictMaxTxThroughput(capabilities);
+        int maxRxLinkSpeedMbps = throughputPredictor.predictMaxRxThroughput(capabilities);
+        mWifiInfo.setWifiStandard(capabilities.wifiStandard);
+        updateQcWifiGenerationInfo();
+        mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps);
+        mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps);
+        mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(
+                maxTxLinkSpeedMbps, maxRxLinkSpeedMbps);
+        mWifiDataStall.setConnectionCapabilities(capabilities);
+        if (mVerboseLoggingEnabled) {
+            StringBuilder sb = new StringBuilder();
+            logd(sb.append("WifiStandard: ").append(capabilities.wifiStandard)
+                    .append(" vhtMax8SS: ").append(mWifiInfo.isVhtMax8SpatialStreamsSupported())
+                    .append(" he8ssAp: ").append(mWifiInfo.isHe8ssCapableAp())
+                    .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps)
+                    .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps)
+                    .toString());
+        }
+    }
+
+    public ScanResult getScanResultForBssid(String bssid) {
+      ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(mInterfaceName);
+      ScanResult scanRes;
+          for (ScanDetail result : scanResults) {
+              scanRes = result.getScanResult();
+              Log.e(TAG, "getScanResults scanRes.BSSID = " + scanRes.BSSID);
+              if (scanRes.BSSID.equals(bssid))
+                  return scanRes;
+          }
+          return null;
+    }
+
+    /**
+     * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore.
+     */
+    private void updateLayer2Information() {
+        if (mIpClient != null) {
+            Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo);
+            if (!p.equals(mLastL2KeyAndGroupHint)) {
+                final MacAddress lastBssid = getCurrentBssid();
+                final Layer2Information l2Information = new Layer2Information(
+                        p.first, p.second, lastBssid);
+                // Update current BSSID on IpClient side whenever l2Key and groupHint
+                // pair changes (i.e. the initial connection establishment or L2 roaming
+                // happened). If we have COMPLETED the roaming to a different BSSID, start
+                // doing DNAv4/DNAv6 -style probing for on-link neighbors of interest (e.g.
+                // routers/DNS servers/default gateway).
+                if (mIpClient.updateLayer2Information(l2Information)) {
+                    mLastL2KeyAndGroupHint = p;
+                } else {
+                    mLastL2KeyAndGroupHint = null;
+                }
+            }
+        }
+    }
+    private @Nullable Pair<String, String> mLastL2KeyAndGroupHint = null;
+
+    /**
+     * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
+     * using the interface, stopping DHCP & disabling interface
+     */
+    private void handleNetworkDisconnect() {
+        if (mVerboseLoggingEnabled) {
+            log("handleNetworkDisconnect:"
+                    + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
+                    + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
+        }
+        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+        stopRssiMonitoringOffload();
+        sendNetworkStateChangeBroadcast();
+        clearTargetBssid("handleNetworkDisconnect");
+
+        // Don't stop DHCP if Fils connection is in progress.
+        if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
+                && mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID
+                && mLastNetworkId != mTargetNetworkId && mIpClientWithPreConnection) {
+            if (mVerboseLoggingEnabled) {
+                log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: "
+                        + " mLastNetworkId: " + mLastNetworkId
+                        + " mTargetNetworkId" + mTargetNetworkId);
+            }
+        } else {
+            stopDhcpSetup();
+        }
+        // update connected band before WifiInfo reset.
+        updateConnectedBand(mWifiInfo.getFrequency(), false);
+        mWifiScoreReport.stopConnectedNetworkScorer();
+        /* Reset data structures */
+        mWifiScoreReport.reset();
+        mWifiInfo.reset();
+        /* Reset roaming parameters */
+        mIsAutoRoaming = false;
+
+        synchronized (mNetworkAgentLock) {
+            if (mNetworkAgent != null) {
+                mNetworkAgent.unregister();
+                mNetworkAgent = null;
+            }
+        }
+
+        /* Clear network properties */
+        clearLinkProperties();
+
+        mLastBssid = null;
+        mLastLinkLayerStats = null;
+        registerDisconnected();
+        mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+        mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        mLastSimBasedConnectionCarrierName = null;
+        mWifiScoreCard.resetConnectionState();
+        mWifiDataStall.reset();
+        updateLayer2Information();
+    }
+
+    void handlePreDhcpSetup() {
+        // Disable the coexistence mode
+        mWifiNative.setBluetoothCoexistenceMode(
+            mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+
+        // Disable power save and suspend optimizations during DHCP
+        // Note: The order here is important for now. Brcm driver changes
+        // power settings when we control suspend mode optimizations.
+        // TODO: Remove this comment when the driver is fixed.
+        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
+        setPowerSave(false);
+
+        // Update link layer stats
+        getWifiLinkLayerStats();
+
+        if (mWifiP2pChannel != null) {
+            /* P2p discovery breaks dhcp, shut it down in order to get through this */
+            Message msg = new Message();
+            msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY;
+            msg.arg1 = WifiP2pServiceImpl.ENABLED;
+            msg.arg2 = CMD_PRE_DHCP_ACTION_COMPLETE;
+            msg.obj = QtiClientModeImpl.this;
+            mWifiP2pChannel.sendMessage(msg);
+        } else {
+            // If the p2p service is not running, we can proceed directly.
+            sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE);
+        }
+    }
+
+
+    void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) {
+        List<Layer2PacketParcelable> mLayer2Packet = packets;
+        if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) {
+            mWifiNative.flushAllHlp(mInterfaceName);
+
+            for (int j = 0; j < mLayer2Packet.size(); j++) {
+                byte [] bytes = mLayer2Packet.get(j).payload;
+                byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length);
+                MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress;
+
+                mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes);
+            }
+        }
+    }
+
+    void handlePostDhcpSetup() {
+        /* Restore power save and suspend optimizations */
+        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
+        setPowerSave(true);
+
+        p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED);
+
+        // Set the coexistence mode back to its default value
+        mWifiNative.setBluetoothCoexistenceMode(
+                mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
+    }
+
+    public String getCapabilities(String capaType) {
+
+        return mWifiNative.getCapabilities(mInterfaceName, capaType);
+    }
+
+    /**
+     * Set power save mode
+     *
+     * @param ps true to enable power save (default behavior)
+     *           false to disable power save.
+     * @return true for success, false for failure
+     */
+    public boolean setPowerSave(boolean ps) {
+        if (mInterfaceName != null) {
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Setting power save for: " + mInterfaceName + " to: " + ps);
+            }
+            mWifiNative.setPowerSave(mInterfaceName, ps);
+        } else {
+            Log.e(TAG, "Failed to setPowerSave, interfaceName is null");
+            return false;
+        }
+        return true;
+    }
+
+    @VisibleForTesting
+    public static final long DIAGS_CONNECT_TIMEOUT_MILLIS = 60 * 1000;
+
+    private WifiGenerationStatus getWifiGenerationStatus() {
+         if (mInterfaceName == null)
+             return null;
+
+        return mWifiNative.getWifiGenerationStatus(mInterfaceName);
+    }
+
+    /**
+     * Inform other components that a new connection attempt is starting.
+     */
+    private void reportConnectionAttemptStart(
+            WifiConfiguration config, String targetBSSID, int roamType) {
+        mWrongPasswordNotifier.onNewConnectionAttempt();
+    }
+
+    private void handleConnectionAttemptEndForDiagnostics(int level2FailureCode) {
+        switch (level2FailureCode) {
+            case WifiMetrics.ConnectionEvent.FAILURE_NONE:
+                break;
+            case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED:
+                // WifiDiagnostics doesn't care about pre-empted connections, or cases
+                // where we failed to initiate a connection attempt with supplicant.
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Inform other components (WifiMetrics, WifiDiagnostics, QtiWifiConnectivityManager, etc.) that
+     * the current connection attempt has concluded.
+     */
+    private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode,
+            int level2FailureReason) {
+        // if connected, this should be non-null.
+        WifiConfiguration configuration = getCurrentWifiConfiguration();
+        if (configuration == null) {
+            // If not connected, this should be non-null.
+            configuration = getTargetWifiConfiguration();
+        }
+
+        String bssid = mLastBssid == null ? mTargetBssid : mLastBssid;
+        String ssid = mWifiInfo.getSSID();
+        if (WifiManager.UNKNOWN_SSID.equals(ssid)) {
+            ssid = getTargetSsid();
+        }
+        if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) {
+            updateConnectedBand(mWifiInfo.getFrequency(), false);
+            int blocklistReason = convertToBssidBlocklistMonitorFailureReason(
+                    level2FailureCode, level2FailureReason);
+            if (blocklistReason != -1) {
+                int networkId = (configuration == null) ? WifiConfiguration.INVALID_NETWORK_ID
+                        : configuration.networkId;
+                int scanRssi = mWifiConfigManager.findScanRssi(networkId,
+                        mWifiHealthMonitor.getScanRssiValidTimeMs());
+                mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason);
+            }
+        }
+        handleConnectionAttemptEndForDiagnostics(level2FailureCode);
+    }
+
+    /* If this connection attempt fails after 802.1x stage, clear intermediate cached data. */
+    void clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason) {
+        if (config == null) return;
+
+        switch(reason) {
+            case 14: // MICHAEL_MIC_FAILURE
+            case 15: // 4WAY_HANDSHAKE_TIMEOUT
+            case 16: // GROUP_KEY_UPDATE_TIMEOUT
+            case 17: // IE_IN_4WAY_DIFFERS
+            case 18: // GROUP_CIPHER_NOT_VALID
+            case 19: // PAIRWISE_CIPHER_NOT_VALID
+            case 20: // AKMP_NOT_VALID
+            case 23: // IEEE_802_1X_AUTH_FAILED
+            case 24: // CIPHER_SUITE_REJECTED
+            case 29: // BAD_CIPHER_OR_AKM
+            case 45: // PEERKEY_MISMATCH
+            case 49: // INVALID_PMKID
+                mWifiNative.removeNetworkCachedData(config.networkId);
+                break;
+            default:
+                logi("Keep PMK cache for network disconnection reason " + reason);
+                break;
+        }
+    }
+
+    /**
+     * Returns the sufficient RSSI for the frequency that this network is last seen on.
+     */
+    private int getSufficientRssi(int networkId, String bssid) {
+        ScanDetailCache scanDetailCache =
+                mWifiConfigManager.getScanDetailCacheForNetwork(networkId);
+        if (scanDetailCache == null) {
+            return WifiInfo.INVALID_RSSI;
+        }
+        ScanResult scanResult = scanDetailCache.getScanResult(bssid);
+        if (scanResult == null) {
+            return WifiInfo.INVALID_RSSI;
+        }
+        return mWifiInjector.getScoringParams().getSufficientRssi(scanResult.frequency);
+    }
+
+    private int convertToBssidBlocklistMonitorFailureReason(
+            int level2FailureCode, int failureReason) {
+        switch (level2FailureCode) {
+            case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT:
+                return BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT;
+            case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION:
+                if (failureReason == WifiMetricsProto.ConnectionEvent
+                        .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) {
+                    return BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA;
+                }
+                return BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION;
+            case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE:
+                if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) {
+                    return BssidBlocklistMonitor.REASON_WRONG_PASSWORD;
+                } else if (failureReason == WifiMetricsProto.ConnectionEvent
+                        .AUTH_FAILURE_EAP_FAILURE) {
+                    return BssidBlocklistMonitor.REASON_EAP_FAILURE;
+                }
+                return BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE;
+            case WifiMetrics.ConnectionEvent.FAILURE_DHCP:
+                return BssidBlocklistMonitor.REASON_DHCP_FAILURE;
+            default:
+                return -1;
+        }
+    }
+
+    private void handleIPv4Success(DhcpResultsParcelable dhcpResults) {
+        if (mVerboseLoggingEnabled) {
+            logd("handleIPv4Success <" + dhcpResults.toString() + ">");
+            logd("link address " + dhcpResults.baseConfiguration.getIpAddress());
+        }
+
+        Inet4Address addr;
+        synchronized (mDhcpResultsParcelableLock) {
+            mDhcpResultsParcelable = dhcpResults;
+            addr = (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress();
+        }
+
+        if (mIsAutoRoaming) {
+            int previousAddress = mWifiInfo.getIpAddress();
+            int newAddress = Inet4AddressUtils.inet4AddressToIntHTL(addr);
+            if (previousAddress != newAddress) {
+                logd("handleIPv4Success, roaming and address changed"
+                        + mWifiInfo + " got: " + addr);
+            }
+        }
+
+        mWifiInfo.setInetAddress(addr);
+
+        final WifiConfiguration config = getCurrentWifiConfiguration();
+        if (config != null) {
+            mWifiInfo.setEphemeral(config.ephemeral);
+            mWifiInfo.setTrusted(config.trusted);
+            mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.leaseDuration);
+            mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid, mWifiInfo.getSSID());
+        }
+
+        // Set meteredHint if DHCP result says network is metered
+        if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) {
+            mWifiInfo.setMeteredHint(true);
+            mWifiMetrics.addMeteredStat(config, true);
+        } else {
+            mWifiMetrics.addMeteredStat(config, false);
+        }
+
+        updateCapabilities(config);
+    }
+
+    private void handleSuccessfulIpConfiguration() {
+        mLastSignalLevel = -1; // Force update of signal strength
+        WifiConfiguration c = getCurrentWifiConfiguration();
+        if (c != null) {
+            // Reset IP failure tracking
+            c.getNetworkSelectionStatus().clearDisableReasonCounter(
+                    WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
+
+            // Tell the framework whether the newly connected network is trusted or untrusted.
+            updateCapabilities(c);
+        }
+        mWifiScoreCard.noteIpConfiguration(mWifiInfo);
+    }
+
+    private void handleIPv4Failure() {
+        // TODO: Move this to provisioning failure, not DHCP failure.
+        // DHCPv4 failure is expected on an IPv6-only network.
+        if (mVerboseLoggingEnabled) {
+            int count = -1;
+            WifiConfiguration config = getCurrentWifiConfiguration();
+            if (config != null) {
+                count = config.getNetworkSelectionStatus().getDisableReasonCounter(
+                        WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
+            }
+            log("DHCP failure count=" + count);
+        }
+        reportConnectionAttemptEnd(
+                WifiMetrics.ConnectionEvent.FAILURE_DHCP,
+                WifiMetricsProto.ConnectionEvent.HLF_DHCP,
+                WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+        synchronized (mDhcpResultsParcelableLock) {
+            mDhcpResultsParcelable = new DhcpResultsParcelable();
+        }
+        if (mVerboseLoggingEnabled) {
+            logd("handleIPv4Failure");
+        }
+    }
+
+    private void handleIpConfigurationLost() {
+        mWifiInfo.setInetAddress(null);
+        mWifiInfo.setMeteredHint(false);
+
+        mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId,
+                WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
+
+        /* DHCP times out after about 30 seconds, we do a
+         * disconnect thru supplicant, we will let autojoin retry connecting to the network
+         */
+        mWifiNative.disconnect(mInterfaceName);
+    }
+
+    private void handleIpReachabilityLost() {
+        mWifiScoreCard.noteIpReachabilityLost(mWifiInfo);
+        mWifiInfo.setInetAddress(null);
+        mWifiInfo.setMeteredHint(false);
+
+        // Disconnect via supplicant, and let autojoin retry connecting to the network.
+        mWifiNative.disconnect(mInterfaceName);
+    }
+
+    /*
+     * Read a MAC address in /proc/arp/table, used by QtiClientModeImpl
+     * so as to record MAC address of default gateway.
+     **/
+    private String macAddressFromRoute(String ipAddress) {
+        String macAddress = null;
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader("/proc/net/arp"));
+
+            // Skip over the line bearing column titles
+            String line = reader.readLine();
+
+            while ((line = reader.readLine()) != null) {
+                String[] tokens = line.split("[ ]+");
+                if (tokens.length < 6) {
+                    continue;
+                }
+
+                // ARP column format is
+                // Address HWType HWAddress Flags Mask IFace
+                String ip = tokens[0];
+                String mac = tokens[3];
+
+                if (ipAddress.equals(ip)) {
+                    macAddress = mac;
+                    break;
+                }
+            }
+
+            if (macAddress == null) {
+                loge("Did not find remoteAddress {" + ipAddress + "} in /proc/net/arp");
+            }
+
+        } catch (FileNotFoundException e) {
+            loge("Could not open /proc/net/arp to lookup mac address");
+        } catch (IOException e) {
+            loge("Could not read /proc/net/arp to lookup mac address");
+        } finally {
+            try {
+                if (reader != null) {
+                    reader.close();
+                }
+            } catch (IOException e) {
+                // Do nothing
+            }
+        }
+        return macAddress;
+
+    }
+
+    /**
+     * Determine if the specified auth failure is considered to be a permanent wrong password
+     * failure. The criteria for such failure is when wrong password error is detected
+     * and the network had never been connected before.
+     *
+     * For networks that have previously connected successfully, we consider wrong password
+     * failures to be temporary, to be on the conservative side.  Since this might be the
+     * case where we are trying to connect to a wrong network (e.g. A network with same SSID
+     * but different password).
+     */
+    private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) {
+        if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) {
+            return false;
+        }
+        WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId);
+        if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * QtiClientModeImpl needs to enable/disable other services when wifi is in client mode.  This
+     * method allows QtiClientModeImpl to get these additional system services.
+     *
+     * At this time, this method is used to setup variables for P2P service and Wifi Aware.
+     */
+    private void getAdditionalWifiServiceInterfaces() {
+        // First set up Wifi Direct
+        if (mP2pSupported) {
+            WifiP2pManager wifiP2pService = mContext.getSystemService(WifiP2pManager.class);
+
+            if (wifiP2pService != null) {
+                mWifiP2pChannel = new AsyncChannel();
+                mWifiP2pChannel.connect(mContext, getHandler(),
+                        wifiP2pService.getP2pStateMachineMessenger());
+            }
+        }
+    }
+
+     /**
+     * Dynamically change the MAC address to use the locally randomized
+     * MAC address generated for each network.
+     * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address
+     * is masked out or not set, it will generate a new random MAC address.
+     */
+    private void configureRandomizedMacAddress(WifiConfiguration config) {
+        if (config == null) {
+            Log.e(TAG, "No config to change MAC address to");
+            return;
+        }
+
+        try {
+            String currentMacString = mWifiNative.getMacAddress(mInterfaceName);
+            MacAddress currentMac = currentMacString == null ? null :
+                    MacAddress.fromString(currentMacString);
+            MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config);
+            if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) {
+                Log.wtf(TAG, "Config generated an invalid MAC address");
+            } else if (currentMac.equals(newMac)) {
+                Log.d(TAG, "No changes in MAC address");
+            } else {
+                mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config);
+                boolean setMacSuccess =
+                        mWifiNative.setMacAddress(mInterfaceName, newMac);
+                if (setMacSuccess) {
+                    mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac);
+                }
+                Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid()
+                        + "). setMacAddress(" + newMac.toString() + ") from "
+                        + currentMacString + " = " + setMacSuccess);
+            }
+        } catch (NullPointerException | IllegalArgumentException e) {
+            Log.e(TAG, "Exception in configureRandomizedMacAddress: " + e.toString());
+        }
+    }
+
+    /**
+     * Sets the current MAC to the factory MAC address.
+     */
+    private void setCurrentMacToFactoryMac(WifiConfiguration config) {
+        MacAddress factoryMac = mWifiNative.getFactoryMacAddress(mInterfaceName);
+        if (factoryMac == null) {
+            Log.e(TAG, "Fail to set factory MAC address. Factory MAC is null.");
+            return;
+        }
+        String currentMacStr = mWifiNative.getMacAddress(mInterfaceName);
+        if (!TextUtils.equals(currentMacStr, factoryMac.toString())) {
+            if (mWifiNative.setMacAddress(mInterfaceName, factoryMac)) {
+                mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac);
+            } else {
+                Log.e(TAG, "Failed to set MAC address to " + "'" + factoryMac.toString() + "'");
+            }
+        }
+    }
+
+    /**
+     * Helper method to check if Connected MAC Randomization is supported - onDown events are
+     * skipped if this feature is enabled (b/72459123).
+     *
+     * @return boolean true if Connected MAC randomization is supported, false otherwise
+     */
+    public boolean isConnectedMacRandomizationEnabled() {
+        return mContext.getResources().getBoolean(
+                R.bool.config_wifi_connected_mac_randomization_supported);
+    }
+
+    /**
+     * Helper method to check if WPA2 network upgrade feature is enabled in the framework
+     *
+     * @return boolean true if feature is enabled.
+     */
+    private boolean isWpa3SaeUpgradeEnabled() {
+        return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeEnabled);
+    }
+
+    /**
+     * Helper method to check if WPA2 network upgrade offload is enabled in the driver/fw
+     *
+     * @return boolean true if feature is enabled.
+     */
+    private boolean isWpa3SaeUpgradeOffloadEnabled() {
+        return mContext.getResources().getBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled);
+    }
+
+    /********************************************************
+     * HSM states
+     *******************************************************/
+
+    class DefaultState extends State {
+
+        @Override
+        public boolean processMessage(Message message) {
+            boolean handleStatus = HANDLED;
+            int callbackIdentifier = -1;
+            int netId;
+            boolean ok;
+
+            switch (message.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
+                    AsyncChannel ac = (AsyncChannel) message.obj;
+                    if (ac == mWifiP2pChannel) {
+                        if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                            p2pSendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                        } else {
+                            // TODO: We should probably do some cleanup or attempt a retry
+                            // b/34283611
+                            loge("WifiP2pService connection failure, error=" + message.arg1);
+                        }
+                    } else {
+                        loge("got HALF_CONNECTED for unknown channel");
+                    }
+                    break;
+                }
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+                    AsyncChannel ac = (AsyncChannel) message.obj;
+                    if (ac == mWifiP2pChannel) {
+                        loge("WifiP2pService channel lost, message.arg1 =" + message.arg1);
+                        //TODO: Re-establish connection to state machine after a delay (b/34283611)
+                        // mWifiP2pChannel.connect(mContext, getHandler(),
+                        // mWifiP2pManager.getMessenger());
+                    }
+                    break;
+                }
+                case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
+                    // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE
+                    // message. So we need to rely on STATE_CHANGE message to detect on->off
+                    // transition and update mBluetoothConnectionActive status correctly.
+                    mBluetoothConnectionActive = mBluetoothConnectionActive
+                            && message.arg1 != BluetoothAdapter.STATE_OFF;
+                    mQtiWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive);
+                    break;
+                case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE:
+                    // Transition to a non-disconnected state does correctly
+                    // indicate BT is connected or being connected.
+                    mBluetoothConnectionActive =
+                            message.arg1 != BluetoothAdapter.STATE_DISCONNECTED;
+                    mQtiWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive);
+                    break;
+                case CMD_ENABLE_RSSI_POLL:
+                    mEnableRssiPolling = (message.arg1 == 1);
+                    break;
+                case CMD_SET_HIGH_PERF_MODE:
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false);
+                    } else {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
+                    }
+                    break;
+                case CMD_SCREEN_STATE_CHANGED:
+                    handleScreenStateChanged(message.arg1 != 0);
+                    break;
+                case CMD_DISCONNECT:
+                case CMD_RECONNECT:
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+                case CMD_RSSI_POLL:
+                case CMD_ONESHOT_RSSI_POLL:
+                case CMD_PRE_DHCP_ACTION:
+                case CMD_PRE_DHCP_ACTION_COMPLETE:
+                case CMD_POST_DHCP_ACTION:
+                case WifiMonitor.SUP_REQUEST_IDENTITY:
+                case WifiMonitor.SUP_REQUEST_SIM_AUTH:
+                case WifiMonitor.TARGET_BSSID_EVENT:
+                case CMD_START_CONNECT:
+                case CMD_START_ROAM:
+                case WifiMonitor.ASSOCIATED_BSSID_EVENT:
+                case CMD_UNWANTED_NETWORK:
+                case CMD_DISCONNECTING_WATCHDOG_TIMER:
+                case CMD_ROAM_WATCHDOG_TIMER:
+                case CMD_IP_REACHABILITY_SESSION_END:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
+                case CMD_SET_OPERATIONAL_MODE:
+                    // using the CMD_SET_OPERATIONAL_MODE (sent at front of queue) to trigger the
+                    // state transitions performed in setOperationalMode.
+                    break;
+                case CMD_SET_SUSPEND_OPT_ENABLED:
+                    if (message.arg1 == 1) {
+                        if (message.arg2 == 1) {
+                            mSuspendWakeLock.release();
+                        }
+                        setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true);
+                    } else {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false);
+                    }
+                    break;
+                case CMD_CONNECT_NETWORK:
+                    // wifi off, can't connect.
+                    callbackIdentifier = message.arg2;
+                    sendActionListenerFailure(callbackIdentifier, WifiManager.BUSY);
+                    break;
+                case CMD_SAVE_NETWORK:
+                    // wifi off, nothing more to do here.
+                    callbackIdentifier = message.arg2;
+                    sendActionListenerSuccess(callbackIdentifier);
+                    break;
+                case CMD_GET_SUPPORTED_FEATURES:
+                    long featureSet = (mWifiNative.getSupportedFeatureSet(mInterfaceName));
+                    replyToMessage(message, message.what, Long.valueOf(featureSet));
+                    break;
+                case CMD_GET_LINK_LAYER_STATS:
+                    // Not supported hence reply with error message
+                    replyToMessage(message, message.what, null);
+                    break;
+                case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    break;
+                case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
+                    mTemporarilyDisconnectWifi = (message.arg1 == 1);
+                    replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
+                    break;
+                /* Link configuration (IP address, DNS, ...) changes notified via netlink */
+                case CMD_UPDATE_LINKPROPERTIES:
+                    updateLinkProperties((LinkProperties) message.obj);
+                    break;
+                case CMD_START_SUBSCRIPTION_PROVISIONING:
+                    replyToMessage(message, message.what, 0);
+                    break;
+                case CMD_IP_CONFIGURATION_SUCCESSFUL:
+                case CMD_IP_CONFIGURATION_LOST:
+                case CMD_IP_REACHABILITY_LOST:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
+                case CMD_START_IP_PACKET_OFFLOAD:
+                    /* fall-through */
+                case CMD_STOP_IP_PACKET_OFFLOAD:
+                case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF:
+                case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF:
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendSocketKeepaliveEvent(message.arg1,
+                                SocketKeepalive.ERROR_INVALID_NETWORK);
+                    }
+                    break;
+                case CMD_START_RSSI_MONITORING_OFFLOAD:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
+                case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
+                case CMD_QUERY_OSU_ICON:
+                    /* reply with arg1 = 0 - it returns API failure to the calling app
+                     * (message.what is not looked at)
+                     */
+                    replyToMessage(message, message.what);
+                    break;
+                case CMD_RESET_SIM_NETWORKS:
+                    /* Defer this message until supplicant is started. */
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
+                    deferMessage(message);
+                    break;
+                case CMD_INSTALL_PACKET_FILTER:
+                    mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj);
+                    break;
+                case CMD_READ_PACKET_FILTER:
+                    byte[] data = mWifiNative.readPacketFilter(mInterfaceName);
+                    if (mIpClient != null) {
+                        mIpClient.readPacketFilterComplete(data);
+                    }
+                    break;
+                case CMD_SET_FALLBACK_PACKET_FILTERING:
+                    if ((boolean) message.obj) {
+                        mWifiNative.startFilteringMulticastV4Packets(mInterfaceName);
+                    } else {
+                        mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName);
+                    }
+                    break;
+                case 0:
+                    // We want to notice any empty messages (with what == 0) that might crop up.
+                    // For example, we may have recycled a message sent to multiple handlers.
+                    Log.wtf(TAG, "Error! empty message encountered");
+                    break;
+                default:
+                    loge("Error! unhandled message" + message);
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+
+            return handleStatus;
+        }
+    }
+
+    /**
+     * Helper method to start other services and get state ready for client mode
+     */
+    private void setupClientMode() {
+        Log.d(TAG, "setupClientMode() ifacename = " + mInterfaceName);
+        setHighPerfModeEnabled(false);
+
+        mWifiStateTracker.updateState(WifiStateTracker.INVALID);
+        mIpClientCallbacks = new IpClientCallbacksImpl();
+        mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks);
+        if (!mIpClientCallbacks.awaitCreation()) {
+            loge("Timeout waiting for IpClient");
+        }
+
+        setMulticastFilter(true);
+        registerForWifiMonitorEvents();
+
+        // reset state related to supplicant starting
+        mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
+        // Initialize data structures
+        mLastBssid = null;
+        mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+        mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        mLastSimBasedConnectionCarrierName = null;
+        mLastSignalLevel = -1;
+        if (isConnectedMacRandomizationEnabled()) {
+            mWifiNative.setMacAddress(mInterfaceName, MacAddressUtils.createRandomUnicastAddress());
+        }
+        mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
+
+        mWifiNative.setExternalSim(mInterfaceName, true);
+
+
+        mMboOceController.enable();
+        mWifiDataStall.enablePhoneStateListener();
+
+        /**
+         * Enable bluetooth coexistence scan mode when bluetooth connection is active.
+         * When this mode is on, some of the low-level scan parameters used by the
+         * driver are changed to reduce interference with bluetooth
+         */
+        mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive);
+        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,null,null);
+        sendNetworkStateChangeBroadcast();
+        // Disable legacy multicast filtering, which on some chipsets defaults to enabled.
+        // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6
+        // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via
+        // IpClient.Callback.setFallbackMulticastFilter()
+        mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName);
+        mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName);
+
+        // Set the right suspend mode settings
+        mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0
+                && mContext.getResources().getBoolean(
+                        R.bool.config_wifiSuspendOptimizationsEnabled));
+
+        setPowerSave(true);
+
+        // Disable wpa_supplicant from auto reconnecting.
+        mWifiNative.enableStaAutoReconnect(mInterfaceName, false);
+        // STA has higher priority over P2P
+        mWifiNative.setConcurrencyPriority(true);
+
+        // Reset Connected band entries
+        mWifiNative.qtiUpdateConnectedBand(mIdentity, WifiNative.ConnectedBand.BAND_NONE);
+    }
+
+    /**
+     * Helper method to stop external services and clean up state from client mode.
+     */
+    private void stopClientMode() {
+        handleNetworkDisconnect();
+        // exiting supplicant started state is now only applicable to client mode
+        mMboOceController.disable();
+        mWifiDataStall.disablePhoneStateListener();
+        if (mIpClient != null && mIpClient.shutdown()) {
+            // Block to make sure IpClient has really shut down, lest cleanup
+            // race with, say, bringup code over in tethering.
+            mIpClientCallbacks.awaitShutdown();
+        }
+        mInterfaceName = null;
+        mWifiScoreReport.setInterfaceName(null);
+        // TODO: b/79504296 This broadcast has been deprecated and should be removed
+
+        mWifiConfigManager.clearUserTemporarilyDisabledList();
+        mWifiNative.qtiUpdateConnectedBand(mIdentity, WifiNative.ConnectedBand.BAND_NONE);
+    }
+
+    void registerConnected() {
+        if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
+            mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId);
+            // Notify PasspointManager of Passpoint network connected event.
+            WifiConfiguration currentNetwork = getCurrentWifiConfiguration();
+            if (currentNetwork != null && currentNetwork.isPasspoint()) {
+                mPasspointManager.onPasspointNetworkConnected(currentNetwork.getKey());
+            }
+        }
+    }
+
+    void registerDisconnected() {
+        if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
+            mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId);
+        }
+    }
+
+    /**
+     * Returns WifiConfiguration object corresponding to the currently connected network, null if
+     * not connected.
+     */
+    public WifiConfiguration getCurrentWifiConfiguration() {
+        if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
+            return null;
+        }
+        return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
+    }
+
+    private WifiConfiguration getTargetWifiConfiguration() {
+        if (mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
+            return null;
+        }
+        return mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
+    }
+
+    ScanResult getCurrentScanResult() {
+        WifiConfiguration config = getCurrentWifiConfiguration();
+        if (config == null) {
+            return null;
+        }
+        String bssid = mWifiInfo.getBSSID();
+        if (bssid == null) {
+            bssid = mTargetBssid;
+        }
+        ScanDetailCache scanDetailCache =
+                mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+
+        if (scanDetailCache == null) {
+            return null;
+        }
+
+        return scanDetailCache.getScanResult(bssid);
+    }
+
+    String getCurrentBSSID() {
+        return mLastBssid;
+    }
+
+    MacAddress getCurrentBssid() {
+        MacAddress bssid = null;
+        try {
+            bssid = (mLastBssid != null) ? MacAddress.fromString(mLastBssid) : null;
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Invalid BSSID format: " + mLastBssid);
+        }
+        return bssid;
+    }
+
+    void connectToNetwork(WifiConfiguration config) {
+        if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) {
+            mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime();
+            mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config);
+            mLastConnectAttemptTimestamp = mClock.getWallClockMillis();
+            mIsAutoRoaming = false;
+            if (getCurrentState() != mDisconnectedState) {
+                transitionTo(mDisconnectingState);
+            }
+        } else {
+            loge("CMD_START_CONNECT Failed to start connection to network " + config);
+            mTargetWifiConfiguration = null;
+            stopIpClient();
+            reportConnectionAttemptEnd(
+                    WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
+                    WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                    WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+        }
+    }
+
+    class ConnectModeState extends State {
+
+        @Override
+        public void enter() {
+            Log.d(TAG, "entering ConnectModeState: ifaceName = " + mInterfaceName);
+            mOperationalMode = ClientModeImpl.CONNECT_MODE;
+            setupClientMode();
+            if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
+                loge("Failed to remove networks on entering connect mode");
+            }
+            mWifiInfo.reset();
+            mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
+
+            // Inform QtiWifiConnectivityManager that Wifi is enabled
+            mQtiWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingEnabled);
+            mQtiWifiConnectivityManager.setWifiEnabled(true);
+            mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
+            mWifiHealthMonitor.setWifiEnabled(true);
+            mWifiDataStall.init();
+        }
+
+        @Override
+        public void exit() {
+            mOperationalMode = ClientModeImpl.DISABLED_MODE;
+
+            // Inform QtiWifiConnectivityManager that Wifi is disabled
+            mQtiWifiConnectivityManager.setWifiEnabled(false);
+
+            // Inform scorecard that wifi is being disabled
+            mWifiScoreCard.noteWifiDisabled(mWifiInfo);
+
+            if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
+                loge("Failed to remove networks on exiting connect mode");
+            }
+
+            // update connected band before WifiInfo reset.
+            updateConnectedBand(mWifiInfo.getFrequency(), false);
+
+            mWifiInfo.reset();
+            mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
+            mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
+            mWifiHealthMonitor.setWifiEnabled(false);
+            mWifiDataStall.reset();
+            stopClientMode();
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            WifiConfiguration config;
+            int netId;
+            boolean ok;
+            boolean didDisconnect;
+            String bssid;
+            String ssid;
+            NetworkUpdateResult result;
+            Set<Integer> removedNetworkIds;
+            int reasonCode;
+            boolean timedOut;
+            boolean handleStatus = HANDLED;
+            int callbackIdentifier = -1;
+            String device_capability;
+
+            int level2FailureReason =
+                    WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN;
+            switch (message.what) {
+                case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+                    stopIpClient();
+                    mDidBlockListBSSID = false;
+                    bssid = (String) message.obj;
+                    timedOut = message.arg1 > 0;
+                    reasonCode = message.arg2;
+                    Log.d(TAG, "Association Rejection event: bssid=" + bssid + " reason code="
+                            + reasonCode + " timedOut=" + Boolean.toString(timedOut));
+                    if (bssid == null || TextUtils.isEmpty(bssid)) {
+                        // If BSSID is null, use the target roam BSSID
+                        bssid = mTargetBssid;
+                    } else if (mTargetBssid == SUPPLICANT_BSSID_ANY) {
+                        // This is needed by BssidBlocklistMonitor to block continuously
+                        // failing BSSIDs. Need to set here because mTargetBssid is currently
+                        // not being set until association success.
+                        mTargetBssid = bssid;
+                    }
+                    mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId,
+                            WifiConfiguration.NetworkSelectionStatus
+                            .DISABLED_ASSOCIATION_REJECTION);
+                    mWifiConfigManager.setRecentFailureAssociationStatus(mTargetNetworkId,
+                            reasonCode);
+
+                    if (reasonCode == REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) {
+                        level2FailureReason = WifiMetricsProto.ConnectionEvent
+                                .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA;
+                    }
+                    // If rejection occurred while Metrics is tracking a ConnnectionEvent, end it.
+                    reportConnectionAttemptEnd(
+                            timedOut
+                                    ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT
+                                    : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
+                            WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                            level2FailureReason);
+                    break;
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                    stopIpClient();
+                    int disableReason = WifiConfiguration.NetworkSelectionStatus
+                            .DISABLED_AUTHENTICATION_FAILURE;
+                    reasonCode = message.arg1;
+                    WifiConfiguration targetedNetwork =
+                            mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
+                    // Check if this is a permanent wrong password failure.
+                    if (isPermanentWrongPasswordFailure(mTargetNetworkId, reasonCode)) {
+                        disableReason = WifiConfiguration.NetworkSelectionStatus
+                                .DISABLED_BY_WRONG_PASSWORD;
+                        if (targetedNetwork != null) {
+                            mWrongPasswordNotifier.onWrongPasswordError(
+                                    targetedNetwork.SSID);
+                        }
+                    } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) {
+                        int errorCode = message.arg2;
+                        handleEapAuthFailure(mTargetNetworkId, errorCode);
+                        if (errorCode == WifiNative.EAP_SIM_NOT_SUBSCRIBED) {
+                            disableReason = WifiConfiguration.NetworkSelectionStatus
+                                .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION;
+                        }
+                    }
+                    mWifiConfigManager.updateNetworkSelectionStatus(
+                            mTargetNetworkId, disableReason);
+                    mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId);
+
+                    //If failure occurred while Metrics is tracking a ConnnectionEvent, end it.
+                    switch (reasonCode) {
+                        case WifiManager.ERROR_AUTH_FAILURE_NONE:
+                            level2FailureReason =
+                                    WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE;
+                            break;
+                        case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT:
+                            level2FailureReason =
+                                    WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT;
+                            break;
+                        case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD:
+                            level2FailureReason =
+                                    WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD;
+                            break;
+                        case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE:
+                            level2FailureReason =
+                                    WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE;
+                            break;
+                        default:
+                            level2FailureReason =
+                                    WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN;
+                            break;
+                    }
+                    reportConnectionAttemptEnd(
+                            WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
+                            WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                            level2FailureReason);
+                    break;
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                    SupplicantState state = handleSupplicantStateChange(message);
+
+                    // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT
+                    // when authentication times out after a successful connection,
+                    // we can figure this from the supplicant state. If supplicant
+                    // state is DISCONNECTED, but the agent is not disconnected, we
+                    // need to handle a disconnection
+                    if (state == SupplicantState.DISCONNECTED && mNetworkAgent != null) {
+                        if (mVerboseLoggingEnabled) {
+                            log("Missed CTRL-EVENT-DISCONNECTED, disconnect");
+                        }
+                        handleNetworkDisconnect();
+                        transitionTo(mDisconnectedState);
+                    }
+
+                    if (state == SupplicantState.COMPLETED) {
+                        mWifiScoreReport.noteIpCheck();
+                    }
+                    break;
+                case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
+                    if (message.arg1 == 1) {
+                        mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+                                StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
+                        mWifiNative.disconnect(mInterfaceName);
+                        mTemporarilyDisconnectWifi = true;
+                    } else {
+                        mWifiNative.reconnect(mInterfaceName);
+                        mTemporarilyDisconnectWifi = false;
+                    }
+                    break;
+                case WifiMonitor.SUP_REQUEST_IDENTITY:
+                    netId = message.arg2;
+                    boolean identitySent = false;
+                    // For SIM & AKA/AKA' EAP method Only, get identity from ICC
+                    if (mTargetWifiConfiguration != null
+                            && mTargetWifiConfiguration.networkId == netId
+                            && mTargetWifiConfiguration.enterpriseConfig != null
+                            && mTargetWifiConfiguration.enterpriseConfig
+                                    .isAuthenticationSimBased()) {
+                        // Pair<identity, encrypted identity>
+                        Pair<String, String> identityPair = mWifiCarrierInfoManager
+                                .getSimIdentity(mTargetWifiConfiguration);
+                        if (identityPair != null && identityPair.first != null) {
+                            Log.i(TAG, "SUP_REQUEST_IDENTITY: identityPair=["
+                                    + ((identityPair.first.length() >= 7)
+                                    ? identityPair.first.substring(0, 7 /* Prefix+PLMN ID */)
+                                    + "****"
+                                    : identityPair.first) + ", "
+                                    + (!TextUtils.isEmpty(identityPair.second) ? identityPair.second
+                                    : "<NONE>") + "]");
+                            mWifiNative.simIdentityResponse(mInterfaceName, identityPair.first,
+                                    identityPair.second);
+                            identitySent = true;
+                        } else {
+                            Log.e(TAG, "Unable to retrieve identity from Telephony");
+                        }
+                    }
+
+                    if (!identitySent) {
+                        // Supplicant lacks credentials to connect to that network, hence black list
+                        ssid = (String) message.obj;
+                        if (mTargetWifiConfiguration != null && ssid != null
+                                && mTargetWifiConfiguration.SSID != null
+                                && mTargetWifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
+                            mWifiConfigManager.updateNetworkSelectionStatus(
+                                    mTargetWifiConfiguration.networkId,
+                                    WifiConfiguration.NetworkSelectionStatus
+                                            .DISABLED_AUTHENTICATION_NO_CREDENTIALS);
+                        }
+                        mWifiNative.disconnect(mInterfaceName);
+                    }
+                    break;
+                case WifiMonitor.SUP_REQUEST_SIM_AUTH:
+                    logd("Received SUP_REQUEST_SIM_AUTH");
+                    SimAuthRequestData requestData = (SimAuthRequestData) message.obj;
+                    if (requestData != null) {
+                        if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) {
+                            handleGsmAuthRequest(requestData);
+                        } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA
+                                || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) {
+                            handle3GAuthRequest(requestData);
+                        }
+                    } else {
+                        loge("Invalid SIM auth request");
+                    }
+                    break;
+                case CMD_START_SUBSCRIPTION_PROVISIONING:
+                    IProvisioningCallback callback = (IProvisioningCallback) message.obj;
+                    OsuProvider provider =
+                            (OsuProvider) message.getData().getParcelable(EXTRA_OSU_PROVIDER);
+                    int res = mPasspointManager.startSubscriptionProvisioning(
+                                    message.arg1, provider, callback) ? 1 : 0;
+                    replyToMessage(message, message.what, res);
+                    break;
+                case CMD_RECONNECT:
+                    WorkSource workSource = (WorkSource) message.obj;
+                    mQtiWifiConnectivityManager.forceConnectivityScan(workSource);
+                    break;
+                case CMD_START_ROAM:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    break;
+                case CMD_START_CONNECT:
+                    /* connect command coming from auto-join */
+                    netId = message.arg1;
+                    int uid = message.arg2;
+                    bssid = (String) message.obj;
+                    mSentHLPs = false;
+
+                    config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId);
+                    logd("CMD_START_CONNECT "
+                            + " my state " + getCurrentState().getName()
+                            + " nid=" + Integer.toString(netId)
+                            + " roam=" + Boolean.toString(mIsAutoRoaming));
+                    if (config == null) {
+                        loge("CMD_START_CONNECT and no config, bail out...");
+                        break;
+                    }
+
+                    if (!isConfigAllowedForInterface(config)) {
+                        loge("CMD_START_CONNECT on wrong interface, bail out...");
+                        break;
+                    }
+                    mTargetNetworkId = netId;
+                    // Update scorecard while there is still state from existing connection
+                    int scanRssi = mWifiConfigManager.findScanRssi(netId,
+                            mWifiHealthMonitor.getScanRssiValidTimeMs());
+                    mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID);
+                    mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID);
+
+                    updateWifiConfigOnStartConnection(config, bssid);
+                    reportConnectionAttemptStart(config, mTargetBssid,
+                            WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED);
+
+                    String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName);
+                    mWifiInfo.setMacAddress(currentMacAddress);
+                    Log.i(TAG, "Connecting with " + currentMacAddress + " as the mac address");
+                    connectToNetwork(config);
+                    break;
+                case CMD_CONNECT_NETWORK:
+                    callbackIdentifier = message.arg2;
+                    result = (NetworkUpdateResult) message.obj;
+		    netId = result.getNetworkId();
+                    if (!isConfigAllowedForInterface(mWifiConfigManager.getConfiguredNetwork(netId))) {
+                        loge("CONNECT_NETWORK Invalid config=" + result + " for this interface");
+                        mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
+                        replyToMessage(message,
+                                WifiManager.ERROR);
+                        break;
+                    }
+                    connectToUserSelectNetwork(
+                            netId, message.sendingUid, result.hasCredentialChanged());
+                    mWifiMetrics.logStaEvent(
+                            StaEvent.TYPE_CONNECT_NETWORK,
+                            mWifiConfigManager.getConfiguredNetwork(netId));
+                    sendActionListenerSuccess(callbackIdentifier);
+                    break;
+                case CMD_SAVE_NETWORK:
+                    callbackIdentifier = message.arg2;
+                    result = (NetworkUpdateResult) message.obj;
+                    netId = result.getNetworkId();
+                    if (mWifiInfo.getNetworkId() == netId) {
+                        if (result.hasCredentialChanged()) {
+                            // The network credentials changed and we're connected to this network,
+                            // start a new connection with the updated credentials.
+                            logi("CMD_SAVE_NETWORK credential changed for nid="
+                                    + netId + ". Reconnecting.");
+                            startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
+                        } else {
+                            if (result.hasProxyChanged()) {
+                                if (mIpClient != null) {
+                                    log("Reconfiguring proxy on connection");
+                                    WifiConfiguration currentConfig = getCurrentWifiConfiguration();
+                                    if (currentConfig != null) {
+                                        mIpClient.setHttpProxy(currentConfig.getHttpProxy());
+                                    } else {
+                                        Log.w(TAG,
+                                                "CMD_SAVE_NETWORK proxy change - but no current "
+                                                        + "Wi-Fi config");
+                                    }
+                                }
+                            }
+                            if (result.hasIpChanged()) {
+                                // The current connection configuration was changed
+                                // We switched from DHCP to static or from static to DHCP, or the
+                                // static IP address has changed.
+                                log("Reconfiguring IP on connection");
+                                mWifiNative.disconnect(mInterfaceName);
+                                transitionTo(mDisconnectingState);
+                                // reconnect to the same network
+                                if (mWifiNative.reconnect(mInterfaceName)) {
+                                    log("Reconnecting after IP reconfiguration");
+                                } else {
+                                    loge("Failed to reconnect after IP reconfiguration");
+                                    // we will transition to disconnected state by previous code
+                                }
+                            }
+                        }
+                    } else if (mWifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID
+                            && result.hasCredentialChanged()) {
+                        logi("CMD_SAVE_NETWORK credential changed for nid="
+                                + netId + " while disconnected. Connecting.");
+                        startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
+                    }
+                    sendActionListenerSuccess(callbackIdentifier);
+                    break;
+                case WifiMonitor.ASSOCIATED_BSSID_EVENT:
+                    // This is where we can confirm the connection BSSID. Use it to find the
+                    // right ScanDetail to populate metrics.
+                    String someBssid = (String) message.obj;
+                    if (someBssid != null) {
+                        // Get the ScanDetail associated with this BSSID.
+                        ScanDetailCache scanDetailCache =
+                                mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId);
+                        if (scanDetailCache != null) {
+                            mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail(
+                                    someBssid));
+                        }
+                        // Update last associated BSSID
+                        mLastBssid = someBssid;
+                    }
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                    if (mVerboseLoggingEnabled) log("Network connection established");
+                    mLastNetworkId = message.arg1;
+                    mWifiConfigManager.clearRecentFailureReason(mLastNetworkId);
+                    mLastBssid = (String) message.obj;
+                    reasonCode = message.arg2;
+
+                    config = getCurrentWifiConfiguration();
+                    if (config != null) {
+                        mWifiInfo.setBSSID(mLastBssid);
+                        mWifiInfo.setNetworkId(mLastNetworkId);
+                        mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
+
+                        ScanDetailCache scanDetailCache =
+                                mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+                        if (scanDetailCache != null && mLastBssid != null) {
+                            ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
+                            if (scanResult != null) {
+                                updateConnectedBand(scanResult.frequency, true);
+                            }
+                        }
+
+                        // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA'
+                        if (config.enterpriseConfig != null
+                                && config.enterpriseConfig.isAuthenticationSimBased()) {
+                            mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config);
+                            mLastSimBasedConnectionCarrierName =
+                                mWifiCarrierInfoManager.getCarrierNameforSubId(mLastSubId);
+                            String anonymousIdentity =
+                                    mWifiNative.getEapAnonymousIdentity(mInterfaceName);
+                            if (!TextUtils.isEmpty(anonymousIdentity)
+                                    && !WifiCarrierInfoManager
+                                    .isAnonymousAtRealmIdentity(anonymousIdentity)) {
+                                String decoratedPseudonym = mWifiCarrierInfoManager
+                                        .decoratePseudonymWith3GppRealm(config,
+                                                anonymousIdentity);
+                                if (decoratedPseudonym != null) {
+                                    anonymousIdentity = decoratedPseudonym;
+                                }
+                                if (mVerboseLoggingEnabled) {
+                                    log("EAP Pseudonym: " + anonymousIdentity);
+                                }
+                                // Save the pseudonym only if it is a real one
+                                config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
+                            } else {
+                                // Clear any stored pseudonyms
+                                config.enterpriseConfig.setAnonymousIdentity(null);
+                            }
+                            mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
+                        }
+                        mIpReachabilityMonitorActive = true;
+                        transitionTo(mObtainingIpState);
+                        sendNetworkStateChangeBroadcast();
+                    } else {
+                        logw("Connected to unknown networkId " + mLastNetworkId
+                                + ", disconnecting...");
+                        sendMessage(CMD_DISCONNECT);
+                    }
+                    break;
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                    if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost ");
+                    mLastNetworkId = message.arg1;
+                    mWifiConfigManager.clearRecentFailureReason(mLastNetworkId);
+                    mLastBssid = (String) message.obj;
+                    handleNetworkDisconnect();
+                    transitionTo(mDisconnectedState);
+                    break;
+                case CMD_QUERY_OSU_ICON:
+                    mPasspointManager.queryPasspointIcon(
+                            ((Bundle) message.obj).getLong(EXTRA_OSU_ICON_QUERY_BSSID),
+                            ((Bundle) message.obj).getString(EXTRA_OSU_ICON_QUERY_FILENAME));
+                    break;
+                case WifiMonitor.TARGET_BSSID_EVENT:
+                    // Trying to associate to this BSSID
+                    if (message.obj != null) {
+                        mTargetBssid = (String) message.obj;
+                    }
+                    break;
+                case CMD_GET_LINK_LAYER_STATS:
+                    WifiLinkLayerStats stats = getWifiLinkLayerStats();
+                    replyToMessage(message, message.what, stats);
+                    break;
+                case CMD_RESET_SIM_NETWORKS:
+                    log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed");
+                    int resetReason = message.arg1;
+                    if (resetReason == RESET_SIM_REASON_SIM_INSERTED) {
+                        // whenever a SIM is inserted clear all SIM related notifications
+                        mSimRequiredNotifier.dismissSimRequiredNotification();
+                    } else {
+                        mWifiConfigManager.resetSimNetworks();
+                    }
+                    if (resetReason != RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED) {
+                        mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps();
+                    }
+                    break;
+                case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
+                    // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE
+                    // message. So we need to rely on STATE_CHANGE message to detect on->off
+                    // transition and update mBluetoothConnectionActive status correctly.
+                    mBluetoothConnectionActive = mBluetoothConnectionActive
+                            && message.arg1 != BluetoothAdapter.STATE_OFF;
+                    mWifiNative.setBluetoothCoexistenceScanMode(
+                            mInterfaceName, mBluetoothConnectionActive);
+                    mQtiWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive);
+                    break;
+                case CMD_BLUETOOTH_ADAPTER_CONNECTION_STATE_CHANGE:
+                    // Transition to a non-disconnected state does correctly
+                    // indicate BT is connected or being connected.
+                    mBluetoothConnectionActive =
+                            message.arg1 != BluetoothAdapter.STATE_DISCONNECTED;
+                    mWifiNative.setBluetoothCoexistenceScanMode(
+                            mInterfaceName, mBluetoothConnectionActive);
+                    mQtiWifiConnectivityManager.setBluetoothConnected(mBluetoothConnectionActive);
+                    break;
+                case CMD_SET_SUSPEND_OPT_ENABLED:
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);
+                        if (message.arg2 == 1) {
+                            mSuspendWakeLock.release();
+                        }
+                    } else {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);
+                    }
+                    break;
+                case CMD_SET_HIGH_PERF_MODE:
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false);
+                    } else {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);
+                    }
+                    break;
+                case WifiMonitor.ANQP_DONE_EVENT:
+                    // TODO(zqiu): remove this when switch over to wificond for ANQP requests.
+                    mPasspointManager.notifyANQPDone((AnqpEvent) message.obj);
+                    break;
+                case CMD_STOP_IP_PACKET_OFFLOAD: {
+                    int slot = message.arg1;
+                    int ret = stopWifiIPPacketOffload(slot);
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendSocketKeepaliveEvent(slot, ret);
+                    }
+                    break;
+                }
+                case WifiMonitor.RX_HS20_ANQP_ICON_EVENT:
+                    // TODO(zqiu): remove this when switch over to wificond for icon requests.
+                    mPasspointManager.notifyIconDone((IconEvent) message.obj);
+                    break;
+                case WifiMonitor.HS20_REMEDIATION_EVENT:
+                    // TODO(zqiu): remove this when switch over to wificond for WNM frames
+                    // monitoring.
+                    mPasspointManager.receivedWnmFrame((WnmData) message.obj);
+                    break;
+                case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE:
+                    handleBssTransitionRequest((BtmFrameData) message.obj);
+                    break;
+                case CMD_CONFIG_ND_OFFLOAD:
+                    final boolean enabled = (message.arg1 > 0);
+                    mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled);
+                    break;
+                case CMD_PRE_DHCP_ACTION:
+                case CMD_PRE_DHCP_ACTION_COMPLETE:
+                case CMD_POST_DHCP_ACTION:
+                case CMD_IPV4_PROVISIONING_SUCCESS:
+                case CMD_IP_CONFIGURATION_SUCCESSFUL:
+                case CMD_IPV4_PROVISIONING_FAILURE:
+                    handleStatus = handleL3MessagesWhenNotConnected(message);
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+
+            return handleStatus;
+        }
+    }
+
+    private boolean handleL3MessagesWhenNotConnected(Message message) {
+        boolean handleStatus = HANDLED;
+
+        if (!mIpClientWithPreConnection) {
+            return NOT_HANDLED;
+        }
+
+        switch (message.what) {
+            case CMD_PRE_DHCP_ACTION:
+                handlePreDhcpSetup();
+                break;
+            case CMD_PRE_DHCP_ACTION_COMPLETE:
+                if (mIpClient != null) {
+                    mIpClient.completedPreDhcpAction();
+                }
+                break;
+            case CMD_IPV4_PROVISIONING_FAILURE:
+                stopDhcpSetup();
+                deferMessage(message);
+                break;
+            case CMD_POST_DHCP_ACTION:
+            case CMD_IPV4_PROVISIONING_SUCCESS:
+            case CMD_IP_CONFIGURATION_SUCCESSFUL:
+                deferMessage(message);
+                break;
+            default:
+                return NOT_HANDLED;
+        }
+
+        return handleStatus;
+    }
+
+    private WifiNetworkAgentSpecifier createNetworkAgentSpecifier(
+            @NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid) {
+        currentWifiConfiguration.BSSID = currentBssid;
+        WifiNetworkAgentSpecifier wns =
+                new WifiNetworkAgentSpecifier(currentWifiConfiguration);
+        return wns;
+    }
+
+    private NetworkCapabilities getCapabilities(WifiConfiguration currentWifiConfiguration) {
+        final NetworkCapabilities.Builder builder =
+                new NetworkCapabilities.Builder(mNetworkCapabilitiesFilter);
+        // MatchAllNetworkSpecifier set in the mNetworkCapabilitiesFilter should never be set in the
+        // agent's specifier.
+        builder.setNetworkSpecifier(null);
+        if (currentWifiConfiguration == null) {
+            return builder.build();
+        }
+
+        if (mWifiInfo.isTrusted()) {
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+        } else {
+            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+        }
+
+        builder.setOwnerUid(currentWifiConfiguration.creatorUid);
+        builder.setAdministratorUids(new int[] {currentWifiConfiguration.creatorUid});
+
+        if (!WifiConfiguration.isMetered(currentWifiConfiguration, mWifiInfo)) {
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        } else {
+            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        }
+
+        if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) {
+            builder.setSignalStrength(mWifiInfo.getRssi());
+        } else {
+            builder.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED);
+        }
+
+        if (currentWifiConfiguration.osu) {
+            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        }
+
+        if (!mWifiInfo.getSSID().equals(WifiManager.UNKNOWN_SSID)) {
+            builder.setSsid(mWifiInfo.getSSID());
+        }
+        // Fill up the uid/packageName for this connection.
+        builder.setRequestorUid(Process.INVALID_UID);
+        builder.setRequestorPackageName("");
+        // Fill up the network agent specifier for this connection.
+        builder.setNetworkSpecifier(createNetworkAgentSpecifier(
+                currentWifiConfiguration, getCurrentBSSID()));
+        updateLinkBandwidth(builder);
+        return builder.build();
+    }
+
+    private void updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder) {
+        int rssiDbm = mWifiInfo.getRssi();
+        int txTputKbps = INVALID_THROUGHPUT;
+        int rxTputKbps = INVALID_THROUGHPUT;
+        // If RSSI is available, check if throughput is available
+        if (rssiDbm != WifiInfo.INVALID_RSSI && mWifiDataStall != null) {
+            txTputKbps = mWifiDataStall.getTxThroughputKbps();
+            rxTputKbps = mWifiDataStall.getRxThroughputKbps();
+        }
+        if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps != INVALID_THROUGHPUT) {
+            txTputKbps = rxTputKbps;
+        } else if (rxTputKbps == INVALID_THROUGHPUT && txTputKbps != INVALID_THROUGHPUT) {
+            rxTputKbps = txTputKbps;
+        } else if (txTputKbps == INVALID_THROUGHPUT && rxTputKbps == INVALID_THROUGHPUT) {
+            int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps();
+            int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps();
+            if (maxTxLinkSpeedMbps > 0) {
+                txTputKbps = maxTxLinkSpeedMbps * 1000;
+            }
+            if (maxRxLinkSpeedMbps > 0) {
+                rxTputKbps = maxRxLinkSpeedMbps * 1000;
+            }
+        }
+        if (mVerboseLoggingEnabled) {
+            logd("tx tput in kbps: " + txTputKbps);
+            logd("rx tput in kbps: " + rxTputKbps);
+        }
+        if (txTputKbps > 0) {
+            networkCapabilitiesBuilder.setLinkUpstreamBandwidthKbps(txTputKbps);
+        }
+        if (rxTputKbps > 0) {
+            networkCapabilitiesBuilder.setLinkDownstreamBandwidthKbps(rxTputKbps);
+        }
+    }
+
+    /**
+     * Method to update network capabilities from the current WifiConfiguration.
+     */
+    public void updateCapabilities() {
+        updateCapabilities(getCurrentWifiConfiguration());
+    }
+
+    private void updateCapabilities(WifiConfiguration currentWifiConfiguration) {
+        updateCapabilities(getCapabilities(currentWifiConfiguration));
+    }
+
+    private void updateCapabilities(NetworkCapabilities networkCapabilities) {
+        if (mNetworkAgent == null) {
+            return;
+        }
+        mNetworkAgent.sendNetworkCapabilities(networkCapabilities);
+    }
+
+    private void handleEapAuthFailure(int networkId, int errorCode) {
+        WifiConfiguration targetedNetwork =
+                mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
+        if (targetedNetwork != null) {
+            switch (targetedNetwork.enterpriseConfig.getEapMethod()) {
+                case WifiEnterpriseConfig.Eap.SIM:
+                case WifiEnterpriseConfig.Eap.AKA:
+                case WifiEnterpriseConfig.Eap.AKA_PRIME:
+                    if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) {
+                        mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork);
+                    }
+                    break;
+                default:
+                    // Do Nothing
+            }
+        }
+    }
+
+    private class WifiNetworkAgent extends NetworkAgent {
+        WifiNetworkAgent(Context c, Looper l, String tag, NetworkCapabilities nc, LinkProperties lp,
+                int score, NetworkAgentConfig config) {
+            super(c, l, tag, nc, lp, score, config, null);
+            register();
+        }
+        private int mLastNetworkStatus = -1; // To detect when the status really changes
+
+        @Override
+        public void onNetworkUnwanted() {
+            // Ignore if we're not the current networkAgent.
+            if (this != mNetworkAgent) return;
+            if (mVerboseLoggingEnabled) {
+                logd("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString(
+                        mWifiInfo.getScore()));
+            }
+            unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT);
+        }
+
+        @Override
+        public void onValidationStatus(int status, @Nullable Uri redirectUri) {
+            if (this != mNetworkAgent) return;
+            if (status == mLastNetworkStatus) return;
+            mLastNetworkStatus = status;
+            if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID) {
+                if (mVerboseLoggingEnabled) {
+                    logd("WifiNetworkAgent -> Wifi networkStatus invalid, score="
+                            + Integer.toString(mWifiInfo.getScore()));
+                }
+                unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED);
+            } else if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
+                if (mVerboseLoggingEnabled) {
+                    logd("WifiNetworkAgent -> Wifi networkStatus valid, score= "
+                            + Integer.toString(mWifiInfo.getScore()));
+                }
+                mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK);
+                doNetworkStatus(status);
+            }
+        }
+
+        @Override
+        public void onSaveAcceptUnvalidated(boolean accept) {
+            if (this != mNetworkAgent) return;
+            QtiClientModeImpl.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0);
+        }
+
+        @Override
+        public void onStartSocketKeepalive(int slot, @NonNull Duration interval,
+                @NonNull KeepalivePacketData packet) {
+            if (this != mNetworkAgent) return;
+            QtiClientModeImpl.this.sendMessage(
+                    CMD_START_IP_PACKET_OFFLOAD, slot, (int) interval.getSeconds(), packet);
+        }
+
+        @Override
+        public void onStopSocketKeepalive(int slot) {
+            if (this != mNetworkAgent) return;
+            QtiClientModeImpl.this.sendMessage(CMD_STOP_IP_PACKET_OFFLOAD, slot);
+        }
+
+        @Override
+        public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) {
+            if (this != mNetworkAgent) return;
+            QtiClientModeImpl.this.sendMessage(
+                    CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0, packet);
+        }
+
+        @Override
+        public void onRemoveKeepalivePacketFilter(int slot) {
+            if (this != mNetworkAgent) return;
+            QtiClientModeImpl.this.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot);
+        }
+
+        @Override
+        public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
+            if (this != mNetworkAgent) return;
+            // 0. If there are no thresholds, or if the thresholds are invalid,
+            //    stop RSSI monitoring.
+            // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and
+            //    MAX_VALUE at the start/end of the thresholds array if necessary.
+            // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware
+            //    event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then
+            //    re-arm the hardware event. This needs to be done on the state machine thread to
+            //    avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one
+            //    sent in the NetworkCapabilities) must be the one received from the hardware event
+            //    received, or we might skip callbacks.
+            // 3. Ensure that when we disconnect, RSSI monitoring is stopped.
+            logd("Received signal strength thresholds: " + Arrays.toString(thresholds));
+            if (thresholds.length == 0) {
+                QtiClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD,
+                        mWifiInfo.getRssi());
+                return;
+            }
+            int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2);
+            rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE;
+            rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE;
+            Arrays.sort(rssiVals);
+            byte[] rssiRange = new byte[rssiVals.length];
+            for (int i = 0; i < rssiVals.length; i++) {
+                int val = rssiVals[i];
+                if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) {
+                    rssiRange[i] = (byte) val;
+                } else {
+                    Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: "
+                            + Arrays.toString(rssiVals));
+                    QtiClientModeImpl.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD,
+                            mWifiInfo.getRssi());
+                    return;
+                }
+            }
+            // TODO: Do we quash rssi values in this sorted array which are very close?
+            mRssiRanges = rssiRange;
+            QtiClientModeImpl.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD,
+                    mWifiInfo.getRssi());
+        }
+
+        @Override
+        public void onAutomaticReconnectDisabled() {
+            if (this != mNetworkAgent) return;
+            unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
+        }
+    }
+
+    void unwantedNetwork(int reason) {
+        sendMessage(CMD_UNWANTED_NETWORK, reason);
+    }
+
+    void doNetworkStatus(int status) {
+        sendMessage(CMD_NETWORK_STATUS, status);
+    }
+
+    class L2ConnectedState extends State {
+        class RssiEventHandler implements WifiNative.WifiRssiEventHandler {
+            @Override
+            public void onRssiThresholdBreached(byte curRssi) {
+                if (mVerboseLoggingEnabled) {
+                    Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi);
+                }
+                sendMessage(CMD_RSSI_THRESHOLD_BREACHED, curRssi);
+            }
+        }
+
+        RssiEventHandler mRssiEventHandler = new RssiEventHandler();
+
+        @Override
+        public void enter() {
+            mRssiPollToken++;
+            if (mEnableRssiPolling) {
+                mLinkProbeManager.resetOnNewConnection();
+                sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
+            }
+
+            // If this network was explicitly selected by the user, evaluate whether to inform
+            // ConnectivityService of that fact so the system can treat it appropriately.
+            final WifiConfiguration config = getCurrentWifiConfiguration();
+
+            boolean explicitlySelected = false;
+            if (shouldEvaluateWhetherToSendExplicitlySelected(config)) {
+                // If explicitlySelected is true, the network was selected by the user via Settings
+                // or QuickSettings. If this network has Internet access, switch to it. Otherwise,
+                // switch to it only if the user confirms that they really want to switch, or has
+                // already confirmed and selected "Don't ask again".
+                explicitlySelected =
+                        mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid);
+                if (mVerboseLoggingEnabled) {
+                    log("Network selected by UID " + config.lastConnectUid + " explicitlySelected="
+                            + explicitlySelected);
+                }
+            }
+
+            if (mVerboseLoggingEnabled) {
+                log("explicitlySelected=" + explicitlySelected + " acceptUnvalidated="
+                        + config.noInternetAccessExpected);
+            }
+
+            final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder()
+                    .setLegacyType(ConnectivityManager.TYPE_WIFI)
+                    .setLegacyTypeName(NETWORKTYPE)
+                    .setExplicitlySelected(explicitlySelected)
+                    .setUnvalidatedConnectivityAcceptable(
+                            explicitlySelected && config.noInternetAccessExpected)
+                    .setPartialConnectivityAcceptable(config.noInternetAccessExpected)
+                    .build();
+            final NetworkCapabilities nc = getCapabilities(getCurrentWifiConfiguration());
+            synchronized (mNetworkAgentLock) {
+                // This should never happen.
+                if (mNetworkAgent != null) {
+                    Log.wtf(TAG, "mNetworkAgent is not null: " + mNetworkAgent);
+                    mNetworkAgent.unregister();
+                    mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,null,null);
+                    sendNetworkStateChangeBroadcast();
+                }
+                mNetworkAgent = new WifiNetworkAgent(mContext, getHandler().getLooper(),
+                        "WifiNetworkAgent", nc, mLinkProperties, 60, naConfig);
+            }
+            mNetworkInfo.setDetailedState(DetailedState.CONNECTING,null,null);
+            sendNetworkStateChangeBroadcast();
+            mWifiScoreReport.setNetworkAgent(mNetworkAgent);
+
+            // We must clear the config BSSID, as the wifi chipset may decide to roam
+            // from this point on and having the BSSID specified in the network block would
+            // cause the roam to faile and the device to disconnect
+            clearTargetBssid("L2ConnectedState");
+            mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo,
+                    mNetworkAgent.getNetwork().getNetId());
+            mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID());
+        }
+
+        @Override
+        public void exit() {
+            if (mIpClient != null) {
+            }
+
+            // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState
+            // Bug: 15347363
+            // For paranoia's sake, call handleNetworkDisconnect
+            // only if BSSID is null or last networkId
+            // is not invalid.
+            if (mVerboseLoggingEnabled) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId));
+                if (mLastBssid != null) {
+                    sb.append(" ").append(mLastBssid);
+                }
+            }
+            mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            boolean handleStatus = HANDLED;
+            int callbackIdentifier = -1;
+
+            switch (message.what) {
+                case CMD_PRE_DHCP_ACTION:
+                    handlePreDhcpSetup();
+                    break;
+                case CMD_PRE_DHCP_ACTION_COMPLETE:
+                    if (mIpClient != null) {
+                        mIpClient.completedPreDhcpAction();
+                    }
+                    break;
+                case CMD_POST_DHCP_ACTION:
+                    handlePostDhcpSetup();
+                    break;
+                case CMD_IPV4_PROVISIONING_SUCCESS: {
+                    handleIPv4Success((DhcpResultsParcelable) message.obj);
+                    sendNetworkStateChangeBroadcast();
+                    break;
+                }
+                case CMD_IPV4_PROVISIONING_FAILURE: {
+                    handleIPv4Failure();
+                    break;
+                }
+                case CMD_IP_CONFIGURATION_SUCCESSFUL:
+                    if (getCurrentWifiConfiguration() == null) {
+                        // The current config may have been removed while we were connecting,
+                        // trigger a disconnect to clear up state.
+                        reportConnectionAttemptEnd(
+                                WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
+                                WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                                WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+                        mWifiNative.disconnect(mInterfaceName);
+                        transitionTo(mDisconnectingState);
+                    } else {
+                        handleSuccessfulIpConfiguration();
+                        sendConnectedState();
+                        transitionTo(mConnectedState);
+                    }
+                    break;
+                case CMD_IP_CONFIGURATION_LOST:
+                    // Get Link layer stats so that we get fresh tx packet counters.
+                    getWifiLinkLayerStats();
+                    handleIpConfigurationLost();
+                    reportConnectionAttemptEnd(
+                            WifiMetrics.ConnectionEvent.FAILURE_DHCP,
+                            WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                            WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+                    transitionTo(mDisconnectingState);
+                    break;
+                case CMD_IP_REACHABILITY_LOST:
+                    if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj);
+                    if (mIpReachabilityDisconnectEnabled) {
+                        if (mDisconnectOnlyOnInitialIpReachability && !mIpReachabilityMonitorActive) {
+                            logd("CMD_IP_REACHABILITY_LOST Connect session is over, skip ip reachability lost indication.");
+                            break;
+                        }
+                        handleIpReachabilityLost();
+                        transitionTo(mDisconnectingState);
+                    } else {
+                        logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore");
+                    }
+                    break;
+                case CMD_DISCONNECT:
+                    mWifiNative.disconnect(mInterfaceName);
+                    transitionTo(mDisconnectingState);
+                    break;
+                case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
+                    if (message.arg1 == 1) {
+                        mWifiNative.disconnect(mInterfaceName);
+                        mTemporarilyDisconnectWifi = true;
+                        transitionTo(mDisconnectingState);
+                    }
+                    break;
+                case WifiMonitor.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;
+                        sendNetworkStateChangeBroadcast();
+                    }
+                    mIpReachabilityMonitorActive = true;
+                    sendMessageDelayed(obtainMessage(CMD_IP_REACHABILITY_SESSION_END, 0, 0), 10000);
+                    break;
+                case CMD_ONESHOT_RSSI_POLL:
+                    if (!mEnableRssiPolling) {
+                        updateLinkLayerStatsRssiAndScoreReportInternal();
+                    }
+                    break;
+                case CMD_RSSI_POLL:
+                    if (message.arg1 == mRssiPollToken) {
+                        WifiLinkLayerStats stats = updateLinkLayerStatsRssiAndScoreReportInternal();
+                        if (mWifiScoreReport.shouldCheckIpLayer()) {
+                            if (mIpClient != null) {
+                                mIpClient.confirmConfiguration();
+                            }
+                            mWifiScoreReport.noteIpCheck();
+                        }
+                        mLastLinkLayerStats = stats;
+                        mWifiScoreCard.noteSignalPoll(mWifiInfo);
+                        mLinkProbeManager.updateConnectionStats(
+                                mWifiInfo, mInterfaceName);
+                        sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
+                                getPollRssiIntervalMsecs());
+                        if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi());
+                        // TODO: UT: Check how to use interface name for traffic poller notificaiton.
+                        mWifiTrafficPoller.notifyOnDataActivity(mWifiInfo.txSuccess,
+                                mWifiInfo.rxSuccess);
+                    } else {
+                        // Polling has completed
+                    }
+                    break;
+                case CMD_ENABLE_RSSI_POLL:
+                    cleanWifiScore();
+                    mEnableRssiPolling = (message.arg1 == 1);
+                    mRssiPollToken++;
+                    if (mEnableRssiPolling) {
+                        // First poll
+                        mLastSignalLevel = -1;
+                        mLinkProbeManager.resetOnScreenTurnedOn();
+                        fetchRssiLinkSpeedAndFrequencyNative();
+                        sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
+                                getPollRssiIntervalMsecs());
+                    }
+                    break;
+                case WifiMonitor.ASSOCIATED_BSSID_EVENT:
+                    if ((String) message.obj == null) {
+                        logw("Associated command w/o BSSID");
+                        break;
+                    }
+                    mLastBssid = (String) message.obj;
+                    if (mLastBssid != null && (mWifiInfo.getBSSID() == null
+                            || !mLastBssid.equals(mWifiInfo.getBSSID()))) {
+                        mWifiInfo.setBSSID(mLastBssid);
+                        WifiConfiguration config = getCurrentWifiConfiguration();
+                        if (config != null) {
+                            ScanDetailCache scanDetailCache = mWifiConfigManager
+                                    .getScanDetailCacheForNetwork(config.networkId);
+                            if (scanDetailCache != null) {
+                                ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
+                                if (scanResult != null) {
+                                    updateConnectedBand(scanResult.frequency, true);
+                                }
+                            }
+                        }
+                    }
+                    break;
+                case CMD_START_RSSI_MONITORING_OFFLOAD:
+                case CMD_RSSI_THRESHOLD_BREACHED:
+                    byte currRssi = (byte) message.arg1;
+                    processRssiThreshold(currRssi, message.what, mRssiEventHandler);
+                    break;
+                case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+                    stopRssiMonitoringOffload();
+                    break;
+                case CMD_RECONNECT:
+                    log(" Ignore CMD_RECONNECT request because wifi is already connected");
+                    break;
+                case CMD_RESET_SIM_NETWORKS:
+                    if (message.arg1 != RESET_SIM_REASON_SIM_INSERTED
+                            && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
+                        WifiConfiguration config =
+                                mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
+                        if ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED
+                                && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)
+                                || (config.enterpriseConfig != null
+                                        && config.enterpriseConfig.isAuthenticationSimBased()
+                                        && !mWifiCarrierInfoManager.isSimPresent(mLastSubId))) {
+                            // remove local PMKSA cache in framework
+                            mWifiNative.removeNetworkCachedData(mLastNetworkId);
+                            // remove network so that supplicant's PMKSA cache is cleared
+                            mWifiNative.removeAllNetworks(mInterfaceName);
+                            mSimRequiredNotifier.showSimRequiredNotification(
+                                    config, mLastSimBasedConnectionCarrierName);
+                            transitionTo(mDisconnectingState);
+                        }
+                    }
+                    /* allow parent state to reset data for other networks */
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case CMD_START_IP_PACKET_OFFLOAD: {
+                    int slot = message.arg1;
+                    int intervalSeconds = message.arg2;
+                    KeepalivePacketData pkt = (KeepalivePacketData) message.obj;
+                    int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendSocketKeepaliveEvent(slot, result);
+                    }
+                    break;
+                }
+                case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: {
+                    if (mIpClient != null) {
+                        final int slot = message.arg1;
+                        if (message.obj instanceof NattKeepalivePacketData) {
+                            final NattKeepalivePacketData pkt =
+                                    (NattKeepalivePacketData) message.obj;
+                            mIpClient.addKeepalivePacketFilter(slot, pkt);
+                        } else if (message.obj instanceof TcpKeepalivePacketData) {
+                            final TcpKeepalivePacketData pkt =
+                                    (TcpKeepalivePacketData) message.obj;
+                            mIpClient.addKeepalivePacketFilter(slot, pkt);
+                        }
+                    }
+                    break;
+                }
+                case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: {
+                    if (mIpClient != null) {
+                        mIpClient.removeKeepalivePacketFilter(message.arg1);
+                    }
+                    break;
+                }
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+
+            return handleStatus;
+        }
+
+        /**
+         * Fetches link stats and updates Wifi Score Report.
+         */
+        private WifiLinkLayerStats updateLinkLayerStatsRssiAndScoreReportInternal() {
+            WifiLinkLayerStats stats = getWifiLinkLayerStats();
+            // Get Info and continue polling
+            fetchRssiLinkSpeedAndFrequencyNative();
+            // Send the update score to network agent.
+            mWifiScoreReport.calculateAndReportScore();
+            return stats;
+        }
+    }
+
+    /**
+     * Fetches link stats and updates Wifi Score Report.
+     */
+    public void updateLinkLayerStatsRssiAndScoreReport() {
+        sendMessage(CMD_ONESHOT_RSSI_POLL);
+    }
+
+    private static int convertToUsabilityStatsTriggerType(int unusableEventTriggerType) {
+        int triggerType;
+        switch (unusableEventTriggerType) {
+            case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
+                triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX;
+                break;
+            case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
+                triggerType = WifiUsabilityStats.TYPE_DATA_STALL_TX_WITHOUT_RX;
+                break;
+            case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
+                triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BOTH;
+                break;
+            case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
+                triggerType = WifiUsabilityStats.TYPE_FIRMWARE_ALERT;
+                break;
+            case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
+                triggerType = WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST;
+                break;
+            default:
+                triggerType = WifiUsabilityStats.TYPE_UNKNOWN;
+                Log.e(TAG, "Unknown WifiIsUnusableEvent: " + unusableEventTriggerType);
+        }
+        return triggerType;
+    }
+
+    class ObtainingIpState extends State {
+        @Override
+        public void enter() {
+            // Reset power save mode after association.
+            // Kernel does not forward power save request to driver if power
+            // save state of that interface is same as requested state in
+            // cfg80211. This happens when driver’s power save state not
+            // synchronized with cfg80211 power save state.
+            // By resetting power save state resolves issues of cfg80211
+            // ignoring enable power save request sent in ObtainingIpState.
+            mWifiNative.setPowerSave(mInterfaceName, false);
+            mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR,null,null);
+            sendNetworkStateChangeBroadcast();
+            WifiConfiguration currentConfig = getCurrentWifiConfiguration();
+            if (mIpClientWithPreConnection && mIpClient != null) {
+                mIpClient.notifyPreconnectionComplete(mSentHLPs);
+                mIpClientWithPreConnection = false;
+                mSentHLPs = false;
+            } else {
+                startIpClient(currentConfig, false);
+            }
+
+            // Get Link layer stats so as we get fresh tx packet counters
+            getWifiLinkLayerStats();
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            boolean handleStatus = HANDLED;
+
+            switch(message.what) {
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                    reportConnectionAttemptEnd(
+                            WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
+                            WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                            WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+                    mWifiInjector.getWifiLastResortWatchdog()
+                            .noteConnectionFailureAndTriggerIfNeeded(
+                                    getTargetSsid(),
+                                    (message.obj == null)
+                                    ? mTargetBssid : (String) message.obj,
+                                    WifiLastResortWatchdog.FAILURE_CODE_DHCP);
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case CMD_SET_HIGH_PERF_MODE:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
+                    deferMessage(message);
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+            return handleStatus;
+        }
+    }
+
+    /**
+     * Helper function to check if we need to invoke
+     * {@link NetworkAgent#explicitlySelected(boolean, boolean)} to indicate that we connected to a
+     * network which the user just chose
+     * (i.e less than {@link #LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS) before).
+     */
+    @VisibleForTesting
+    public boolean shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration currentConfig) {
+        if (currentConfig == null) {
+            Log.wtf(TAG, "Current WifiConfiguration is null, but IP provisioning just succeeded");
+            return false;
+        }
+        long currentTimeMillis = mClock.getElapsedSinceBootMillis();
+        return (mWifiConfigManager.getLastSelectedNetwork() == currentConfig.networkId
+                && currentTimeMillis - mWifiConfigManager.getLastSelectedTimeStamp()
+                < LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS);
+    }
+
+    private void sendConnectedState() {
+        mNetworkAgent.markConnected();
+        sendNetworkStateChangeBroadcast();
+    }
+
+    class RoamingState extends State {
+        boolean mAssociated;
+        @Override
+        public void enter() {
+            if (mVerboseLoggingEnabled) {
+                log("RoamingState Enter mScreenOn=" + mScreenOn);
+            }
+
+            // Make sure we disconnect if roaming fails
+            mRoamWatchdogCount++;
+            logd("Start Roam Watchdog " + mRoamWatchdogCount);
+            sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER,
+                    mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC);
+            mAssociated = false;
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            WifiConfiguration config;
+            boolean handleStatus = HANDLED;
+
+            switch (message.what) {
+                case CMD_UNWANTED_NETWORK:
+                    if (mVerboseLoggingEnabled) {
+                        log("Roaming and CS doesn't want the network -> ignore");
+                    }
+                    break;
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                    /**
+                     * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT
+                     * before NETWORK_DISCONNECTION_EVENT
+                     * And there is an associated BSSID corresponding to our target BSSID, then
+                     * we have missed the network disconnection, transition to mDisconnectedState
+                     * and handle the rest of the events there.
+                     */
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    if (stateChangeResult.state == SupplicantState.DISCONNECTED
+                            || stateChangeResult.state == SupplicantState.INACTIVE
+                            || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) {
+                        if (mVerboseLoggingEnabled) {
+                            log("STATE_CHANGE_EVENT in roaming state "
+                                    + stateChangeResult.toString());
+                        }
+                        if (stateChangeResult.BSSID != null
+                                && stateChangeResult.BSSID.equals(mTargetBssid)) {
+                            handleNetworkDisconnect();
+                            transitionTo(mDisconnectedState);
+                        }
+                    }
+                    if (stateChangeResult.state == SupplicantState.ASSOCIATED) {
+                        // We completed the layer2 roaming part
+                        mAssociated = true;
+                        if (stateChangeResult.BSSID != null) {
+                            mTargetBssid = stateChangeResult.BSSID;
+                        }
+                    }
+                    break;
+                case CMD_ROAM_WATCHDOG_TIMER:
+                    if (mRoamWatchdogCount == message.arg1) {
+                        if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect");
+                        mRoamFailCount++;
+                        handleNetworkDisconnect();
+                        mWifiNative.disconnect(mInterfaceName);
+                        transitionTo(mDisconnectedState);
+                    }
+                    break;
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                    if (mAssociated) {
+                        if (mVerboseLoggingEnabled) {
+                            log("roaming and Network connection established");
+                        }
+                        mLastNetworkId = message.arg1;
+                        mLastBssid = (String) message.obj;
+                        mWifiInfo.setBSSID(mLastBssid);
+                        mWifiInfo.setNetworkId(mLastNetworkId);
+
+                        sendNetworkStateChangeBroadcast();
+                        // Successful framework roam! (probably)
+                        mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid,
+                                mWifiInfo.getSSID());
+                        reportConnectionAttemptEnd(
+                                WifiMetrics.ConnectionEvent.FAILURE_NONE,
+                                WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                                WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+
+                        // We must clear the config BSSID, as the wifi chipset may decide to roam
+                        // from this point on and having the BSSID specified by QNS would cause
+                        // the roam to fail and the device to disconnect.
+                        // When transition from RoamingState to DisconnectingState or
+                        // DisconnectedState, the config BSSID is cleared by
+                        // handleNetworkDisconnect().
+                        clearTargetBssid("RoamingCompleted");
+
+                        // We used to transition to ObtainingIpState in an
+                        // attempt to do DHCPv4 RENEWs on framework roams.
+                        // DHCP can take too long to time out, and we now rely
+                        // upon IpClient's use of IpReachabilityMonitor to
+                        // confirm our current network configuration.
+                        //
+                        // mIpClient.confirmConfiguration() is called within
+                        // the handling of SupplicantState.COMPLETED.
+                        mIpReachabilityMonitorActive = true;
+                        transitionTo(mConnectedState);
+                    } else {
+                        mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+                    }
+                    break;
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                    // Throw away but only if it corresponds to the network we're roaming to
+                    String bssid = (String) message.obj;
+                    if (true) {
+                        String target = "";
+                        if (mTargetBssid != null) target = mTargetBssid;
+                        log("NETWORK_DISCONNECTION_EVENT in roaming state"
+                                + " BSSID=" + bssid
+                                + " target=" + target);
+                    }
+                    clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2);
+                    if (bssid != null && bssid.equals(mTargetBssid)) {
+                        handleNetworkDisconnect();
+                        transitionTo(mDisconnectedState);
+                    }
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+            return handleStatus;
+        }
+
+        @Override
+        public void exit() {
+            logd("QtiClientModeImpl: Leaving Roaming state");
+        }
+    }
+
+    class ConnectedState extends State {
+        @Override
+        public void enter() {
+            if (mVerboseLoggingEnabled) {
+                log("Enter ConnectedState  mScreenOn=" + mScreenOn);
+            }
+            mNetworkInfo.setDetailedState(DetailedState.CONNECTED,null,null);
+            sendNetworkStateChangeBroadcast();
+            reportConnectionAttemptEnd(
+                    WifiMetrics.ConnectionEvent.FAILURE_NONE,
+                    WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                    WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+
+            if (mIpReachabilityMonitorActive)
+                sendMessageDelayed(obtainMessage(CMD_IP_REACHABILITY_SESSION_END, 0, 0), 10000);
+
+            registerConnected();
+            mLastConnectAttemptTimestamp = 0;
+            mTargetWifiConfiguration = null;
+            mWifiScoreReport.reset();
+            mLastSignalLevel = -1;
+
+            // Not roaming anymore
+            mIsAutoRoaming = false;
+
+            mLastDriverRoamAttempt = 0;
+            mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+            mWifiStateTracker.updateState(WifiStateTracker.CONNECTED);
+            mWifiScoreReport.startConnectedNetworkScorer(mNetworkAgent.getNetwork().getNetId());
+            updateLinkLayerStatsRssiAndScoreReport();
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            WifiConfiguration config = null;
+            boolean handleStatus = HANDLED;
+
+            switch (message.what) {
+                case CMD_UNWANTED_NETWORK:
+                    if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) {
+                        mWifiNative.disconnect(mInterfaceName);
+                        transitionTo(mDisconnectingState);
+                    } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
+                            || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) {
+                        Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
+                                ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN"
+                                : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED"));
+                        config = getCurrentWifiConfiguration();
+                        if (config != null) {
+                            // Disable autojoin
+                            if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) {
+                                mWifiConfigManager.setNetworkValidatedInternetAccess(
+                                        config.networkId, false);
+                                mWifiConfigManager.updateNetworkSelectionStatus(config.networkId,
+                                        DISABLED_NO_INTERNET_PERMANENT);
+                            } else {
+                                mWifiConfigManager.incrementNetworkNoInternetAccessReports(
+                                        config.networkId);
+                                // If this was not the last selected network, update network
+                                // selection status to temporarily disable the network.
+                                if (mWifiConfigManager.getLastSelectedNetwork() != config.networkId
+                                        && !config.noInternetAccessExpected) {
+                                    Log.i(TAG, "Temporarily disabling network because of"
+                                            + "no-internet access");
+                                    mWifiConfigManager.updateNetworkSelectionStatus(
+                                            config.networkId,
+                                            DISABLED_NO_INTERNET_TEMPORARY);
+                                }
+                                int rssi = mWifiInfo.getRssi();
+                                mBssidBlocklistMonitor.handleBssidConnectionFailure(
+                                        mLastBssid, config.SSID,
+                                        BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE,
+                                        rssi);
+                                mWifiScoreCard.noteValidationFailure(mWifiInfo);
+                            }
+                        }
+                    }
+                    break;
+                case CMD_NETWORK_STATUS:
+                    if (message.arg1 == NetworkAgent.VALIDATION_STATUS_VALID) {
+                        mWifiScoreCard.noteValidationSuccess(mWifiInfo);
+                        mBssidBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid,
+                                mWifiInfo.getSSID());
+                        config = getCurrentWifiConfiguration();
+                        if (config != null) {
+                            // re-enable autojoin
+                            mWifiConfigManager.updateNetworkSelectionStatus(
+                                    config.networkId,
+                                    WifiConfiguration.NetworkSelectionStatus
+                                            .DISABLED_NONE);
+                            mWifiConfigManager.setNetworkValidatedInternetAccess(
+                                    config.networkId, true);
+                        }
+                    }
+                    break;
+                case CMD_ACCEPT_UNVALIDATED:
+                    boolean accept = (message.arg1 != 0);
+                    mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept);
+                    break;
+                case WifiMonitor.ASSOCIATED_BSSID_EVENT:
+                    // ASSOCIATING to a new BSSID while already connected, indicates
+                    // that driver is roaming
+                    mLastDriverRoamAttempt = mClock.getWallClockMillis();
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                    long lastRoam = 0;
+                    reportConnectionAttemptEnd(
+                            WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
+                            WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                            WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+                    if (mLastDriverRoamAttempt != 0) {
+                        // Calculate time since last driver roam attempt
+                        lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt;
+                        mLastDriverRoamAttempt = 0;
+                    }
+
+                    boolean localGen = message.arg1 == 1;
+                    if (!localGen) { // ignore disconnects initiated by wpa_supplicant.
+                        mWifiScoreCard.noteNonlocalDisconnect(message.arg2);
+                        int rssi = mWifiInfo.getRssi();
+                        mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
+                                mWifiInfo.getSSID(),
+                                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, rssi);
+                    }
+                    config = getCurrentWifiConfiguration();
+
+                    if (mVerboseLoggingEnabled) {
+                        log("NETWORK_DISCONNECTION_EVENT in connected state"
+                                + " BSSID=" + mWifiInfo.getBSSID()
+                                + " RSSI=" + mWifiInfo.getRssi()
+                                + " freq=" + mWifiInfo.getFrequency()
+                                + " reason=" + message.arg2
+                                + " Network Selection Status=" + (config == null ? "Unavailable"
+                                    : config.getNetworkSelectionStatus().getNetworkStatusString()));
+                    }
+                    break;
+                case CMD_START_ROAM:
+                    // Clear the driver roam indication since we are attempting a framework roam
+                    mLastDriverRoamAttempt = 0;
+
+                    /* Connect command coming from auto-join */
+                    int netId = message.arg1;
+                    ScanResult candidate = (ScanResult) message.obj;
+                    String bssid = SUPPLICANT_BSSID_ANY;
+                    if (candidate != null) {
+                        bssid = candidate.BSSID;
+                    }
+                    config = mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId);
+                    if (config == null) {
+                        loge("CMD_START_ROAM and no config, bail out...");
+                        break;
+                    }
+                    int scanRssi = mWifiConfigManager.findScanRssi(netId,
+                            mWifiHealthMonitor.getScanRssiValidTimeMs());
+                    mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID);
+                    setTargetBssid(config, bssid);
+                    mTargetNetworkId = netId;
+
+                    logd("CMD_START_ROAM sup state "
+                            + " my state " + getCurrentState().getName()
+                            + " nid=" + Integer.toString(netId)
+                            + " config " + config.getKey()
+                            + " targetRoamBSSID " + mTargetBssid);
+
+                    reportConnectionAttemptStart(config, mTargetBssid,
+                            WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
+                    if (mWifiNative.roamToNetwork(mInterfaceName, config)) {
+                        mLastConnectAttemptTimestamp = mClock.getWallClockMillis();
+                        mTargetWifiConfiguration = config;
+                        mIsAutoRoaming = true;
+                        transitionTo(mRoamingState);
+                    } else {
+                        loge("CMD_START_ROAM Failed to start roaming to network " + config);
+                        reportConnectionAttemptEnd(
+                                WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
+                                WifiMetricsProto.ConnectionEvent.HLF_NONE,
+                                WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+                        mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
+                        break;
+                    }
+                    break;
+                case CMD_IP_CONFIGURATION_LOST:
+                    mWifiMetrics.incrementIpRenewalFailure();
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case CMD_START_IP_PACKET_OFFLOAD: {
+                    int slot = message.arg1;
+                    int intervalSeconds = message.arg2;
+                    KeepalivePacketData pkt = (KeepalivePacketData) message.obj;
+                    int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendSocketKeepaliveEvent(slot, result);
+                    }
+                    break;
+                }
+                case CMD_IP_REACHABILITY_SESSION_END:
+                    mIpReachabilityMonitorActive = false;
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+
+            return handleStatus;
+        }
+
+        @Override
+        public void exit() {
+            logd("QtiClientModeImpl: Leaving Connected state");
+
+            mLastDriverRoamAttempt = 0;
+        }
+    }
+
+    class DisconnectingState extends State {
+
+        @Override
+        public void enter() {
+
+            if (mVerboseLoggingEnabled) {
+                logd(" Enter DisconnectingState State screenOn=" + mScreenOn);
+            }
+            sendNetworkStateChangeBroadcast();
+
+            // Make sure we disconnect: we enter this state prior to connecting to a new
+            // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE
+            // event which in this case will be indicating that supplicant started to associate.
+            // In some cases supplicant doesn't ignore the connect requests (it might not
+            // find the target SSID in its cache),
+            // Therefore we end up stuck that state, hence the need for the watchdog.
+            mDisconnectingWatchdogCount++;
+            logd("Start Disconnecting Watchdog " + mDisconnectingWatchdogCount);
+            sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER,
+                    mDisconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            boolean handleStatus = HANDLED;
+
+            switch (message.what) {
+                case CMD_CONNECT_NETWORK:
+                case CMD_SAVE_NETWORK:
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
+                    deferMessage(message);
+                    break;
+                case CMD_DISCONNECT:
+                    if (mVerboseLoggingEnabled) {
+                        log("Ignore CMD_DISCONNECT when already disconnecting.");
+                    }
+                    break;
+                case WifiMonitor.NETWORK_CONNECTION_EVENT:
+                    if (mVerboseLoggingEnabled) {
+                        log("Ignore NETWORK_CONNECTION_EVENT when already disconnecting.");
+                    }
+                    break;
+                case CMD_DISCONNECTING_WATCHDOG_TIMER:
+                    if (mDisconnectingWatchdogCount == message.arg1) {
+                        if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect");
+                        handleNetworkDisconnect();
+                        transitionTo(mDisconnectedState);
+                    }
+                    break;
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                    /**
+                     * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT
+                     * we have missed the network disconnection, transition to mDisconnectedState
+                     * and handle the rest of the events there
+                     */
+                    mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
+                    deferMessage(message);
+                    handleNetworkDisconnect();
+                    transitionTo(mDisconnectedState);
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+            return handleStatus;
+        }
+    }
+
+    class DisconnectedState extends State {
+        @Override
+        public void enter() {
+            Log.i(TAG, "disconnectedstate enter");
+            // We don't scan frequently if this is a temporary disconnect
+            // due to p2p
+            if (mTemporarilyDisconnectWifi) {
+                p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
+                return;
+            }
+            mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+            sendNetworkStateChangeBroadcast();
+            if (mVerboseLoggingEnabled) {
+                logd(" Enter DisconnectedState screenOn=" + mScreenOn);
+            }
+
+            /** clear the roaming state, if we were roaming, we failed */
+            mIsAutoRoaming = false;
+            mIpReachabilityMonitorActive = false;
+            removeMessages(CMD_IP_REACHABILITY_SESSION_END);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            boolean handleStatus = HANDLED;
+
+            switch (message.what) {
+                case CMD_DISCONNECT:
+                    mWifiNative.disconnect(mInterfaceName);
+                    break;
+                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+                    stopIpClient();
+                    if (message.arg2 == 15 /* FOURWAY_HANDSHAKE_TIMEOUT */) {
+                        String bssid = (message.obj == null)
+                                ? mTargetBssid : (String) message.obj;
+                    }
+                    clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2);
+                    break;
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    if (mVerboseLoggingEnabled) {
+                        logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state
+                                + " -> state= "
+                                + WifiInfo.getDetailedStateOf(stateChangeResult.state));
+                    }
+                    if (SupplicantState.isConnecting(stateChangeResult.state)) {
+                        WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(
+                                stateChangeResult.networkId);
+
+                        // Update Passpoint information before setNetworkDetailedState as
+                        // WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI.
+                        mWifiInfo.setFQDN(null);
+                        mWifiInfo.setPasspointUniqueId(null);
+                        mWifiInfo.setOsuAp(false);
+                        mWifiInfo.setProviderFriendlyName(null);
+                        if (config != null && (config.isPasspoint() || config.osu)) {
+                            if (config.isPasspoint()) {
+                                mWifiInfo.setFQDN(config.FQDN);
+                                mWifiInfo.setPasspointUniqueId(config.getPasspointUniqueId());
+                            } else {
+                                mWifiInfo.setOsuAp(true);
+                            }
+                            mWifiInfo.setProviderFriendlyName(config.providerFriendlyName);
+                        }
+                    }
+                    /* ConnectModeState does the rest of the handling */
+                    handleStatus = NOT_HANDLED;
+                    break;
+                case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    break;
+                case CMD_RECONNECT:
+                    if (mTemporarilyDisconnectWifi) {
+                        // Drop a third party reconnect/reassociate if STA is
+                        // temporarily disconnected for p2p
+                        break;
+                    } else {
+                        // ConnectModeState handles it
+                        handleStatus = NOT_HANDLED;
+                    }
+                    break;
+                case CMD_SCREEN_STATE_CHANGED:
+                    handleScreenStateChanged(message.arg1 != 0);
+                    break;
+                default:
+                    handleStatus = NOT_HANDLED;
+                    break;
+            }
+
+            if (handleStatus == HANDLED) {
+                logStateAndMessage(message, this);
+            }
+            return handleStatus;
+        }
+    }
+
+    /**
+     * State machine initiated requests can have replyTo set to null, indicating
+     * there are no recipients, we ignore those reply actions.
+     */
+    private void replyToMessage(Message msg, int what) {
+        if (msg.replyTo == null) return;
+        Message dstMsg = obtainMessageWithWhatAndArg2(msg, what);
+        mReplyChannel.replyToMessage(msg, dstMsg);
+    }
+
+    private void replyToMessage(Message msg, int what, int arg1) {
+        if (msg.replyTo == null) return;
+        Message dstMsg = obtainMessageWithWhatAndArg2(msg, what);
+        dstMsg.arg1 = arg1;
+        mReplyChannel.replyToMessage(msg, dstMsg);
+    }
+
+    private void replyToMessage(Message msg, int what, Object obj) {
+        if (msg.replyTo == null) return;
+        Message dstMsg = obtainMessageWithWhatAndArg2(msg, what);
+        dstMsg.obj = obj;
+        mReplyChannel.replyToMessage(msg, dstMsg);
+    }
+
+    /**
+     * arg2 on the source message has a unique id that needs to be retained in replies
+     * to match the request
+     * <p>see WifiManager for details
+     */
+    private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) {
+        Message msg = Message.obtain();
+        msg.what = what;
+        msg.arg2 = srcMsg.arg2;
+        return msg;
+    }
+
+    void handleGsmAuthRequest(SimAuthRequestData requestData) {
+        if (mTargetWifiConfiguration != null
+                && mTargetWifiConfiguration.networkId
+                == requestData.networkId) {
+            logd("id matches targetWifiConfiguration");
+        } else {
+            logd("id does not match targetWifiConfiguration");
+            return;
+        }
+
+        /*
+         * Try authentication in the following order.
+         *
+         *    Standard       Cellular_auth     Type Command
+         *
+         * 1. 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN]
+         *                            [Length][RES][Length][CK][Length][IK] and more
+         * 2. 3GPP TS 31.102 2G_authentication [Length][RAND]
+         *                            [Length][SRES][Length][Cipher Key Kc]
+         * 3. 3GPP TS 11.11  2G_authentication [RAND]
+         *                            [SRES][Cipher Key Kc]
+         */
+        String response = mWifiCarrierInfoManager
+                .getGsmSimAuthResponse(requestData.data, mTargetWifiConfiguration);
+        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);
+            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);
+            }
+        }
+        if (response == null || response.length() == 0) {
+            mWifiNative.simAuthFailedResponse(mInterfaceName);
+        } else {
+            logv("Supplicant Response -" + response);
+            mWifiNative.simAuthResponse(
+                    mInterfaceName, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response);
+        }
+    }
+
+    void handle3GAuthRequest(SimAuthRequestData requestData) {
+        if (mTargetWifiConfiguration != null
+                && mTargetWifiConfiguration.networkId
+                == requestData.networkId) {
+            logd("id matches targetWifiConfiguration");
+        } else {
+            logd("id does not match targetWifiConfiguration");
+            return;
+        }
+
+        SimAuthResponseData response = mWifiCarrierInfoManager
+                .get3GAuthResponse(requestData, mTargetWifiConfiguration);
+        if (response != null) {
+            mWifiNative.simAuthResponse(
+                    mInterfaceName, response.type, response.response);
+        } else {
+            mWifiNative.umtsAuthFailedResponse(mInterfaceName);
+        }
+    }
+
+    /**
+     * Automatically connect to the network specified
+     *
+     * @param networkId ID of the network to connect to
+     * @param uid UID of the app triggering the connection.
+     * @param bssid BSSID of the network
+     */
+    public void startConnectToNetwork(int networkId, int uid, String bssid) {
+        sendMessage(CMD_START_CONNECT, networkId, uid, bssid);
+    }
+
+    /**
+     * Automatically roam to the network specified
+     *
+     * @param networkId ID of the network to roam to
+     * @param scanResult scan result which identifies the network to roam to
+     */
+    public void startRoamToNetwork(int networkId, ScanResult scanResult) {
+        sendMessage(CMD_START_ROAM, networkId, 0, scanResult);
+    }
+
+    private boolean isConfigAllowedForInterface(WifiConfiguration config) {
+        if (config == null)
+            return false;
+
+        if (config.staId != mIdentity)
+            return false;
+
+        return true;
+    }
+
+    /**
+     * @param reason reason code from supplicant on network disconnected event
+     * @return true if this is a suspicious disconnect
+     */
+
+    private static String getLinkPropertiesSummary(LinkProperties lp) {
+        List<String> attributes = new ArrayList<>(6);
+        if (lp.hasIpv4Address()) {
+            attributes.add("v4");
+        }
+        if (lp.hasIpv4DefaultRoute()) {
+            attributes.add("v4r");
+        }
+        if (lp.hasIpv4DnsServer()) {
+            attributes.add("v4dns");
+        }
+        if (lp.hasGlobalIpv6Address()) {
+            attributes.add("v6");
+        }
+        if (lp.hasIpv6DefaultRoute()) {
+            attributes.add("v6r");
+        }
+        if (lp.hasIpv6DnsServer()) {
+            attributes.add("v6dns");
+        }
+
+        return TextUtils.join(" ", attributes);
+    }
+
+    /**
+     * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId'
+     * This should match the network config framework is attempting to connect to.
+     */
+    private String getTargetSsid() {
+        WifiConfiguration currentConfig = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
+        if (currentConfig != null) {
+            return currentConfig.SSID;
+        }
+        return null;
+    }
+
+    /**
+     * Send message to WifiP2pServiceImpl.
+     * @return true if message is sent.
+     *         false if there is no channel configured for WifiP2pServiceImpl.
+     */
+    private boolean p2pSendMessage(int what) {
+        if (mWifiP2pChannel != null) {
+            mWifiP2pChannel.sendMessage(what);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Send message to WifiP2pServiceImpl with an additional param |arg1|.
+     * @return true if message is sent.
+     *         false if there is no channel configured for WifiP2pServiceImpl.
+     */
+    private boolean p2pSendMessage(int what, int arg1) {
+        if (mWifiP2pChannel != null) {
+            mWifiP2pChannel.sendMessage(what, arg1);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether CMD_IP_REACHABILITY_LOST events should trigger disconnects.
+     */
+    public boolean getIpReachabilityDisconnectEnabled() {
+        return mIpReachabilityDisconnectEnabled;
+    }
+
+    /**
+     * Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects.
+     */
+    public void setIpReachabilityDisconnectEnabled(boolean enabled) {
+        mIpReachabilityDisconnectEnabled = enabled;
+    }
+
+    public String getInterfaceName() {
+        return mInterfaceName;
+    }
+
+    private void sendActionListenerFailure(int callbackIdentifier, int reason) {
+        IActionListener actionListener;
+        synchronized (mProcessingActionListeners) {
+            actionListener = mProcessingActionListeners.remove(callbackIdentifier);
+        }
+        if (actionListener != null) {
+            try {
+                actionListener.onFailure(reason);
+            } catch (RemoteException e) {
+                // no-op (client may be dead, nothing to be done)
+            }
+        }
+    }
+
+    private void sendActionListenerSuccess(int callbackIdentifier) {
+        IActionListener actionListener;
+        synchronized (mProcessingActionListeners) {
+            actionListener = mProcessingActionListeners.remove(callbackIdentifier);
+        }
+        if (actionListener != null) {
+            try {
+                actionListener.onSuccess();
+            } catch (RemoteException e) {
+                // no-op (client may be dead, nothing to be done)
+            }
+        }
+    }
+
+    /**
+     * Trigger network connection and provide status via the provided callback.
+     */
+    public void connect(WifiConfiguration config, int netId, @Nullable IBinder binder,
+            @Nullable IActionListener callback, int callbackIdentifier, int callingUid) {
+        mWifiInjector.getWifiThreadRunner().post(() -> {
+            if (callback != null && binder != null) {
+                mProcessingActionListeners.add(binder, callback, callbackIdentifier);
+            }
+            /**
+             * The connect message can contain a network id passed as arg1 on message or
+             * or a config passed as obj on message.
+             * For a new network, a config is passed to create and connect.
+             * For an existing network, a network id is passed
+             */
+            NetworkUpdateResult result = null;
+            if (config != null) {
+                result = mWifiConfigManager.addOrUpdateNetwork(config, callingUid);
+                if (!result.isSuccess()) {
+                    loge("connectNetwork adding/updating config=" + config + " failed");
+                    sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+                    return;
+                }
+            } else {
+                if (mWifiConfigManager.getConfiguredNetwork(netId) == null) {
+                    loge("connectNetwork Invalid network Id=" + netId);
+                    sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+                    return;
+                }
+                result = new NetworkUpdateResult(netId);
+            }
+            final int networkId = result.getNetworkId();
+            mWifiConfigManager.userEnabledNetwork(networkId);
+            if (!mWifiConfigManager.enableNetwork(networkId, true, callingUid, null)
+                    || !mWifiConfigManager.updateLastConnectUid(networkId, callingUid)) {
+                logi("connect Allowing uid " + callingUid
+                        + " with insufficient permissions to connect=" + networkId);
+            } else if (mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) {
+                // Note user connect choice here, so that it will be considered in the
+                // next network selection.
+                mQtiWifiConnectivityManager.setUserConnectChoice(networkId);
+            }
+            Message message =
+                    obtainMessage(CMD_CONNECT_NETWORK, -1, callbackIdentifier, result);
+            message.sendingUid = callingUid;
+            sendMessage(message);
+        });
+    }
+
+    /**
+     * Trigger network save and provide status via the provided callback.
+     */
+    public void save(WifiConfiguration config, @Nullable IBinder binder,
+            @Nullable IActionListener callback, int callbackIdentifier, int callingUid) {
+        mWifiInjector.getWifiThreadRunner().post(() -> {
+            if (callback != null && binder != null) {
+                mProcessingActionListeners.add(binder, callback, callbackIdentifier);
+            }
+            if (config == null) {
+                loge("saveNetwork with null configuration my state "
+                        + getCurrentState().getName());
+                sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+                return;
+            }
+            NetworkUpdateResult result =
+                    mWifiConfigManager.addOrUpdateNetwork(config, callingUid);
+            if (!result.isSuccess()) {
+                loge("saveNetwork adding/updating config=" + config + " failed");
+                sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+                return;
+            }
+            if (!mWifiConfigManager.enableNetwork(
+                    result.getNetworkId(), false, callingUid, null)) {
+                loge("saveNetwork enabling config=" + config + " failed");
+                sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+                return;
+            }
+            Message message =
+                    obtainMessage(CMD_SAVE_NETWORK, -1 , callbackIdentifier, result);
+            message.sendingUid = callingUid;
+            sendMessage(message);
+        });
+    }
+
+    /**
+     * Trigger network forget and provide status via the provided callback.
+     */
+    public void forget(int netId, @Nullable IBinder binder, @Nullable IActionListener callback,
+            int callbackIdentifier, int callingUid) {
+        mWifiInjector.getWifiThreadRunner().post(() -> {
+            if (callback != null && binder != null) {
+                mProcessingActionListeners.add(binder, callback, callbackIdentifier);
+            }
+            boolean success = mWifiConfigManager.removeNetwork(netId, callingUid, null);
+            if (!success) {
+                loge("Failed to remove network");
+                sendActionListenerFailure(callbackIdentifier, WifiManager.ERROR);
+            }
+            sendActionListenerSuccess(callbackIdentifier);
+        });
+    }
+
+    /**
+     * Handle BSS transition request from Connected BSS.
+     *
+     * @param frameData Data retrieved from received BTM request frame.
+     */
+    private void handleBssTransitionRequest(BtmFrameData frameData) {
+        if (frameData == null) {
+            return;
+        }
+
+        String bssid = mWifiInfo.getBSSID();
+        String ssid = mWifiInfo.getSSID();
+        if ((bssid == null) || (ssid == null) || WifiManager.UNKNOWN_SSID.equals(ssid)) {
+            Log.e(TAG, "Failed to handle BSS transition: bssid: " + bssid + " ssid: " + ssid);
+            return;
+        }
+
+        if ((frameData.mBssTmDataFlagsMask
+                & MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED)
+                != 0) {
+            mWifiMetrics.incrementMboCellularSwitchRequestCount();
+        }
+
+
+        if ((frameData.mBssTmDataFlagsMask
+                & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED)
+                != 0) {
+            long duration = frameData.mBlockListDurationMs;
+            mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
+            if (duration == 0) {
+                /*
+                 * When 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_BLOCKLIST_DURATION_MS;
+            }
+            // Blocklist the current BSS
+            mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, duration,
+                    BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0);
+        }
+
+        if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) {
+            // Trigger the network selection and re-connect to new network if available.
+            mWifiMetrics.incrementForceScanCountDueToSteeringRequest();
+            mQtiWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
+        }
+    }
+    /**
+     * Update the wifi configuration before sending connect to
+     * supplicant/driver.
+     *
+     * @param config wifi configuration object.
+     * @param bssid BSSID to assocaite with.
+     */
+    void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) {
+        boolean canUpgradePskToSae = false;
+        boolean isFrameworkWpa3SaeUpgradePossible = false;
+        boolean isLegacyWpa2ApInScanResult = false;
+
+        setTargetBssid(config, bssid);
+
+        if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get(
+                WifiConfiguration.KeyMgmt.WPA_PSK)) {
+            isFrameworkWpa3SaeUpgradePossible = true;
+        }
+
+        if (isFrameworkWpa3SaeUpgradePossible && isWpa3SaeUpgradeOffloadEnabled()) {
+            // Driver offload of upgrading legacy WPA/WPA2 connection to WPA3
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Driver upgrade legacy WPA/WPA2 connection to WPA3");
+            }
+            config.allowedAuthAlgorithms.clear();
+            // Note: KeyMgmt.WPA2_PSK is already enabled, enable SAE as well
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+            isFrameworkWpa3SaeUpgradePossible = false;
+        }
+        // Check if network selection selected a good WPA3 candidate AP for a WPA2
+        // saved network.
+        ScanResult scanResultCandidate = config.getNetworkSelectionStatus().getCandidate();
+        if (isFrameworkWpa3SaeUpgradePossible && scanResultCandidate != null) {
+            ScanResultMatchInfo scanResultMatchInfo = ScanResultMatchInfo
+                    .fromScanResult(scanResultCandidate);
+            if ((scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_SAE)) {
+                canUpgradePskToSae = true;
+            } else {
+                // No SAE candidate
+                isFrameworkWpa3SaeUpgradePossible = false;
+            }
+        }
+
+        /**
+         *  Go through the matching scan results and update wifi config.
+         */
+        ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config);
+        ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy();
+        List<ScanResult> scanResults = scanRequestProxy.getScanResults();
+        for (ScanResult scanResult : scanResults) {
+            if (!config.SSID.equals(ScanResultUtil.createQuotedSSID(scanResult.SSID))) {
+                continue;
+            }
+            if (isFrameworkWpa3SaeUpgradePossible && !isLegacyWpa2ApInScanResult) {
+                if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
+                        && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
+                    // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to
+                    // allow seamless roaming within the ESS.
+                    if (mVerboseLoggingEnabled) {
+                        Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3");
+                    }
+                    isLegacyWpa2ApInScanResult = true;
+                    canUpgradePskToSae = false;
+                }
+                if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)
+                        && scanResultCandidate == null) {
+                    // When the user manually selected a network from the Wi-Fi picker, evaluate
+                    // if to upgrade based on the scan results. The most typical use case during
+                    // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In
+                    // this case, we would like to upgrade the connection.
+                    canUpgradePskToSae = true;
+                }
+            }
+
+            ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult);
+            if (!key1.equals(key2)) {
+                continue;
+            }
+        }
+
+        if (isFrameworkWpa3SaeUpgradePossible && canUpgradePskToSae
+                && !(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
+                            || config.allowedKeyManagement.get(
+                            WifiConfiguration.KeyMgmt.FILS_SHA384))) {
+            // Upgrade legacy WPA/WPA2 connection to WPA3
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Upgrade legacy WPA/WPA2 connection to WPA3");
+            }
+            config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+        }
+
+        if (isConnectedMacRandomizationEnabled()) {
+            if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+                configureRandomizedMacAddress(config);
+            } else {
+                setCurrentMacToFactoryMac(config);
+            }
+        }
+
+        if (config.enterpriseConfig != null
+                && config.enterpriseConfig.isAuthenticationSimBased()
+                && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(
+                mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))
+                && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) {
+            String anonAtRealm = mWifiCarrierInfoManager
+                    .getAnonymousIdentityWith3GppRealm(config);
+            // Use anonymous@<realm> when pseudonym is not available
+            config.enterpriseConfig.setAnonymousIdentity(anonAtRealm);
+        }
+    }
+
+    private void setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config) {
+        mIpClient.setHttpProxy(config.getHttpProxy());
+        if (!TextUtils.isEmpty(mContext.getResources().getString(
+                R.string.config_wifi_tcp_buffers))) {
+            mIpClient.setTcpBufferSizes(mContext.getResources().getString(
+                    R.string.config_wifi_tcp_buffers));
+        }
+    }
+
+    private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) {
+        if (mIpClient == null) {
+            return false;
+        }
+
+        final boolean isUsingStaticIp =
+                (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
+        if (mVerboseLoggingEnabled) {
+            final String key = config.getKey();
+            log("startIpClient netId=" + Integer.toString(mLastNetworkId)
+                    + " " + key + " "
+                    + " roam=" + mIsAutoRoaming
+                    + " static=" + isUsingStaticIp
+                    + " isFilsConnection=" + isFilsConnection);
+        }
+
+        final MacAddress currentBssid = getCurrentBssid();
+        final String l2Key = mLastL2KeyAndGroupHint != null
+                ? mLastL2KeyAndGroupHint.first : null;
+        final String groupHint = mLastL2KeyAndGroupHint != null
+                ? mLastL2KeyAndGroupHint.second : null;
+        final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint,
+                currentBssid);
+        clearTargetBssid("ObtainingIpAddress");
+        stopDhcpSetup();
+        setConfigurationsPriorToIpClientProvisioning(config);
+        ScanDetailCache scanDetailCache =
+                mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+        ScanResult scanResult = null;
+        if (mLastBssid != null) {
+            if (scanDetailCache != null) {
+                scanResult = scanDetailCache.getScanResult(mLastBssid);
+            }
+            if (scanResult == null) {
+                ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy();
+                List<ScanResult> scanResults = scanRequestProxy.getScanResults();
+                for (ScanResult result : scanResults) {
+                    if (result.SSID.equals(WifiInfo.removeDoubleQuotes(config.SSID))
+                            && result.BSSID.equals(mLastBssid)) {
+                        scanResult = result;
+                        break;
+                    }
+                }
+            }
+ 
+            final ProvisioningConfiguration prov;
+            ProvisioningConfiguration.ScanResultInfo scanResultInfo = null;
+            if (scanResult != null) {
+                final List<ScanResultInfo.InformationElement> ies =
+                        new ArrayList<ScanResultInfo.InformationElement>();
+                for (ScanResult.InformationElement ie : scanResult.getInformationElements()) {
+                    ScanResultInfo.InformationElement scanResultInfoIe =
+                            new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes());
+                    ies.add(scanResultInfoIe);
+                }
+                scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID,
+                        scanResult.BSSID, ies);
+            }
+
+            if (!isUsingStaticIp) {
+                prov = new ProvisioningConfiguration.Builder()
+                    .withPreDhcpAction()
+                    .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
+                    .withNetwork(getCurrentNetwork())
+                    .withDisplayName(config.SSID)
+                    .withScanResultInfo(scanResultInfo)
+                    .withLayer2Information(layer2Info)
+                    .build();
+            } else {
+                StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration();
+                prov = new ProvisioningConfiguration.Builder()
+                        .withStaticConfiguration(staticIpConfig)
+                        .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
+                        .withNetwork(getCurrentNetwork())
+                        .withDisplayName(config.SSID)
+                        .withLayer2Information(layer2Info)
+                        .build();
+            }
+            mIpClient.startProvisioning(prov);
+        }
+
+        return true;
+    }
+
+    private void updateQcWifiGenerationInfo() {
+        WifiGenerationStatus wifiGenerationStatus = getWifiGenerationStatus();
+
+        if (wifiGenerationStatus == null)
+            return;
+
+        mWifiInfo.setVhtMax8SpatialStreamsSupport(wifiGenerationStatus.vhtMax8SpatialStreamsSupport);
+        WifiConfiguration config = getCurrentWifiConfiguration();
+
+        if (config == null)
+            return;
+
+        ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+        if (scanDetailCache == null)
+            return;
+
+        ScanResult result = scanDetailCache.getScanResult(mLastBssid);
+        if (result != null) {
+            if (result.capabilities.contains("WFA-HE-READY")) {
+                mWifiInfo.setHe8ssCapableAp(true);
+            } else {
+                mWifiInfo.setHe8ssCapableAp(false);
+            }
+        }
+    }
+    public List<ScanDetail> qtiGetFilteredScan(List<ScanDetail> scanDetails) {
+        // All Bands are available for use
+        if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_NONE))
+            return scanDetails;
+
+        boolean filter2G = false;
+        boolean filter5G = false;
+
+        if (isDisconnected()) {
+            if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))
+                filter2G = true;
+            if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+                filter5G = true;
+        } else {
+            if (mWifiInfo.is24GHz() &&
+                    mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+                filter5G = true;
+            else if ((mWifiInfo.is5GHz() || mWifiInfo.is6GHz()) &&
+                        mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))
+                filter2G = true;
+        }
+
+        List<ScanDetail> filtered = new ArrayList<ScanDetail>();
+        for (ScanDetail entry : scanDetails) {
+            if (entry.getScanResult().is24GHz() && !filter2G)
+                filtered.add(entry);
+            if (entry.getScanResult().is5GHz() && !filter5G)
+                filtered.add(entry);
+        }
+        if (mVerboseLoggingEnabled)
+            Log.d(TAG, "filtering out " + (scanDetails.size() - filtered.size()) + " scan entries");
+
+        return filtered;
+    }
+
+    private void updateConnectedBand(int freq, boolean set) {
+        if (mVerboseLoggingEnabled)
+            Log.d(TAG, "updateConnectedBand freq="+freq+" set="+set);
+
+        if (set) {
+            mWifiInfo.setFrequency(freq);
+
+            if (ScanResult.is24GHz(freq)) {
+                mWifiNative.qtiUpdateConnectedBand(mIdentity, WifiNative.ConnectedBand.BAND_2G);
+            } else if (ScanResult.is5GHz(freq) || ScanResult.is6GHz(freq)) {
+                mWifiNative.qtiUpdateConnectedBand(mIdentity, WifiNative.ConnectedBand.BAND_5G);
+            }
+        } else {
+            mWifiNative.qtiUpdateConnectedBand(mIdentity, WifiNative.ConnectedBand.BAND_NONE);
+        }
+    }
+
+    /**
+     * Check for STA+STA in active mode.
+     *
+     * active mode: atleast one of the iface is connected and other is looking for connection
+     */
+    public boolean isActiveDualMode() {
+        if (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_NONE)) {
+            return false;
+        }
+
+        if (!isConnected() && (mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G)
+                               || mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G)))
+            return true;
+
+        if (isConnected()
+            && ((mWifiInfo.is24GHz() && mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_5G))
+            || ((mWifiInfo.is5GHz() || mWifiInfo.is6GHz()) && mWifiNative.qtiConnectedbands.get(WifiNative.ConnectedBand.BAND_2G))))
+            return true;
+
+        return false;
+    }
+}
diff --git a/service/java/com/android/server/wifi/QtiClientModeManager.java b/service/java/com/android/server/wifi/QtiClientModeManager.java
new file mode 100644
index 0000000..aba7e58
--- /dev/null
+++ b/service/java/com/android/server/wifi/QtiClientModeManager.java
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityManager;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.ScanResult;
+import android.net.NetworkCapabilities;
+import android.net.Network;
+import android.net.NetworkInfo;
+import android.net.LinkProperties;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.RegistrationManager;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.text.TextUtils;
+import android.util.Log;
+import android.os.Handler;
+import android.os.WorkSource;
+
+import android.net.wifi.WifiConfiguration;
+import com.android.internal.util.IState;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.internal.util.AsyncChannel;
+import com.android.server.wifi.WifiNative.InterfaceCallback;
+import com.android.server.wifi.util.WifiAsyncChannel;
+import com.android.server.wifi.util.WifiHandler;
+
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+/**
+ * Manager WiFi in Client Mode where we connect to configured networks.
+ */
+public class QtiClientModeManager implements ActiveModeManager {
+    private static final String TAG = "QtiWifiClientModeManager";
+
+    private final ClientModeStateMachine mStateMachine;
+
+    private final Context mContext;
+    private final Clock mClock;
+    private final WifiNative mWifiNative;
+
+    private final WifiInjector mWifiInjector;
+    private final SarManager mSarManager;
+    private final WakeupController mWakeupController;
+    private final Listener mListener;
+
+    private String mClientInterfaceName;
+    private boolean mIfaceIsUp = false;
+    private @Role int mRole = ROLE_UNSPECIFIED;
+    private DeferStopHandler mDeferStopHandler;
+    private int mTargetRole = ROLE_UNSPECIFIED;
+    private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+    private final QtiClientModeImpl mQtiClientModeImpl;
+    private final int mStaId;
+    /**
+     * Asynchronous channel to QtiClientModeImpl
+     */
+    AsyncChannel mQtiClientModeImplChannel;
+
+    QtiClientModeManager(Context context, @NonNull Looper looper, Clock clock, WifiNative wifiNative,
+            Listener listener, WifiInjector wifiInjector, SarManager sarManager,
+            WakeupController wakeupController, int staId, WifiConfigManager wifiConfigManager) {
+        mContext = context;
+        mClock = clock;
+        mWifiNative = wifiNative;
+        mSarManager = sarManager;
+        mWakeupController = wakeupController;
+        mWifiInjector = wifiInjector;
+        mStaId = staId;
+        mListener = listener;
+        mQtiClientModeImpl = wifiInjector.makeQtiClientModeImpl(mListener, wifiConfigManager);
+        mStateMachine = new ClientModeStateMachine(looper);
+        mDeferStopHandler = new DeferStopHandler(TAG, looper);
+    }
+
+    public QtiClientModeImpl getClientModeImpl() {
+        return mQtiClientModeImpl;
+    }
+
+    public int getStaId() {
+        return mStaId;
+    }
+
+    public AsyncChannel getClientImplChannel() {
+        return mQtiClientModeImplChannel;
+    }
+
+    /**
+     * Start client mode.
+     */
+    @Override
+    public void start() {
+        mTargetRole = ROLE_CLIENT_SCAN_ONLY;
+        mQtiClientModeImpl.enableVerboseLogging(mWifiInjector.getVerboseLogging());
+        mQtiClientModeImpl.start();
+        mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
+    }
+
+    /**
+     * Disconnect from any currently connected networks and stop client mode.
+     */
+    @Override
+    public void stop() {
+        Log.d(TAG, " currentstate: " + getCurrentStateName());
+        mTargetRole = ROLE_UNSPECIFIED;
+        if (mIfaceIsUp) {
+            updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                    WifiManager.WIFI_STATE_ENABLED);
+        } else {
+            updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                    WifiManager.WIFI_STATE_ENABLING);
+        }
+        mDeferStopHandler.start(getWifiOffDeferringTimeMs());
+        mQtiClientModeImpl.quit();
+    }
+
+    @Override
+    public boolean isStopping() {
+        return mTargetRole == ROLE_UNSPECIFIED && mRole != ROLE_UNSPECIFIED;
+    }
+    private class DeferStopHandler extends WifiHandler {
+        private boolean mIsDeferring = false;
+        private ImsMmTelManager mImsMmTelManager = null;
+        private Looper mLooper = null;
+        private final Runnable mRunnable = () -> continueToStopWifi();
+        private int mMaximumDeferringTimeMillis = 0;
+        private long mDeferringStartTimeMillis = 0;
+
+        private static final int QTI_DELAY_DISCONNECT_ON_NETWORK_LOST_MS = 1000;
+        private NetworkRequest mImsRequest = null;
+        private ConnectivityManager mConnectivityManager = null;
+
+        private RegistrationManager.RegistrationCallback mImsRegistrationCallback =
+                new RegistrationManager.RegistrationCallback() {
+                    @Override
+                    public void onRegistered(int imsRadioTech) {
+                        Log.d(TAG, "on IMS registered on type " + imsRadioTech);
+                        if (!mIsDeferring) return;
+
+                        if (imsRadioTech != AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+                            continueToStopWifi();
+                        }
+                    }
+
+                    @Override
+                    public void onUnregistered(ImsReasonInfo imsReasonInfo) {
+                        Log.d(TAG, "on IMS unregistered");
+                        // Wait for onLost in NetworkCallback
+                    }
+                };
+
+        private NetworkCallback mImsNetworkCallback = new NetworkCallback() {
+            private int countRegIMS = 0;
+            @Override
+            public void onAvailable(Network network) {
+                Log.d(TAG, "IMS network available id: " + network);
+                countRegIMS++;
+            }
+
+            @Override
+            public void onLost(Network network) {
+                Log.d(TAG, "IMS network lost: " + network);
+                countRegIMS--;
+                // Add additional delay of 1 sec after onLost() indication as IMS PDN down
+                // at modem takes additional 500ms+ of delay.
+                // TODO: this should be fixed.
+                if (mIsDeferring && (countRegIMS == 0)
+                        && !postDelayed(mRunnable, QTI_DELAY_DISCONNECT_ON_NETWORK_LOST_MS))
+                    continueToStopWifi();
+            }
+        };
+
+        DeferStopHandler(String tag, Looper looper) {
+            super(tag, looper);
+            mLooper = looper;
+        }
+
+        public void start(int delayMs) {
+            if (mIsDeferring) return;
+
+            mMaximumDeferringTimeMillis = delayMs;
+            mDeferringStartTimeMillis = mClock.getElapsedSinceBootMillis();
+            // Most cases don't need delay, check it first to avoid unnecessary work.
+            if (delayMs == 0) {
+                continueToStopWifi();
+                return;
+            }
+
+            mImsMmTelManager = ImsMmTelManager.createForSubscriptionId(mActiveSubId);
+            if (mImsMmTelManager == null || !postDelayed(mRunnable, delayMs)) {
+                // if no delay or failed to add runnable, stop Wifi immediately.
+                continueToStopWifi();
+                return;
+            }
+
+            mIsDeferring = true;
+            Log.d(TAG, "Start DeferWifiOff handler with deferring time "
+                    + delayMs + " ms. for subId: " + mActiveSubId);
+
+            try {
+                mImsMmTelManager.registerImsRegistrationCallback(
+                        new HandlerExecutor(new Handler(mLooper)),
+                        mImsRegistrationCallback);
+            } catch (RuntimeException | ImsException e) {
+                Log.e(TAG, "registerImsRegistrationCallback failed", e);
+                continueToStopWifi();
+                return;
+            }
+
+            mImsRequest = new NetworkRequest.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                .build();
+
+            mConnectivityManager = (ConnectivityManager)mContext.getSystemService
+                                   (Context.CONNECTIVITY_SERVICE);
+
+            mConnectivityManager.registerNetworkCallback(mImsRequest, mImsNetworkCallback,
+                                                         new Handler(mLooper));
+        }
+
+        private void continueToStopWifi() {
+            Log.d(TAG, "The target role " + mTargetRole);
+
+            int deferringDurationMillis =
+                    (int) (mClock.getElapsedSinceBootMillis() - mDeferringStartTimeMillis);
+            boolean isTimedOut = mMaximumDeferringTimeMillis > 0
+                    && deferringDurationMillis >= mMaximumDeferringTimeMillis;
+            if (mTargetRole == ROLE_UNSPECIFIED) {
+                Log.d(TAG, "Continue to stop wifi");
+                mStateMachine.quitNow();
+            } else if (mTargetRole == ROLE_CLIENT_SCAN_ONLY) {
+                mStateMachine.sendMessage(
+                            ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE);
+            } else {
+                updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
+                        WifiManager.WIFI_STATE_DISABLING);
+            }
+
+            if (!mIsDeferring) return;
+
+            Log.d(TAG, "Stop DeferWifiOff handler.");
+            removeCallbacks(mRunnable);
+            if (mImsMmTelManager != null) {
+                try {
+                    mImsMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback);
+                } catch (RuntimeException e) {
+                    Log.e(TAG, "unregisterImsRegistrationCallback failed", e);
+                }
+            }
+
+            if (mConnectivityManager != null) {
+                mConnectivityManager.unregisterNetworkCallback(mImsNetworkCallback);
+            }
+
+            mIsDeferring = false;
+        }
+    }
+
+    /**
+     * Get deferring time before turning off WiFi.
+     */
+    private int getWifiOffDeferringTimeMs() {
+        SubscriptionManager subscriptionManager = (SubscriptionManager) mContext.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        if (subscriptionManager == null) {
+            return 0;
+        }
+
+        List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList();
+        if (subInfoList == null) {
+            return 0;
+        }
+
+        // Get the delay for first active subscription latched on IWLAN.
+        int delay = 0;
+        for (SubscriptionInfo subInfo : subInfoList) {
+            delay = getWifiOffDeferringTimeMs(subInfo.getSubscriptionId());
+            if (delay > 0) {
+                mActiveSubId = subInfo.getSubscriptionId();
+                break;
+            }
+        }
+        return delay;
+    }
+
+    private int getWifiOffDeferringTimeMs(int subId) {
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return 0;
+        }
+
+        ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId);
+        // If no wifi calling, no delay
+        if (!imsMmTelManager.isAvailable(
+                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                    ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
+            return 0;
+        }
+
+        TelephonyManager defaultVoiceTelephonyManager =
+                mContext.getSystemService(TelephonyManager.class)
+                        .createForSubscriptionId(subId);
+        // if LTE is available, no delay needed as IMS will be registered over LTE
+        if (defaultVoiceTelephonyManager.getVoiceNetworkType()
+                == TelephonyManager.NETWORK_TYPE_LTE) {
+            return 0;
+        }
+
+        CarrierConfigManager configManager =
+                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle config = configManager.getConfigForSubId(subId);
+        return (config != null)
+                ? config.getInt(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT)
+                : 0;
+    }
+
+    @Override
+    public @Role int getRole() {
+        return mRole;
+    }
+
+    @Override
+    public void setRole(@Role int role) {
+        Preconditions.checkState(CLIENT_ROLES.contains(role));
+        if (role == ROLE_CLIENT_SCAN_ONLY) {
+            mTargetRole = role;
+            // Switch client mode manager to scan only mode.
+            mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE);
+        } else if (CLIENT_CONNECTIVITY_ROLES.contains(role)) {
+            mTargetRole = role;
+            // Switch client mode manager to connect mode.
+            mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role);
+        }
+    }
+
+    /**
+     * Dump info about this ClientMode manager.
+     */
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("--Dump of QtiClientModeManager--");
+
+        pw.println("current StateMachine mode: " + getCurrentStateName());
+        pw.println("mRole: " + mRole);
+        pw.println("mTargetRole: " + mTargetRole);
+        pw.println("mClientInterfaceName: " + mClientInterfaceName);
+        pw.println("mIfaceIsUp: " + mIfaceIsUp);
+        mStateMachine.dump(fd, pw, args);
+	}
+    /**
+     * Listener for ClientMode state changes.
+     */
+    public interface Listener {
+        /**
+         * Invoke when wifi state changes.
+         * @param state new wifi state
+         */
+        void onStateChanged(int staId, int state);
+
+        /**
+         * Invoke when RSSI changes.
+         * @param rssi new RSSI value.
+         */
+        void onRssiChanged(int staId, int rssi);
+
+        /**
+         * Invoke when Link configuration changes.
+         * @param linkProperties Link Property object.
+         */
+        void onLinkConfigurationChanged(int staId, LinkProperties lp);
+
+        /**
+         * Invoke when network state changes.
+         * @param networkInfo network info corresponding to bssid.
+         */
+        void onNetworkStateChanged(int staId, NetworkInfo netInfo);
+    }
+
+    private String getCurrentStateName() {
+        IState currentState = mStateMachine.getCurrentState();
+
+        if (currentState != null) {
+            return currentState.getName();
+        }
+
+        return "StateMachine not active";
+    }
+
+    /**
+     * Update Wifi state and send the broadcast.
+     * @param newState new Wifi state
+     * @param currentState current wifi state
+     */
+    private void updateConnectModeState(int newState, int currentState) {
+        mListener.onStateChanged(mStaId, newState);
+        mQtiClientModeImpl.setWifiStateForApiCalls(newState);
+    }
+
+    private class ClientModeStateMachine extends StateMachine {
+        // Commands for the state machine.
+        public static final int CMD_START = 0;
+        public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE = 1;
+        public static final int CMD_SWITCH_TO_CONNECT_MODE = 2;
+        public static final int CMD_INTERFACE_STATUS_CHANGED = 3;
+        public static final int CMD_INTERFACE_DESTROYED = 4;
+        public static final int CMD_INTERFACE_DOWN = 5;
+        public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE = 6;
+        private final State mIdleState = new IdleState();
+        private final State mStartedState = new StartedState();
+        private final State mScanOnlyModeState = new ScanOnlyModeState();
+        private final State mConnectModeState = new ConnectModeState();
+
+        private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() {
+            @Override
+            public void onDestroyed(String ifaceName) {
+                if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
+                    Log.d(TAG, "STA iface " + ifaceName + " was destroyed, stopping client mode");
+
+                    // we must immediately clean up state in ClientModeImpl to unregister
+                    // all client mode related objects
+                    // Note: onDestroyed is only called from the main Wifi thread
+                    mQtiClientModeImpl.handleIfaceDestroyed();
+
+                    sendMessage(CMD_INTERFACE_DESTROYED);
+                }
+            }
+
+            @Override
+            public void onUp(String ifaceName) {
+                if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
+                    sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);
+                }
+            }
+
+            @Override
+            public void onDown(String ifaceName) {
+                if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
+                    sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0);
+                }
+            }
+        };
+
+        ClientModeStateMachine(Looper looper) {
+            super(TAG, looper);
+
+            // CHECKSTYLE:OFF IndentationCheck
+            addState(mIdleState);
+            addState(mStartedState);
+                addState(mScanOnlyModeState, mStartedState);
+                addState(mConnectModeState, mStartedState);
+            // CHECKSTYLE:ON IndentationCheck
+
+            setInitialState(mIdleState);
+            start();
+        }
+
+        private class IdleState extends State {
+            @Override
+            public void enter() {
+                Log.d(TAG, "entering IdleState");
+                mClientInterfaceName = null;
+                mIfaceIsUp = false;
+            }
+
+            @Override
+            public boolean processMessage(Message message) {
+                switch (message.what) {
+                    case CMD_START:
+                        // Always start in scan mode first.
+                        mClientInterfaceName =
+                                mWifiNative.setupInterfaceForClientInScanMode(
+                                mWifiNativeInterfaceCallback);
+                        if (TextUtils.isEmpty(mClientInterfaceName)) {
+                            Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
+                            break;
+                        }
+                        transitionTo(mScanOnlyModeState);
+                        break;
+                    default:
+                        Log.d(TAG, "received an invalid message: " + message);
+                        return NOT_HANDLED;
+                }
+                return HANDLED;
+            }
+        }
+
+        private class StartedState extends State {
+
+            private void onUpChanged(boolean isUp) {
+                if (isUp == mIfaceIsUp) {
+                    return;  // no change
+                }
+                mIfaceIsUp = isUp;
+                if (!isUp) {
+                    // if the interface goes down we should exit and go back to idle state.
+                    Log.d(TAG, "interface down!");
+                    mStateMachine.sendMessage(CMD_INTERFACE_DOWN);
+                }
+            }
+
+            @Override
+            public void enter() {
+                Log.d(TAG, "entering StartedState");
+                mIfaceIsUp = false;
+                onUpChanged(mWifiNative.isInterfaceUp(mClientInterfaceName));
+            }
+
+            @Override
+            public boolean processMessage(Message message) {
+                switch(message.what) {
+                    case CMD_START:
+                        // Already started, ignore this command.
+                        break;
+                    case CMD_SWITCH_TO_CONNECT_MODE:
+                        mRole = message.arg1; // could be any one of possible connect mode roles.
+                        updateConnectModeState(WifiManager.WIFI_STATE_ENABLING,
+                                WifiManager.WIFI_STATE_DISABLED);
+                        if (!mWifiNative.switchClientInterfaceToConnectivityMode(
+                                mClientInterfaceName)) {
+                            updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN,
+                                    WifiManager.WIFI_STATE_ENABLING);
+                            updateConnectModeState(WifiManager.WIFI_STATE_DISABLED,
+                                    WifiManager.WIFI_STATE_UNKNOWN);
+                            break;
+                        }
+                        transitionTo(mConnectModeState);
+                        break;
+                    case CMD_SWITCH_TO_SCAN_ONLY_MODE:
+                        updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                                WifiManager.WIFI_STATE_ENABLED);
+                        mDeferStopHandler.start(getWifiOffDeferringTimeMs());
+                        break;
+                    case CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE:
+                        transitionTo(mScanOnlyModeState);
+                        break;
+                    case CMD_INTERFACE_DOWN:
+                        Log.e(TAG, "Detected an interface down, reporting failure to "
+                                + "SelfRecovery");
+                        transitionTo(mIdleState);
+                        break;
+                    case CMD_INTERFACE_STATUS_CHANGED:
+                        boolean isUp = message.arg1 == 1;
+                        onUpChanged(isUp);
+                        break;
+                    case CMD_INTERFACE_DESTROYED:
+                        Log.d(TAG, "interface destroyed - client mode stopping");
+                        mClientInterfaceName = null;
+                        transitionTo(mIdleState);
+                        break;
+                    default:
+                        return NOT_HANDLED;
+                }
+                return HANDLED;
+            }
+
+            /**
+             * Clean up state, unregister listeners and update wifi state.
+             */
+            @Override
+            public void exit() {
+                mQtiClientModeImpl.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
+
+                if (mClientInterfaceName != null) {
+                    mWifiNative.teardownInterface(mClientInterfaceName);
+                    mClientInterfaceName = null;
+                    mIfaceIsUp = false;
+                }
+
+                // once we leave started, nothing else to do...  stop the state machine
+                mRole = ROLE_UNSPECIFIED;
+                mStateMachine.quitNow();
+                mQtiClientModeImpl.quit();
+            }
+        }
+
+        private class ScanOnlyModeState extends State {
+            @Override
+            public void enter() {
+                Log.d(TAG, "entering ScanOnlyModeState");
+                mQtiClientModeImpl.setOperationalMode(ClientModeImpl.SCAN_ONLY_MODE,
+                        mClientInterfaceName);
+                mRole = ROLE_CLIENT_SCAN_ONLY;
+
+                // Inform sar manager that scan only is being enabled
+                mSarManager.setScanOnlyWifiState(WifiManager.WIFI_STATE_ENABLED);
+                mWakeupController.start();
+            }
+
+            @Override
+            public boolean processMessage(Message message) {
+                switch (message.what) {
+                    case CMD_SWITCH_TO_SCAN_ONLY_MODE:
+                        // Already in scan only mode, ignore this command.
+                        break;
+                    default:
+                        return NOT_HANDLED;
+                }
+                return HANDLED;
+            }
+
+            @Override
+            public void exit() {
+                // Inform sar manager that scan only is being disabled
+                mSarManager.setScanOnlyWifiState(WifiManager.WIFI_STATE_DISABLED);
+                mWakeupController.stop();
+            }
+        }
+
+        private class ConnectModeState extends State {
+            @Override
+            public void enter() {
+                Log.d(TAG, "entering ConnectModeState");
+                mQtiClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
+                        mClientInterfaceName);
+                updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
+                        WifiManager.WIFI_STATE_ENABLING);
+
+                // Inform sar manager that wifi is Enabled
+                mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
+            }
+
+            @Override
+            public boolean processMessage(Message message) {
+                switch (message.what) {
+                    case CMD_SWITCH_TO_CONNECT_MODE:
+                        int newRole = message.arg1;
+                        // Already in connect mode, only switching the connectivity roles.
+                        if (newRole != mRole) {
+                            mRole = newRole;
+                        }
+                        break;
+                    case CMD_SWITCH_TO_SCAN_ONLY_MODE:
+                        updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                                WifiManager.WIFI_STATE_ENABLED);
+                        return NOT_HANDLED; // Handled in StartedState.
+                    case CMD_INTERFACE_DOWN:
+                        updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                                WifiManager.WIFI_STATE_UNKNOWN);
+                        return NOT_HANDLED; // Handled in StartedState.
+                    case CMD_INTERFACE_STATUS_CHANGED:
+                        boolean isUp = message.arg1 == 1;
+                        if (isUp == mIfaceIsUp) {
+                            break;  // no change
+                        }
+                        if (!isUp) {
+                            if (!mQtiClientModeImpl.isConnectedMacRandomizationEnabled()) {
+                                // Handle the error case where our underlying interface went down if
+                                // we do not have mac randomization enabled (b/72459123).
+                                // if the interface goes down we should exit and go back to idle
+                                // state.
+                                updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN,
+                                        WifiManager.WIFI_STATE_ENABLED);
+                            } else {
+                                return HANDLED; // For MAC randomization, ignore...
+                            }
+                        }
+                        return NOT_HANDLED; // Handled in StartedState.
+                    case CMD_INTERFACE_DESTROYED:
+                        updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
+                                WifiManager.WIFI_STATE_ENABLED);
+                        return NOT_HANDLED; // Handled in StartedState.
+                    default:
+                        return NOT_HANDLED;
+                }
+                return HANDLED;
+            }
+
+            @Override
+            public void exit() {
+                updateConnectModeState(WifiManager.WIFI_STATE_DISABLED,
+                        WifiManager.WIFI_STATE_DISABLING);
+
+                // Inform sar manager that wifi is being disabled
+                mSarManager.setClientWifiState(WifiManager.WIFI_STATE_DISABLED);
+            }
+        }
+    }
+}
diff --git a/service/java/com/android/server/wifi/QtiWifiConnectivityManager.java b/service/java/com/android/server/wifi/QtiWifiConnectivityManager.java
new file mode 100644
index 0000000..7f35435
--- /dev/null
+++ b/service/java/com/android/server/wifi/QtiWifiConnectivityManager.java
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE;
+
+import android.annotation.NonNull;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.net.MacAddress;
+import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.DeviceMobilityState;
+import android.net.wifi.WifiNetworkSuggestion;
+import android.net.wifi.WifiScanner;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.WifiScanner.PnoSettings;
+import android.net.wifi.WifiScanner.ScanSettings;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Process;
+import android.os.WorkSource;
+import android.util.ArrayMap;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.util.ScanResultUtil;
+import com.android.wifi.resources.R;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * This class manages all the connectivity related scanning activities.
+ *
+ * When the screen is turned on or off, WiFi is connected or disconnected,
+ * or on-demand, a scan is initiatiated and the scan results are passed
+ * to WifiNetworkSelector for it to make a recommendation on which network
+ * to connect to.
+ */
+public class QtiWifiConnectivityManager {
+    private static final long RESET_TIME_STAMP = Long.MIN_VALUE;
+    // This is the time interval for the connection attempt rate calculation. Connection attempt
+    // timestamps beyond this interval is evicted from the list.
+    public static final int MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS = 4 * 60 * 1000; // 4 mins
+    // Max number of connection attempts in the above time interval.
+    public static final int MAX_CONNECTION_ATTEMPTS_RATE = 6;
+    private static final int TEMP_BSSID_BLOCK_DURATION = 10 * 1000; // 10 seconds
+    // Maximum age of frequencies last seen to be included in pno scans. (30 days)
+    private static final long MAX_PNO_SCAN_FREQUENCY_AGE_MS = (long) 1000 * 3600 * 24 * 30;
+    // ClientModeImpl has a bunch of states. From the
+    // WifiConnectivityManager's perspective it only cares
+    // if it is in Connected state, Disconnected state or in
+    // transition between these two states.
+    public static final int WIFI_STATE_UNKNOWN = 0;
+    public static final int WIFI_STATE_CONNECTED = 1;
+    public static final int WIFI_STATE_DISCONNECTED = 2;
+    public static final int WIFI_STATE_TRANSITIONING = 3;
+
+    private static final boolean SCAN_IMMEDIATELY = true;
+
+    // Initial scan state, used to manage performing partial scans in initial scans
+    // Initial scans are the first scan after enabling Wifi or turning on screen when disconnected
+    private static final int INITIAL_SCAN_STATE_START = 0;
+    private static final int INITIAL_SCAN_STATE_AWAITING_RESPONSE = 1;
+    private static final int INITIAL_SCAN_STATE_COMPLETE = 2;
+
+    // Log tag for this class
+    private static final String TAG = "QtiWifiConnectivityManager";
+    private static final String ALL_SINGLE_SCAN_LISTENER = "AllSingleScanListener";
+    private static final String PNO_SCAN_LISTENER = "PnoScanListener";
+
+    private final Context mContext;
+    private final QtiClientModeImpl mStateMachine;
+    private final WifiInjector mWifiInjector;
+    private final WifiConfigManager mConfigManager;
+    private final WifiInfo mWifiInfo;
+    private final WifiConnectivityHelper mConnectivityHelper;
+    private final WifiNetworkSelector mNetworkSelector;
+    private final Handler mEventHandler;
+    private final Clock mClock;
+    private final ScoringParams mScoringParams;
+    private final LocalLog mLocalLog;
+    private final LinkedList<Long> mConnectionAttemptTimeStamps;
+    private final BssidBlocklistMonitor mBssidBlocklistMonitor;
+    private WifiScanner mScanner;
+
+    private boolean mDbg = false;
+    private boolean mVerboseLoggingEnabled = false;
+    private boolean mWifiEnabled = false;
+    private boolean mRunning = false;
+    private boolean mScreenOn = false;
+    private int mMiracastMode = WifiP2pManager.MIRACAST_DISABLED;
+    private int mWifiState = WIFI_STATE_UNKNOWN;
+    private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE;
+    private boolean mAutoJoinEnabledExternal = true; // enabled by default
+    private int mTotalConnectivityAttemptsRateLimited = 0;
+    private String mLastConnectionAttemptBssid = null;
+
+    // Used for Initial Scan metrics
+    private boolean mFailedInitialPartialScan = false;
+    private int mInitialPartialScanChannelCount;
+
+    // Device configs
+    private boolean mWaitForFullBandScanResults = false;
+    private final int mStaId;
+
+    // Scanning Schedules
+    // Default schedule used in case of invalid configuration
+    private static final int[] DEFAULT_SCANNING_SCHEDULE_SEC = {20, 40, 80, 160};
+    private int[] mConnectedSingleScanScheduleSec;
+    private int[] mDisconnectedSingleScanScheduleSec;
+    private int[] mConnectedSingleSavedNetworkSingleScanScheduleSec;
+    private List<WifiCandidates.Candidate> mLatestCandidates = null;
+    private long mLatestCandidatesTimestampMs = 0;
+
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private int[] mCurrentSingleScanScheduleSec;
+
+    private int mCurrentSingleScanScheduleIndex;
+    private WifiChannelUtilization mWifiChannelUtilization;
+    // Cached WifiCandidates used in high mobility state to avoid connecting to APs that are
+    // moving relative to the user.
+    private @DeviceMobilityState int mDeviceMobilityState =
+            WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
+
+    // A helper to log debugging information in the local log buffer, which can
+    // be retrieved in bugreport.
+    private void localLog(String log) {
+        mLocalLog.log(log);
+        if (mVerboseLoggingEnabled) Log.v(TAG, log);
+    }
+
+    /**
+     * Enable verbose logging for QtiWifiConnectivityManager.
+     */
+    public void enableVerboseLogging(boolean verbose) {
+        mVerboseLoggingEnabled = verbose;
+    }
+
+    /**
+     * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener.
+     * Executes selection of potential network candidates, initiation of connection attempt to that
+     * network.
+     *
+     * @return true - if a candidate is selected by WifiNetworkSelector
+     *         false - if no candidate is selected by WifiNetworkSelector
+     */
+    private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName,
+            boolean isFullScan) {
+        mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(
+                mStateMachine.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ);
+
+        updateUserDisabledList(scanDetails);
+
+        // Check if any blocklisted BSSIDs can be freed.
+        Set<String> bssidBlocklist = mBssidBlocklistMonitor.updateAndGetBssidBlocklist();
+
+        if (mStateMachine.isSupplicantTransientState()) {
+            localLog(listenerName
+                    + " onResults: No network selection because supplicantTransientState is "
+                    + mStateMachine.isSupplicantTransientState());
+            return false;
+        }
+
+        localLog(listenerName + " onResults: start network selection");
+
+        List<ScanDetail> filteredScans = mStateMachine.qtiGetFilteredScan(scanDetails);
+        List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan(
+                filteredScans, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(),
+                mStateMachine.isDisconnected(), true);
+        mLatestCandidates = candidates;
+        mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis();
+
+        WifiConfiguration candidate = mNetworkSelector.selectNetwork(candidates);
+        if (candidate != null) {
+            localLog(listenerName + ":  WNS candidate-" + candidate.SSID);
+            connectToNetwork(candidate);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    private void updateUserDisabledList(List<ScanDetail> scanDetails) {
+        List<String> results = new ArrayList<>();
+        List<ScanResult> passpointAp = new ArrayList<>();
+        for (ScanDetail scanDetail : scanDetails) {
+            results.add(ScanResultUtil.createQuotedSSID(scanDetail.getScanResult().SSID));
+            if (!scanDetail.getScanResult().isPasspointNetwork()) {
+                continue;
+            }
+            passpointAp.add(scanDetail.getScanResult());
+        }
+        if (!passpointAp.isEmpty()) {
+            results.addAll(new ArrayList<>(mWifiInjector.getPasspointManager()
+                    .getAllMatchingPasspointProfilesForScanResults(passpointAp).keySet()));
+        }
+        mConfigManager.updateUserDisabledList(results);
+    }
+
+    /**
+     * Set whether bluetooth is in the connected state
+     */
+    public void setBluetoothConnected(boolean isBluetoothConnected) {
+        mNetworkSelector.setBluetoothConnected(isBluetoothConnected);
+    }
+    // All single scan results listener.
+    //
+    // Note: This is the listener for all the available single scan results,
+    //       including the ones initiated by QtiWifiConnectivityManager and
+    //       other modules.
+    private class AllSingleScanListener implements WifiScanner.ScanListener {
+        private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>();
+
+        public void clearScanDetails() {
+            mScanDetails.clear();
+        }
+
+        @Override
+        public void onSuccess() {
+        }
+
+        @Override
+        public void onFailure(int reason, String description) {
+            localLog("registerScanListener onFailure:"
+                      + " reason: " + reason + " description: " + description);
+        }
+
+        @Override
+        public void onPeriodChanged(int periodInMs) {
+        }
+
+        @Override
+        public void onResults(WifiScanner.ScanData[] results) {
+            if (!mWifiEnabled) {
+                clearScanDetails();
+                mWaitForFullBandScanResults = false;
+                return;
+            }
+
+            // We treat any full band scans (with DFS or not) as "full".
+            boolean isFullBandScanResults =
+                results[0].getBandScanned() == WifiScanner.WIFI_BAND_BOTH_WITH_DFS
+                         || results[0].getBandScanned() == WifiScanner.WIFI_BAND_BOTH;
+
+            // Full band scan results only.
+            if (mWaitForFullBandScanResults) {
+                if (!isFullBandScanResults) {
+                    localLog("AllSingleScanListener waiting for full band scan results.");
+                    clearScanDetails();
+                    return;
+                } else {
+                    mWaitForFullBandScanResults = false;
+                }
+            }
+            boolean wasConnectAttempted = handleScanResults(mScanDetails,
+                    ALL_SINGLE_SCAN_LISTENER, isFullBandScanResults);
+            clearScanDetails();
+            // Check if we are in the middle of initial partial scan
+            if (mInitialScanState == INITIAL_SCAN_STATE_AWAITING_RESPONSE) {
+                // Done with initial scan
+                setInitialScanState(INITIAL_SCAN_STATE_COMPLETE);
+
+                if (wasConnectAttempted) {
+                    Log.i(TAG, "Connection attempted with the reduced initial scans");
+                    mInitialPartialScanChannelCount = 0;
+                } else {
+                    Log.i(TAG, "Connection was not attempted, issuing a full scan");
+                    mFailedInitialPartialScan = true;
+                }
+            } else if (mInitialScanState == INITIAL_SCAN_STATE_COMPLETE) {
+                mFailedInitialPartialScan = false;
+                mInitialPartialScanChannelCount = 0;
+            }
+        }
+
+        @Override
+        public void onFullResult(ScanResult fullScanResult) {
+            if (!mWifiEnabled) {
+                return;
+            }
+
+            if (mDbg) {
+                localLog("AllSingleScanListener onFullResult: " + fullScanResult.SSID
+                        + " capabilities " + fullScanResult.capabilities);
+            }
+
+            mScanDetails.add(ScanResultUtil.toScanDetail(fullScanResult));
+        }
+    }
+
+    private final AllSingleScanListener mAllSingleScanListener = new AllSingleScanListener();
+
+
+    /**
+     * QtiWifiConnectivityManager constructor
+     */
+    QtiWifiConnectivityManager(Context context, ScoringParams scoringParams,
+            QtiClientModeImpl stateMachine,
+            WifiInjector injector, WifiConfigManager configManager,
+            WifiNetworkSelector networkSelector, WifiConnectivityHelper connectivityHelper,
+            Handler handler, Clock clock, LocalLog localLog, int identity) {
+        mContext = context;
+        mStateMachine = stateMachine;
+        mWifiInjector = injector;
+        mConfigManager = configManager;
+        mWifiInfo = mStateMachine.getWifiInfo();
+        mNetworkSelector = networkSelector;
+        mConnectivityHelper = connectivityHelper;
+        mLocalLog = localLog;
+        mEventHandler = handler;
+        mClock = clock;
+        mScoringParams = scoringParams;
+        mConnectionAttemptTimeStamps = new LinkedList<>();
+        mStaId = identity;
+        // Listen to WifiConfigManager network update events
+        mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor();
+        mWifiChannelUtilization = mWifiInjector.getWifiChannelUtilizationScan();
+        mNetworkSelector.setWifiChannelUtilization(mWifiChannelUtilization);
+    }
+
+    /**
+     * This checks the connection attempt rate and recommends whether the connection attempt
+     * should be skipped or not. This attempts to rate limit the rate of connections to
+     * prevent us from flapping between networks and draining battery rapidly.
+     */
+    private boolean shouldSkipConnectionAttempt(Long timeMillis) {
+        Iterator<Long> attemptIter = mConnectionAttemptTimeStamps.iterator();
+        // First evict old entries from the queue.
+        while (attemptIter.hasNext()) {
+            Long connectionAttemptTimeMillis = attemptIter.next();
+            if ((timeMillis - connectionAttemptTimeMillis)
+                    > MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS) {
+                attemptIter.remove();
+            } else {
+                // This list is sorted by timestamps, so we can skip any more checks
+                break;
+            }
+        }
+        // If we've reached the max connection attempt rate, skip this connection attempt
+        return (mConnectionAttemptTimeStamps.size() >= MAX_CONNECTION_ATTEMPTS_RATE);
+    }
+
+    /**
+     * Add the current connection attempt timestamp to our queue of connection attempts.
+     */
+    private void noteConnectionAttempt(Long timeMillis) {
+        mConnectionAttemptTimeStamps.addLast(timeMillis);
+    }
+
+    /**
+     * This is used to clear the connection attempt rate limiter. This is done when the user
+     * explicitly tries to connect to a specified network.
+     */
+    private void clearConnectionAttemptTimeStamps() {
+        mConnectionAttemptTimeStamps.clear();
+    }
+
+    /**
+     * Attempt to connect to a network candidate.
+     *
+     * Based on the currently connected network, this menthod determines whether we should
+     * connect or roam to the network candidate recommended by WifiNetworkSelector.
+     */
+    private void connectToNetwork(WifiConfiguration candidate) {
+        ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();
+        if (scanResultCandidate == null) {
+            localLog("connectToNetwork: bad candidate - "  + candidate
+                    + " scanResult: " + scanResultCandidate);
+            return;
+        }
+
+        String targetBssid = scanResultCandidate.BSSID;
+        String targetAssociationId = candidate.SSID + " : " + targetBssid;
+
+        // Check if we are already connected or in the process of connecting to the target
+        // BSSID. mWifiInfo.mBSSID tracks the currently connected BSSID. This is checked just
+        // in case the firmware automatically roamed to a BSSID different from what
+        // WifiNetworkSelector selected.
+        if (targetBssid != null
+                && (targetBssid.equals(mLastConnectionAttemptBssid)
+                    || targetBssid.equals(mWifiInfo.getBSSID()))
+                && SupplicantState.isConnecting(mWifiInfo.getSupplicantState())) {
+            localLog("connectToNetwork: Either already connected "
+                    + "or is connecting to " + targetAssociationId);
+            return;
+        }
+
+        if (candidate.BSSID != null
+                && !candidate.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY)
+                && !candidate.BSSID.equals(targetBssid)) {
+            localLog("connecToNetwork: target BSSID " + targetBssid + " does not match the "
+                    + "config specified BSSID " + candidate.BSSID + ". Drop it!");
+            return;
+        }
+
+        long elapsedTimeMillis = mClock.getElapsedSinceBootMillis();
+        if (!mScreenOn && shouldSkipConnectionAttempt(elapsedTimeMillis)) {
+            localLog("connectToNetwork: Too many connection attempts. Skipping this attempt!");
+            mTotalConnectivityAttemptsRateLimited++;
+            return;
+        }
+        noteConnectionAttempt(elapsedTimeMillis);
+
+        mLastConnectionAttemptBssid = targetBssid;
+
+        WifiConfiguration currentConnectedNetwork = mConfigManager
+                .getConfiguredNetwork(mWifiInfo.getNetworkId());
+        String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" :
+                (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID());
+
+        if (currentConnectedNetwork != null
+                && (currentConnectedNetwork.networkId == candidate.networkId
+                //TODO(b/36788683): re-enable linked configuration check
+                /* || currentConnectedNetwork.isLinked(candidate) */)) {
+            // Framework initiates roaming only if firmware doesn't support
+            // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING}.
+            if (mConnectivityHelper.isFirmwareRoamingSupported()) {
+                // Keep this logging here for now to validate the firmware roaming behavior.
+                localLog("connectToNetwork: Roaming candidate - " + targetAssociationId + "."
+                        + " The actual roaming target is up to the firmware.");
+            } else {
+                localLog("connectToNetwork: Roaming to " + targetAssociationId + " from "
+                        + currentAssociationId);
+                mStateMachine.startRoamToNetwork(candidate.networkId, scanResultCandidate);
+            }
+        } else {
+            // Framework specifies the connection target BSSID if firmware doesn't support
+            // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING} or the
+            // candidate configuration contains a specified BSSID.
+            if (!mStateMachine.isActiveDualMode() && mConnectivityHelper.isFirmwareRoamingSupported() && (candidate.BSSID == null
+                      || candidate.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY))) {
+                targetBssid = ClientModeImpl.SUPPLICANT_BSSID_ANY;
+                localLog("connectToNetwork: Connect to " + candidate.SSID + ":" + targetBssid
+                        + " from " + currentAssociationId);
+            } else {
+                localLog("connectToNetwork: Connect to " + targetAssociationId + " from "
+                        + currentAssociationId);
+            }
+            mStateMachine.startConnectToNetwork(candidate.networkId, Process.WIFI_UID, targetBssid);
+        }
+    }
+
+    // Retrieve a value from single scanning schedule in ms
+    private int getScheduledSingleScanIntervalMs(int index) {
+        synchronized (mLock) {
+            if (mCurrentSingleScanScheduleSec == null) {
+                Log.e(TAG, "Invalid attempt to get schedule interval, Schedule array is null ");
+
+                // Use a default value
+                return DEFAULT_SCANNING_SCHEDULE_SEC[0] * 1000;
+            }
+
+            if (index >= mCurrentSingleScanScheduleSec.length) {
+                index = mCurrentSingleScanScheduleSec.length - 1;
+            }
+
+            return mCurrentSingleScanScheduleSec[index] * 1000;
+        }
+    }
+
+    // Set initial scan state
+    private void setInitialScanState(int state) {
+        Log.i(TAG, "SetInitialScanState to : " + state);
+        mInitialScanState = state;
+    }
+
+    /**
+     * Handler for screen state (on/off) changes
+     */
+    public void handleScreenStateChanged(boolean screenOn) {
+        localLog("handleScreenStateChanged: screenOn=" + screenOn);
+        mScreenOn = screenOn;
+    }
+
+    /**
+     * Save current miracast mode, it will be used to ignore
+     * connectivity scan during the time when miracast is enabled.
+     */
+    public void saveMiracastMode(int mode) {
+        Log.d(TAG,"saveMiracastMode: mode=" + mode);
+        mMiracastMode = mode;
+    }
+
+    /**
+     * Helper function that converts the WIFI_STATE_XXX constants to string
+     */
+    private static String stateToString(int state) {
+        switch (state) {
+            case WIFI_STATE_CONNECTED:
+                return "connected";
+            case WIFI_STATE_DISCONNECTED:
+                return "disconnected";
+            case WIFI_STATE_TRANSITIONING:
+                return "transitioning";
+            default:
+                return "unknown";
+        }
+    }
+
+    /**
+     * Handler for WiFi state (connected/disconnected) changes
+     */
+    public void handleConnectionStateChanged(int state) {
+        localLog("handleConnectionStateChanged: state=" + stateToString(state));
+
+        mWifiState = state;
+
+        // Reset BSSID of last connection attempt and kick off
+        // the watchdog timer if entering disconnected state.
+        if (mWifiState == WIFI_STATE_DISCONNECTED) {
+            mLastConnectionAttemptBssid = null;
+        }
+    }
+
+    /**
+     * Handler when user specifies a particular network to connect to
+     */
+    public void setUserConnectChoice(int netId) {
+        localLog("setUserConnectChoice: netId=" + netId);
+
+        mNetworkSelector.setUserConnectChoice(netId);
+    }
+
+    /**
+     * Handler to prepare for connection to a user or app specified network
+     */
+    public void prepareForForcedConnection(int netId) {
+        WifiConfiguration config = mConfigManager.getConfiguredNetwork(netId);
+        if (config == null) {
+            return;
+        }
+        localLog("prepareForForcedConnection: SSID=" + config.SSID);
+
+        clearConnectionAttemptTimeStamps();
+        mBssidBlocklistMonitor.clearBssidBlocklistForSsid(config.SSID);
+    }
+
+    /**
+     * Handler for on-demand connectivity scan
+     */
+    public void forceConnectivityScan(WorkSource workSource) {
+        if (!mWifiEnabled) return;
+        localLog("forceConnectivityScan in request of " + workSource);
+
+        mWaitForFullBandScanResults = true;
+    }
+
+    /**
+     * Helper method to populate WifiScanner handle. This is done lazily because
+     * WifiScanningService is started after WifiService.
+     */
+    private void retrieveWifiScanner() {
+        if (mScanner != null) return;
+        mScanner = mWifiInjector.getWifiScanner();
+        checkNotNull(mScanner);
+        // Register for all single scan results
+        mScanner.registerScanListener(new HandlerExecutor(mEventHandler), mAllSingleScanListener);
+    }
+
+    /**
+     * Start QtiWifiConnectivityManager
+     */
+    private void start() {
+        if (mRunning) return;
+        retrieveWifiScanner();
+        mConnectivityHelper.setInterfaceName(mStateMachine.getInterfaceName());
+        mConnectivityHelper.getFirmwareRoamingInfo();
+        mBssidBlocklistMonitor.clearBssidBlocklist();
+        mWifiChannelUtilization.init(mStateMachine.getWifiLinkLayerStats());
+
+        if (mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) {
+            setInitialScanState(INITIAL_SCAN_STATE_START);
+        }
+
+        mRunning = true;
+        mLatestCandidates = null;
+        mLatestCandidatesTimestampMs = 0;
+    }
+
+    /**
+     * Stop and reset QtiWifiConnectivityManager
+     */
+    private void stop() {
+        if (!mRunning) return;
+        mRunning = false;
+        mLastConnectionAttemptBssid = null;
+        mWaitForFullBandScanResults = false;
+        mLatestCandidates = null;
+        mLatestCandidatesTimestampMs = 0;
+    }
+
+    /**
+     * Update QtiWifiConnectivityManager running state
+     *
+     * Start QtiWifiConnectivityManager only if both Wifi and QtiWifiConnectivityManager
+     * are enabled, otherwise stop it.
+     */
+    private void updateRunningState() {
+        if (mWifiEnabled) {
+            localLog("Starting up QtiWifiConnectivityManager");
+            start();
+        } else {
+            localLog("Stopping QtiWifiConnectivityManager");
+            stop();
+        }
+    }
+
+    /**
+     * Inform WiFi is enabled for connection or not
+     */
+    public void setWifiEnabled(boolean enable) {
+        localLog("Set WiFi " + (enable ? "enabled" : "disabled"));
+
+        if (mWifiEnabled && !enable) {
+            mNetworkSelector.resetOnDisable();
+            mBssidBlocklistMonitor.clearBssidBlocklist();
+        }
+        mWifiEnabled = enable;
+        updateRunningState();
+    }
+
+    /**
+     * Dump the local logs.
+     */
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("Dump of QtiWifiConnectivityManager");
+        pw.println("QtiWifiConnectivityManager - Log Begin ----");
+        mLocalLog.dump(fd, pw, args);
+        pw.println("QtiWifiConnectivityManager - Log End ----");
+        mBssidBlocklistMonitor.dump(fd, pw, args);
+    }
+}
diff --git a/service/java/com/android/server/wifi/RandomizedMacStoreData.java b/service/java/com/android/server/wifi/RandomizedMacStoreData.java
index a03be60..05f8e20 100644
--- a/service/java/com/android/server/wifi/RandomizedMacStoreData.java
+++ b/service/java/com/android/server/wifi/RandomizedMacStoreData.java
@@ -21,6 +21,7 @@
 
 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
 import com.android.server.wifi.util.XmlUtil;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -102,6 +103,13 @@
         // Shared general store.
         return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
     }
+    @Override
+    public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+        // Shared general store.
+        if (staId == STA_SECONDARY)
+            return WifiConfigStore.QTI_STORE_FILE_SHARED_SECONDARY;
+        return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
+    }
 
     /**
      * An empty Map will be returned for null MAC address map.
diff --git a/service/java/com/android/server/wifi/SavedNetworkNominator.java b/service/java/com/android/server/wifi/SavedNetworkNominator.java
index 3c94bed..fe2fad3 100644
--- a/service/java/com/android/server/wifi/SavedNetworkNominator.java
+++ b/service/java/com/android/server/wifi/SavedNetworkNominator.java
@@ -28,6 +28,8 @@
 
 import java.util.List;
 
+import static android.net.wifi.WifiManager.STA_PRIMARY;
+
 /**
  * This class is the WifiNetworkSelector.NetworkNominator implementation for
  * saved networks.
@@ -89,6 +91,10 @@
                     WifiConfiguration currentNetwork, String currentBssid, boolean connected,
                     boolean untrustedNetworkAllowed,
                     @NonNull OnConnectableListener onConnectableListener) {
+	if (currentNetwork != null && currentNetwork.staId == STA_PRIMARY) {
+            mWifiConfigManager.addOrUpdateAutoConnectNetworks(currentNetwork.networkId,
+                                                              currentBssid, scanDetails);
+	}
         findMatchedSavedNetworks(scanDetails, onConnectableListener);
         findMatchedPasspointNetworks(scanDetails, onConnectableListener);
     }
@@ -113,7 +119,8 @@
              * {@link PasspointNetworkNominator} and {@link ScoredNetworkNominator}
              * respectively.
              */
-            if (network.isPasspoint() || network.isEphemeral()) {
+            if (network.isPasspoint()
+                   || (network.isEphemeral() && !network.isAutoConnectionEnabled)) {
                 continue;
             }
 
diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java
index c054b90..e622d3e 100644
--- a/service/java/com/android/server/wifi/ScanRequestProxy.java
+++ b/service/java/com/android/server/wifi/ScanRequestProxy.java
@@ -112,6 +112,7 @@
     private final RemoteCallbackList<IScanResultsCallback> mRegisteredScanResultsCallbacks;
     // Global scan listener for listening to all scan requests.
     private class GlobalScanListener implements WifiScanner.ScanListener {
+        private boolean mPartialScanResults;
         @Override
         public void onSuccess() {
             // Ignore. These will be processed from the scan request listener.
@@ -143,12 +144,24 @@
                 // Store the last scan results & send out the scan completion broadcast.
                 mLastScanResults.clear();
                 mLastScanResults.addAll(Arrays.asList(scanResults));
+                if (mPartialScanResults) {
+                    sendPartialScanResultBroadcast(true);
+                    return;
+	        }
                 sendScanResultBroadcast(true);
                 sendScanResultsAvailableToCallbacks();
             }
         }
 
         @Override
+        public void onPartialScanResults(WifiScanner.ScanData[] scanDatas) {
+            Log.d(TAG, "onPartialScanResults invoked");
+            mPartialScanResults = true;
+            onResults(scanDatas);
+            mPartialScanResults = false;
+        }
+
+        @Override
         public void onFullResult(ScanResult fullScanResult) {
             // Ignore for single scans.
         }
@@ -292,6 +305,16 @@
     }
 
     /**
+     * Helper method to send the partial scan request status broadcast.
+     */
+    private void sendPartialScanResultBroadcast(boolean scanSucceeded) {
+        Intent intent = new Intent(WifiManager.PARTIAL_SCAN_RESULTS_AVAILABLE_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    /**
      * Helper method to send the scan request failure broadcast to specified package.
      */
     private void sendScanResultFailureBroadcastToPackage(String packageName) {
@@ -464,7 +487,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..7f799e5 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -90,6 +90,7 @@
     private final WifiManager.SoftApCallback mSoftApCallback;
 
     private String mApInterfaceName;
+    private String mDataInterfaceName;
     private boolean mIfaceIsUp;
     private boolean mIfaceIsDestroyed;
 
@@ -110,6 +111,8 @@
 
     private List<WifiClient> mConnectedClients = new ArrayList<>();
     private boolean mTimeoutEnabled = false;
+    private String[] mdualApInterfaces;
+    private boolean mDualSapIfacesDestroyed = false;
 
     private final SarManager mSarManager;
 
@@ -195,6 +198,7 @@
                 softApConfig, mCurrentSoftApCapability);
         mWifiMetrics = wifiMetrics;
         mSarManager = sarManager;
+        mdualApInterfaces = new String[2];
         mWifiDiagnostics = wifiDiagnostics;
         mStateMachine = new SoftApStateMachine(looper);
         if (softApConfig != null) {
@@ -221,16 +225,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
@@ -325,7 +320,7 @@
             intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason);
         }
 
-        intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, mApInterfaceName);
+        intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, mDataInterfaceName);
         intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mApConfig.getTargetMode());
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
@@ -365,9 +360,9 @@
     private int setCountryCode() {
         int band = mApConfig.getSoftApConfiguration().getBand();
         if (TextUtils.isEmpty(mCountryCode)) {
-            if (band == SoftApConfiguration.BAND_5GHZ) {
+            if (band == SoftApConfiguration.BAND_5GHZ || band == SoftApConfiguration.BAND_6GHZ) {
                 // Country code is mandatory for 5GHz band.
-                Log.e(TAG, "Invalid country code, required for setting up soft ap in 5GHz");
+                Log.e(TAG, "Invalid country code, required for setting up soft ap in 5GHz/6GHz");
                 return ERROR_GENERIC;
             }
             // Absence of country code is not fatal for 2Ghz & Any band options.
@@ -376,10 +371,10 @@
 
         if (!mWifiNative.setCountryCodeHal(
                 mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT))) {
-            if (band == SoftApConfiguration.BAND_5GHZ) {
+            if (band == SoftApConfiguration.BAND_5GHZ || band == SoftApConfiguration.BAND_6GHZ) {
                 // Return an error if failed to set country code when AP is configured for
                 // 5GHz band.
-                Log.e(TAG, "Failed to set country code, required for setting up soft ap in 5GHz");
+                Log.e(TAG, "Failed to set country code, required for setting up soft ap in 5GHz/6GHz");
                 return ERROR_GENERIC;
             }
             // Failure to set country code is not fatal for other band options.
@@ -417,10 +412,10 @@
 
         boolean acsEnabled = mCurrentSoftApCapability.areFeaturesSupported(
                 SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD);
-
         result = ApConfigUtil.updateApChannelConfig(
                 mWifiNative, mContext.getResources(), mCountryCode, localConfigBuilder, config,
                 acsEnabled);
+
         if (result != SUCCESS) {
             Log.e(TAG, "Failed to update AP band and channel");
             return result;
@@ -449,14 +444,37 @@
     }
 
     /**
+     * Disconnect a client with specified mac address.
+     * Using broadcast mac to disconnect all clients.
+     */
+    private void forceClientDisconnect(@NonNull String ifaceName,
+            @NonNull MacAddress client, int reasonCode) {
+        if (mWifiApConfigStore.getDualSapStatus()) {
+            if (!mDualSapIfacesDestroyed) {
+                if(!TextUtils.isEmpty(mdualApInterfaces[0])) {
+                    mWifiNative.forceClientDisconnect(
+                            mdualApInterfaces[0], client, reasonCode);
+                }
+                if(!TextUtils.isEmpty(mdualApInterfaces[1])) {
+                    mWifiNative.forceClientDisconnect(
+                            mdualApInterfaces[1], client, reasonCode);
+                }
+            }
+        } else {
+            if (!TextUtils.isEmpty(ifaceName)) {
+                mWifiNative.forceClientDisconnect(ifaceName, client, reasonCode);
+            }
+        }
+    }
+
+    /**
      * Disconnect all connected clients on active softap interface(s).
      * This is usually done just before stopSoftAp().
      */
     private void disconnectAllClients() {
-        for (WifiClient client : mConnectedClients) {
-            mWifiNative.forceClientDisconnect(mApInterfaceName, client.getMacAddress(),
-                    SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED);
-        }
+        forceClientDisconnect(mApInterfaceName,
+                MacAddress.fromString("ff:ff:ff:ff:ff:ff"),
+                SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED);
     }
 
     /**
@@ -464,6 +482,11 @@
      */
     private void stopSoftAp() {
         disconnectAllClients();
+        if (mWifiApConfigStore.getDualSapStatus() && !mDualSapIfacesDestroyed) {
+            mDualSapIfacesDestroyed = true;
+            mWifiNative.teardownInterface(mdualApInterfaces[0]);
+            mWifiNative.teardownInterface(mdualApInterfaces[1]);
+        }
         mWifiDiagnostics.stopLogging(mApInterfaceName);
         mWifiNative.teardownInterface(mApInterfaceName);
         Log.d(TAG, "Soft AP is stopped");
@@ -477,7 +500,7 @@
 
         if (mBlockedClientList.contains(newClient.getMacAddress())) {
             Log.d(TAG, "Force disconnect for client: " + newClient + "in blocked list");
-            mWifiNative.forceClientDisconnect(
+            forceClientDisconnect(
                     mApInterfaceName, newClient.getMacAddress(),
                     WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
             return false;
@@ -487,7 +510,7 @@
             mSoftApCallback.onBlockedClientConnecting(newClient,
                     WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
             Log.d(TAG, "Force disconnect for unauthorized client: " + newClient);
-            mWifiNative.forceClientDisconnect(
+            forceClientDisconnect(
                     mApInterfaceName, newClient.getMacAddress(),
                     WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
             return false;
@@ -499,7 +522,7 @@
 
         if (mConnectedClients.size() >= maxConfig) {
             Log.i(TAG, "No more room for new client:" + newClient);
-            mWifiNative.forceClientDisconnect(
+            forceClientDisconnect(
                     mApInterfaceName, newClient.getMacAddress(),
                     WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
             mSoftApCallback.onBlockedClientConnecting(newClient,
@@ -517,6 +540,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;
@@ -526,6 +550,7 @@
         public static final int CMD_SOFT_AP_CHANNEL_SWITCHED = 9;
         public static final int CMD_UPDATE_CAPABILITY = 10;
         public static final int CMD_UPDATE_CONFIG = 11;
+        public static final int CMD_DUAL_SAP_INTERFACE_DESTROYED = 50;
 
         private final State mIdleState = new IdleState();
         private final State mStartedState = new StartedState();
@@ -533,31 +558,187 @@
         private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() {
             @Override
             public void onDestroyed(String ifaceName) {
-                if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) {
+                if (mDataInterfaceName != null && mDataInterfaceName.equals(ifaceName)) {
                     sendMessage(CMD_INTERFACE_DESTROYED);
                 }
             }
 
             @Override
             public void onUp(String ifaceName) {
-                if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) {
+                if (mDataInterfaceName != null && mDataInterfaceName.equals(ifaceName)) {
                     sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);
                 }
             }
 
             @Override
             public void onDown(String ifaceName) {
-                if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) {
+                if (mDataInterfaceName != null && mDataInterfaceName.equals(ifaceName)) {
                     sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0);
                 }
             }
         };
 
+        private final InterfaceCallback mWifiNativeDualIfaceCallback = new InterfaceCallback() {
+            @Override
+            public void onDestroyed(String ifaceName) {
+                sendMessage(CMD_DUAL_SAP_INTERFACE_DESTROYED, ifaceName);
+            }
+
+            @Override
+            public void onUp(String ifaceName) { }
+
+            @Override
+            public void onDown(String ifaceName) { }
+        };
+
+        /* Utility API to generate a temporary MAC for 2nd interface when starting Softap on 2 interfaces.
+         * This flips the last bit of MAC address which was assigned to 1st interface.
+         */
+        private SoftApConfiguration randomizeMacOnSecondInterface(SoftApConfiguration config) {
+            if (config.getBssid() == null) return config;
+            byte[] macBytes = config.getBssid().toByteArray();
+            macBytes[5] ^= 1;
+            MacAddress mac = MacAddress.fromBytes(macBytes);
+
+            return new SoftApConfiguration.Builder(config).setBssid(mac).build();
+        }
+
+        private boolean validateDualSapSetupResult(int result) {
+            if (result != SUCCESS) {
+                int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;
+                if (result == ERROR_NO_CHANNEL) {
+                    failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+                }
+                updateApState(WifiManager.WIFI_AP_STATE_FAILED,
+                              WifiManager.WIFI_AP_STATE_ENABLING,
+                              failureReason);
+                stopSoftAp();
+                mWifiMetrics.incrementSoftApStartResult(false, failureReason);
+                mModeListener.onStartFailure();
+                return false;
+            }
+            if (!mWifiNative.setInterfaceUp(mApInterfaceName)) {
+               Log.e(TAG, "Failed to set interface up " +mApInterfaceName);
+               return false;
+            }
+
+            return true;
+        }
+
+        private boolean setupInterfacesForDualSoftApMode() {
+            mdualApInterfaces[0] = mWifiNative.setupInterfaceForSoftApMode(
+                    mWifiNativeDualIfaceCallback);
+            mdualApInterfaces[1] = mWifiNative.setupInterfaceForSoftApMode(
+                    mWifiNativeDualIfaceCallback);
+
+            String bridgeIfacename = mWifiNative.setupInterfaceForBridgeMode(
+                    mWifiNativeInterfaceCallback);
+
+            mApInterfaceName = bridgeIfacename;
+            if (TextUtils.isEmpty(mdualApInterfaces[0]) ||
+                    TextUtils.isEmpty(mdualApInterfaces[1]) ||
+                    TextUtils.isEmpty(mApInterfaceName)) {
+                Log.e(TAG, "setup failure when creating dual ap interface(s).");
+                stopSoftAp();
+                updateApState(WifiManager.WIFI_AP_STATE_FAILED,
+                        WifiManager.WIFI_AP_STATE_DISABLED,
+                        WifiManager.SAP_START_FAILURE_GENERAL);
+                mWifiMetrics.incrementSoftApStartResult(false,
+                        WifiManager.SAP_START_FAILURE_GENERAL);
+                mModeListener.onStartFailure();
+                return false;
+            }
+            mDataInterfaceName = mWifiNative.getFstDataInterfaceName();
+            if (TextUtils.isEmpty(mDataInterfaceName)) {
+                mDataInterfaceName = mApInterfaceName;
+            }
+            updateApState(WifiManager.WIFI_AP_STATE_ENABLING,
+                    WifiManager.WIFI_AP_STATE_DISABLED, 0);
+
+            return true;
+        }
+
+        /**
+         * Start Dual band soft AP.
+         */
+        private boolean setupForDualBandSoftApMode(SoftApConfiguration config) {
+            if (!setupInterfacesForDualSoftApMode())
+                return false;
+
+            SoftApConfiguration localConfig;
+            SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config);
+            String bridgeIfacename = mApInterfaceName;
+            SoftApModeConfiguration savedApConfig = mApConfig;
+
+            mApInterfaceName = mdualApInterfaces[0];
+            localConfig = configBuilder.setBand(SoftApConfiguration.BAND_2GHZ).build();
+            mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), localConfig,
+                    mCurrentSoftApCapability);
+            int result = startSoftAp();
+            if (result == SUCCESS) {
+                localConfig = configBuilder.setBand(SoftApConfiguration.BAND_5GHZ).build();
+                localConfig = randomizeMacOnSecondInterface(localConfig);
+                mApInterfaceName = mdualApInterfaces[1];
+                mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), localConfig,
+                        mCurrentSoftApCapability);
+                result = startSoftAp();
+            }
+
+            mApInterfaceName = bridgeIfacename;
+            mApConfig = savedApConfig;
+
+            return validateDualSapSetupResult(result);
+        }
+
+        /**
+         * Start OWE transition soft AP.
+         */
+        private boolean setupForOweTransitionSoftApMode(SoftApConfiguration config) {
+            if (!setupInterfacesForDualSoftApMode())
+                return false;
+
+            SoftApConfiguration.Builder oweConfigBuilder = new SoftApConfiguration.Builder(config);
+            SoftApConfiguration.Builder openConfigBuilder = new SoftApConfiguration.Builder(config);
+
+            String bridgeIfacename = mApInterfaceName;
+            SoftApModeConfiguration savedApConfig = mApConfig;
+
+            mApInterfaceName = mdualApInterfaces[0];
+            oweConfigBuilder.setOweTransIfaceName(mdualApInterfaces[1]);
+
+            // hashCode() generates integer hash for given string
+            // As maximum string size of a integer is 12 bytes SSID size never crosses 32 bytes
+            oweConfigBuilder.setSsid("OWE_" + config.getSsid().hashCode());
+            oweConfigBuilder.setHiddenSsid(true);
+            SoftApConfiguration oweConfig = oweConfigBuilder.build();
+            Log.i(TAG, "Generated OWE SSID: " + oweConfig.getSsid());
+            mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), oweConfig,
+                    mCurrentSoftApCapability);
+            int result = startSoftAp();
+            if (result == SUCCESS) {
+                mApInterfaceName = mdualApInterfaces[1];
+                openConfigBuilder.setOweTransIfaceName(mdualApInterfaces[0]);
+                openConfigBuilder.setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN);
+                SoftApConfiguration openConfig = openConfigBuilder.build();
+                openConfig = randomizeMacOnSecondInterface(openConfig);
+                mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(), openConfig,
+                        mCurrentSoftApCapability);
+                result = startSoftAp();
+            }
+
+            mApInterfaceName = bridgeIfacename;
+            mApConfig = savedApConfig;
+
+            return validateDualSapSetupResult(result);
+        }
+
         SoftApStateMachine(Looper looper) {
             super(TAG, looper);
 
+            // CHECKSTYLE:OFF IndentationCheck
             addState(mIdleState);
-            addState(mStartedState);
+                addState(mStartedState, mIdleState);
+            // CHECKSTYLE:ON IndentationCheck
 
             setInitialState(mIdleState);
             start();
@@ -567,14 +748,42 @@
             @Override
             public void enter() {
                 mApInterfaceName = null;
+                mDataInterfaceName = null;
                 mIfaceIsUp = false;
                 mIfaceIsDestroyed = false;
             }
 
             @Override
+            public void exit() {
+                mModeListener.onStopped();
+            }
+
+            @Override
             public boolean processMessage(Message message) {
                 switch (message.what) {
+                    case CMD_STOP:
+                        mStateMachine.quitNow();
+                        break;
                     case CMD_START:
+                        SoftApConfiguration config = (SoftApConfiguration) message.obj;
+                        if (config == null)
+                            config = mApConfig.getSoftApConfiguration();
+                        if (config != null && config.getBand() == SoftApConfiguration.BAND_DUAL) {
+                            if (!setupForDualBandSoftApMode(config)) {
+                                Log.d(TAG, "Dual band sap start failed");
+                                break;
+                            }
+                            transitionTo(mStartedState);
+                            break;
+                        } else if (config != null && config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OWE) {
+                            if (!setupForOweTransitionSoftApMode(config)) {
+                                Log.d(TAG, "OWE transition sap start failed");
+                                break;
+                            }
+                            transitionTo(mStartedState);
+                            break;
+                        }
+
                         mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(
                                 mWifiNativeInterfaceCallback);
                         if (TextUtils.isEmpty(mApInterfaceName)) {
@@ -587,6 +796,11 @@
                             mModeListener.onStartFailure();
                             break;
                         }
+                        mDataInterfaceName = mWifiNative.getFstDataInterfaceName();
+                        if (TextUtils.isEmpty(mDataInterfaceName)) {
+                            mDataInterfaceName = mApInterfaceName;
+                        }
+
                         mSoftApNotifier.dismissSoftApShutDownTimeoutExpiredNotification();
                         updateApState(WifiManager.WIFI_AP_STATE_ENABLING,
                                 WifiManager.WIFI_AP_STATE_DISABLED, 0);
@@ -639,7 +853,7 @@
             private WakeupMessage mSoftApTimeoutMessage;
 
             private void scheduleTimeoutMessage() {
-                if (!mTimeoutEnabled || mConnectedClients.size() != 0) {
+                if (!mTimeoutEnabled) {
                     cancelTimeoutMessage();
                     return;
                 }
@@ -685,7 +899,7 @@
                               || (mApConfig.getSoftApConfiguration().isClientControlByUserEnabled()
                               && !mAllowedClientList.contains(client.getMacAddress()))) {
                         Log.d(TAG, "Force disconnect for not allowed client: " + client);
-                        mWifiNative.forceClientDisconnect(
+                        forceClientDisconnect(
                                 mApInterfaceName, client.getMacAddress(),
                                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
                         targetDisconnectClientNumber--;
@@ -701,7 +915,7 @@
                         WifiClient allowedClient = allowedClientIterator.next();
                         Log.d(TAG, "Force disconnect for client due to no more room: "
                                 + allowedClient);
-                        mWifiNative.forceClientDisconnect(
+                        forceClientDisconnect(
                                 mApInterfaceName, allowedClient.getMacAddress(),
                                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
                         targetDisconnectClientNumber--;
@@ -810,6 +1024,7 @@
                 mIfaceIsUp = false;
                 mIfaceIsDestroyed = false;
                 onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName));
+                onUpChanged(mWifiNative.isInterfaceUp(mDataInterfaceName));
 
                 Handler handler = mStateMachine.getHandler();
                 mSoftApTimeoutMessage = new WakeupMessage(mContext, handler,
@@ -850,11 +1065,10 @@
 
                 mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_DISABLED);
                 mApInterfaceName = null;
+                mDataInterfaceName = null;
                 mIfaceIsUp = false;
                 mIfaceIsDestroyed = false;
                 mRole = ROLE_UNSPECIFIED;
-                mStateMachine.quitNow();
-                mModeListener.onStopped();
                 setSoftApChannel(0, SoftApInfo.CHANNEL_WIDTH_INVALID);
             }
 
@@ -908,6 +1122,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;
@@ -925,14 +1149,36 @@
                         Log.i(TAG, "Timeout message received. Stopping soft AP.");
                         updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
                                 WifiManager.WIFI_AP_STATE_ENABLED, 0);
-                        transitionTo(mIdleState);
+                        quitNow();
                         break;
                     case CMD_INTERFACE_DESTROYED:
-                        Log.d(TAG, "Interface was cleanly destroyed.");
+                        //teardown Dual SAP interfaces if required
+                        if (mWifiApConfigStore.getDualSapStatus() && !mDualSapIfacesDestroyed) {
+                            Log.d(TAG, "Bridge inteface destroyed, Teardown dual intefaces");
+                            mDualSapIfacesDestroyed = true;
+                            mWifiNative.teardownInterface(mdualApInterfaces[0]);
+                            mWifiNative.teardownInterface(mdualApInterfaces[1]);
+                        }
+                        Log.d(TAG, "Interface(s) was cleanly destroyed.");
                         updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
                                 WifiManager.WIFI_AP_STATE_ENABLED, 0);
                         mIfaceIsDestroyed = true;
-                        transitionTo(mIdleState);
+                        quitNow();
+                        break;
+                    case CMD_DUAL_SAP_INTERFACE_DESTROYED:
+                        // one of the dual interface is destroyed by native layers. trigger full cleanup.
+                        if (!mDualSapIfacesDestroyed) {
+                            String ifaceName = (String) message.obj;
+                            Log.d(TAG, "One of Dual interface ("+ifaceName+") destroyed. trigger cleanup");
+                            // teardown other dual interface and bridge interface.
+                            mDualSapIfacesDestroyed = true;
+                            if (ifaceName.equals(mdualApInterfaces[0])) {
+                               mWifiNative.teardownInterface(mdualApInterfaces[1]);
+                            } else if (ifaceName.equals(mdualApInterfaces[1])) {
+                               mWifiNative.teardownInterface(mdualApInterfaces[0]);
+                            }
+                            mWifiNative.teardownInterface(mApInterfaceName);
+                        }
                         break;
                     case CMD_FAILURE:
                         Log.w(TAG, "hostapd failure, stop and report failure");
@@ -944,7 +1190,7 @@
                                 WifiManager.SAP_START_FAILURE_GENERAL);
                         updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
                                 WifiManager.WIFI_AP_STATE_FAILED, 0);
-                        transitionTo(mIdleState);
+                        quitNow();
                         break;
                     case CMD_UPDATE_CAPABILITY:
                         // Capability should only changed by carrier requirement. Only apply to
@@ -993,7 +1239,8 @@
                                     mApConfig.getTargetMode());
                         } else {
                             Log.d(TAG, "Ignore the config: " + newConfig
-                                    + " update since it requires restart");
+                                    + " update since it requires restart"
+                                    + " \n CurrentConfig: " + currentConfig);
                         }
                         break;
                     default:
diff --git a/service/java/com/android/server/wifi/SoftApStoreData.java b/service/java/com/android/server/wifi/SoftApStoreData.java
index ae9a40a..416f374 100644
--- a/service/java/com/android/server/wifi/SoftApStoreData.java
+++ b/service/java/com/android/server/wifi/SoftApStoreData.java
@@ -303,4 +303,9 @@
     public @WifiConfigStore.StoreFileId int getStoreFileId() {
         return WifiConfigStore.STORE_FILE_SHARED_SOFTAP; // Shared softap store.
     }
+
+    @Override
+    public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+        return WifiConfigStore.STORE_FILE_SHARED_SOFTAP; // Shared softap store.
+    }
 }
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
index 92ba43b..dc10244 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,25 +152,32 @@
     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 =
                     supplicantHidlStateToFrameworkState(newState);
-            WifiSsid wifiSsid =
-                    WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
+            WifiSsid wifiSsid = // wifigbk++
+                        WifiGbk.createWifiSsidFromByteArray(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) {
@@ -238,15 +251,23 @@
     public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) {
         synchronized (mLock) {
             mStaIfaceHal.logCallback("onDisconnected");
-            if (mStaIfaceHal.isVerboseLoggingEnabled()) {
-                Log.e(TAG, "onDisconnected 4way=" + mStateIsFourway
+            Log.i(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
+                        || mStateBeforeDisconnect == State.ASSOCIATED)
+                        && 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,
@@ -259,9 +280,9 @@
         synchronized (mLock) {
             mStaIfaceHal.logCallback("onAssociationRejected");
             boolean isWrongPwd = false;
+            boolean broadcastAssociationRejectionEvent = true;
             WifiConfiguration curConfiguration =
                     mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
-
             if (curConfiguration != null) {
                 if (!timedOut) {
                     Log.d(TAG, "flush PMK cache due to association rejection for config id "
@@ -273,14 +294,16 @@
                 // (unspecified failure). In SAE networks, the password authentication
                 // is not related to the 4-way handshake. In this case, we will send an
                 // authentication failure event up.
+                // For WEP password error: not check status code to avoid IoT issues with AP.
                 if (statusCode == StatusCode.UNSPECIFIED_FAILURE
                         && WifiConfigurationUtil.isConfigForSaeNetwork(curConfiguration)) {
                     mStaIfaceHal.logCallback("SAE incorrect password");
                     isWrongPwd = true;
-                } else if (statusCode == StatusCode.CHALLENGE_FAIL
-                        && WifiConfigurationUtil.isConfigForWepNetwork(curConfiguration)) {
+                } else if (WifiConfigurationUtil.isConfigForWepNetwork(curConfiguration)) {
                     mStaIfaceHal.logCallback("WEP incorrect password");
                     isWrongPwd = true;
+                    // Not broadcast ASSOC REJECT to avoid bssid get blacklisted.
+                    broadcastAssociationRejectionEvent = false;
                 }
             }
 
@@ -288,10 +311,12 @@
                 mWifiMonitor.broadcastAuthenticationFailureEvent(
                         mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
             }
-            mWifiMonitor
-                    .broadcastAssociationRejectionEvent(
-                            mIfaceName, statusCode, timedOut,
-                            NativeUtil.macAddressFromByteArray(bssid));
+            if (broadcastAssociationRejectionEvent) {
+                mWifiMonitor
+                        .broadcastAssociationRejectionEvent(
+                                mIfaceName, statusCode, timedOut,
+                                NativeUtil.macAddressFromByteArray(bssid));
+            }
         }
     }
 
@@ -369,4 +394,5 @@
             mStaIfaceHal.logCallback("onExtRadioWorkTimeout");
         }
     }
+
 }
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..c779512 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
@@ -15,20 +15,15 @@
  */
 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;
+import android.util.Pair;
 
 abstract class SupplicantStaIfaceCallbackV1_3Impl extends
         android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback.Stub {
@@ -37,7 +32,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 +51,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 +88,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 +231,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 +344,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..fc37666 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -25,10 +25,20 @@
 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
 
+import static android.net.wifi.WifiDppConfig.DppResult.DPP_EVENT_AUTH_SUCCESS;
+import static android.net.wifi.WifiDppConfig.DppResult.DPP_EVENT_CONF;
+
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.wifi.V1_0.WifiChannelWidthInMhz;
 import android.hardware.wifi.supplicant.V1_0.ISupplicant;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendor;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorIface;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorStaIface;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorNetwork;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorStaNetwork;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorStaIfaceCallback;
+import vendor.qti.hardware.wifi.supplicant.V2_1.WifiGenerationStatus;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
@@ -45,8 +55,12 @@
 import android.hidl.manager.V1_0.IServiceNotification;
 import android.net.MacAddress;
 import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiAnnotations.WifiStandard;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiSsid;
+import android.net.wifi.WifiDppConfig;
+import android.net.wifi.WifiDppConfig.DppResult;
 import android.os.Handler;
 import android.os.IHwBinder.DeathRecipient;
 import android.os.RemoteException;
@@ -55,6 +69,7 @@
 import android.util.MutableBoolean;
 import android.util.MutableInt;
 import android.util.Pair;
+import android.util.MutableInt;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.wifi.WifiNative.DppEventCallback;
@@ -106,11 +121,17 @@
     // Supplicant HAL interface objects
     private IServiceManager mIServiceManager = null;
     private ISupplicant mISupplicant;
+    private ISupplicantVendor mISupplicantVendor; // Supplicant Vendor HAL interface objects
     private HashMap<String, ISupplicantStaIface> mISupplicantStaIfaces = new HashMap<>();
+    private HashMap<String, ISupplicantVendorStaIface> mISupplicantVendorStaIfaces = new HashMap<>();
     private HashMap<String, ISupplicantStaIfaceCallback> mISupplicantStaIfaceCallbacks =
             new HashMap<>();
+    private HashMap<String, ISupplicantVendorStaIfaceCallback> mISupplicantVendorStaIfaceCallbacks =
+            new HashMap<>();
     private HashMap<String, SupplicantStaNetworkHal> mCurrentNetworkRemoteHandles = new HashMap<>();
     private HashMap<String, WifiConfiguration> mCurrentNetworkLocalConfigs = new HashMap<>();
+    private HashMap<String, ArrayList<Pair<SupplicantStaNetworkHal, WifiConfiguration>>>
+            mLinkedNetworkLocalAndRemoteConfigs = new HashMap<>();
     @VisibleForTesting
     HashMap<Integer, PmkCacheStoreData> mPmkCacheEntries = new HashMap<>();
     private SupplicantDeathEventHandler mDeathEventHandler;
@@ -180,6 +201,14 @@
         }
     }
 
+    private final DeathRecipient mSupplicantVendorDeathRecipient =
+            cookie -> {
+                synchronized (mLock) {
+                    Log.w(TAG, "ISupplicantVendor/ISupplicantVendorStaIface died: cookie=" + cookie);
+                    supplicantvendorServiceDiedHandler();
+                }
+            };
+
     public SupplicantStaIfaceHal(Context context, WifiMonitor monitor,
                                  FrameworkFacade frameworkFacade, Handler handler,
                                  Clock clock, WifiMetrics wifiMetrics) {
@@ -238,7 +267,9 @@
                 Log.i(TAG, "Registering ISupplicant service ready callback.");
             }
             mISupplicant = null;
+            mISupplicantVendor = null;
             mISupplicantStaIfaces.clear();
+            mISupplicantVendorStaIfaces.clear();
             if (mIServiceManager != null) {
                 // Already have an IServiceManager and serviceNotification registered, don't
                 // don't register another.
@@ -256,7 +287,7 @@
                 /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
                    exists */
                 if (!mIServiceManager.registerForNotifications(
-                        ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) {
+                        ISupplicant.kInterfaceName, "default", mServiceNotificationCallback)) {
                     Log.e(TAG, "Failed to register for notifications to "
                             + ISupplicant.kInterfaceName);
                     mIServiceManager = null; // Will need to register a new ServiceNotification
@@ -289,6 +320,23 @@
         }
     }
 
+    private boolean linkToSupplicantVendorDeath() {
+        synchronized (mLock) {
+            if (mISupplicantVendor == null) return false;
+            try {
+                if (!mISupplicantVendor.linkToDeath(mSupplicantVendorDeathRecipient, 0)) {
+                    Log.wtf(TAG, "Error on linkToDeath on ISupplicantVendor");
+                    supplicantvendorServiceDiedHandler();
+                    return false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.linkToDeath exception", e);
+                return false;
+            }
+            return true;
+        }
+    }
+
     private boolean initSupplicantService() {
         synchronized (mLock) {
             try {
@@ -300,6 +348,7 @@
                 Log.e(TAG, "ISupplicant.getService exception: " + e);
                 return false;
             }
+
             if (mISupplicant == null) {
                 Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
                 return false;
@@ -308,9 +357,52 @@
                 return false;
             }
         }
+        if (!initSupplicantVendorService())
+            Log.e(TAG, "Failed to init SupplicantVendor service");
         return true;
     }
 
+    private boolean initSupplicantVendorService() {
+        synchronized (mLock) {
+            try {
+            // Discovering supplicantvendor service
+                mISupplicantVendor = getSupplicantVendorMockable();
+                if (mISupplicantVendor != null) {
+                   Log.e(TAG, "Discover ISupplicantVendor service successfull");
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.getService exception: " + e);
+                return false;
+            }
+            if (mISupplicantVendor == null) {
+                Log.e(TAG, "Got null ISupplicantVendor service. Stopping supplicantVendor HIDL startup");
+                return false;
+            }
+            // check mISupplicantVendor service and trigger death service
+            if (!linkToSupplicantVendorDeath()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean linkToSupplicantVendorStaIfaceDeath(ISupplicantVendorStaIface iface) {
+        synchronized (mLock) {
+            if (iface == null) return false;
+            try {
+                if (!iface.linkToDeath(mSupplicantVendorDeathRecipient, 0)) {
+                    Log.wtf(TAG, "Error on linkToDeath on ISupplicantVendorStaIface");
+                    supplicantvendorServiceDiedHandler();
+                    return false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendorStaIface.linkToDeath exception", e);
+                return false;
+            }
+            return true;
+        }
+    }
+
     protected int getCurrentNetworkId(@NonNull String ifaceName) {
         synchronized (mLock) {
             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
@@ -416,32 +508,143 @@
      * @return true on success, false otherwise.
      */
     public boolean setupIface(@NonNull String ifaceName) {
-        final String methodStr = "setupIface";
-        if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) != null) return false;
-        ISupplicantIface ifaceHwBinder;
+        synchronized (mLock) {
+            final String methodStr = "setupIface";
+            if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) != null) return false;
+            if (!checkSupplicantAndLogFailure(methodStr)) return false;
+            ISupplicantIface ifaceHwBinder;
 
-        if (isV1_1()) {
-            ifaceHwBinder = addIfaceV1_1(ifaceName);
-        } else {
-            ifaceHwBinder = getIfaceV1_0(ifaceName);
+            if (isV1_1()) {
+                ifaceHwBinder = addIfaceV1_1(ifaceName);
+            } else {
+                ifaceHwBinder = getIfaceV1_0(ifaceName);
+            }
+            if (ifaceHwBinder == null) {
+                Log.e(TAG, "setupIface got null iface");
+                return false;
+            }
+
+            try {
+                ISupplicantStaIface iface = setupStaIface(ifaceName, ifaceHwBinder);
+                mISupplicantStaIfaces.put(ifaceName, iface);
+            } catch (RemoteException e) {
+                loge("setup StaIface failed: " + e.toString());
+                return false;
+            }
+
+            SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName);
+            /** creation vendor sta iface binder */
+            if (!vendor_setupIface(ifaceName, callback))
+                Log.e(TAG, "Failed to create vendor setupiface");
+
+            return true;
         }
-        if (ifaceHwBinder == null) {
-            Log.e(TAG, "setupIface got null iface");
+    }
+
+    /**
+     * Setup a Vendor STA interface for the specified iface name.
+     *
+     * @param ifaceName Name of the interface.
+     * @return true on success, false otherwise.
+     */
+    public boolean vendor_setupIface(@NonNull String ifaceName, SupplicantStaIfaceHalCallback callback) {
+        final String methodStr = "vendor_setupIface";
+        if (checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr) != null) {
+            Log.e(TAG, "Already created vendor setupinterface");
+            return true;
+        }
+        ISupplicantVendorIface Vendor_ifaceHwBinder = null;
+
+        if (isVendor_2_0()) {
+            Log.e(TAG, "Try to get Vendor HIDL@2.0 interface");
+            Vendor_ifaceHwBinder = getVendorIfaceV2_0(ifaceName);
+        }
+        if (Vendor_ifaceHwBinder == null) {
+            Log.e(TAG, "Failed to get vendor iface binder");
             return false;
         }
 
-        try {
-            ISupplicantStaIface iface = setupStaIface(ifaceName, ifaceHwBinder);
-            mISupplicantStaIfaces.put(ifaceName, iface);
-        } catch (RemoteException e) {
-            loge("setup StaIface failed: " + e.toString());
+        ISupplicantVendorStaIface vendor_iface = getVendorStaIfaceMockable(Vendor_ifaceHwBinder);
+        if (vendor_iface == null) {
+            Log.e(TAG, "Failed to get ISupplicantVendorStaIface proxy");
+            return false;
+        }
+        else
+            Log.e(TAG, "Successful get Vendor sta interface");
+
+        if (!linkToSupplicantVendorStaIfaceDeath(vendor_iface)) {
             return false;
         }
 
+        if (vendor_iface != null) {
+            ISupplicantVendorStaIfaceCallback vendorcallback =
+                    new SupplicantVendorStaIfaceHalCallback(ifaceName, callback);
+            if (!registerVendorCallback(vendor_iface, vendorcallback)) {
+                Log.e(TAG, "Failed to register Vendor callback");
+            } else {
+                mISupplicantVendorStaIfaces.put(ifaceName, vendor_iface);
+                if (vendorcallback != null)
+                    mISupplicantVendorStaIfaceCallbacks.put(ifaceName, vendorcallback);
+            }
+        }
         return true;
     }
 
     /**
+     * Get a Vendor STA interface for the specified iface name.
+     *
+     * @param ifaceName Name of the interface.
+     * @return true on success, false otherwise.
+     */
+    private ISupplicantVendorIface getVendorIfaceV2_0(@NonNull String ifaceName) {
+        synchronized (mLock) {
+            /** List all supplicant Ifaces */
+            final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
+            try {
+                final String methodStr = "listVendorInterfaces";
+                if (!checkSupplicantVendorAndLogFailure(methodStr)) return null;
+                mISupplicantVendor.listVendorInterfaces((SupplicantStatus status,
+                                             ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
+                    if (!checkSupplicantVendorStatusAndLogFailure(status, methodStr)) {
+                        return;
+                    }
+                    supplicantIfaces.addAll(ifaces);
+                });
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.listInterfaces exception: " + e);
+                supplicantvendorServiceDiedHandler();
+                return null;
+            }
+            if (supplicantIfaces.size() == 0) {
+                Log.e(TAG, "Got zero HIDL supplicant vendor ifaces. Stopping supplicant vendor HIDL startup.");
+                return null;
+            }
+            Mutable<ISupplicantVendorIface> supplicantVendorIface = new Mutable<>();
+            for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
+                if (ifaceInfo.type == IfaceType.STA && ifaceName.equals(ifaceInfo.name)) {
+                    try {
+                        final String methodStr = "getVendorInterface";
+                        if (!checkSupplicantVendorAndLogFailure(methodStr)) return null;
+                        mISupplicantVendor.getVendorInterface(ifaceInfo,
+                                (SupplicantStatus status, ISupplicantVendorIface iface) -> {
+                                    if (!checkSupplicantVendorStatusAndLogFailure(status, methodStr)) {
+                                        return;
+                                    }
+                                    supplicantVendorIface.value = iface;
+                                });
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "ISupplicantVendor.getInterface exception: " + e);
+                        supplicantvendorServiceDiedHandler();
+                        return null;
+                    }
+                    break;
+                }
+            }
+            return supplicantVendorIface.value;
+        }
+    }
+
+    /**
      * Get a STA interface for the specified iface name.
      *
      * @param ifaceName Name of the interface.
@@ -449,12 +652,14 @@
      */
     private ISupplicantIface getIfaceV1_0(@NonNull String ifaceName) {
         synchronized (mLock) {
+            final String methodStr = "getIfaceV1_0";
             if (mISupplicant == null) {
                 return null;
             }
 
             /** List all supplicant Ifaces */
             final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
+            if (!checkSupplicantAndLogFailure(methodStr)) return null;
             try {
                 mISupplicant.listInterfaces((SupplicantStatus status,
                                              ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
@@ -510,7 +715,12 @@
             ifaceInfo.type = IfaceType.STA;
             Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
             try {
-                getSupplicantMockableV1_1().addInterface(ifaceInfo,
+                android.hardware.wifi.supplicant.V1_1.ISupplicant ISupplicantV1_1 = getSupplicantMockableV1_1();
+                if(ISupplicantV1_1 == null) {
+                    Log.e(TAG, "Cannot add network, ISupplicant is null");
+                    return null;
+                }
+                ISupplicantV1_1.addInterface(ifaceInfo,
                         (SupplicantStatus status, ISupplicantIface iface) -> {
                             if (status.code != SupplicantStatusCode.SUCCESS
                                     && status.code != SupplicantStatusCode.FAILURE_IFACE_EXISTS) {
@@ -527,6 +737,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;
         }
@@ -552,7 +766,12 @@
                 Log.e(TAG, "Trying to teardown unknown inteface");
                 return false;
             }
+            if (mISupplicantVendorStaIfaces.remove(ifaceName) == null) {
+                Log.e(TAG, "Trying to teardown unknown vendor interface");
+                return false;
+            }
             mISupplicantStaIfaceCallbacks.remove(ifaceName);
+            mISupplicantVendorStaIfaceCallbacks.remove(ifaceName);
             return true;
         }
     }
@@ -569,7 +788,12 @@
                 ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo();
                 ifaceInfo.name = ifaceName;
                 ifaceInfo.type = IfaceType.STA;
-                SupplicantStatus status = getSupplicantMockableV1_1().removeInterface(ifaceInfo);
+                android.hardware.wifi.supplicant.V1_1.ISupplicant ISupplicantV1_1 = getSupplicantMockableV1_1();
+                if(ISupplicantV1_1 == null) {
+                    Log.e(TAG, "Failed to remove iface, ISupplicant is null");
+                    return false;
+		}
+                SupplicantStatus status = ISupplicantV1_1.removeInterface(ifaceInfo);
                 if (status.code != SupplicantStatusCode.SUCCESS) {
                     Log.e(TAG, "Failed to remove iface " + status.code);
                     return false;
@@ -592,11 +816,13 @@
      * @return Returns true on success.
      */
     public boolean registerDeathHandler(@NonNull SupplicantDeathEventHandler handler) {
-        if (mDeathEventHandler != null) {
-            Log.e(TAG, "Death handler already present");
+        synchronized (mLock) {
+            if (mDeathEventHandler != null) {
+                Log.e(TAG, "Death handler already present");
+            }
+            mDeathEventHandler = handler;
+            return true;
         }
-        mDeathEventHandler = handler;
-        return true;
     }
 
     /**
@@ -604,20 +830,32 @@
      * @return Returns true on success.
      */
     public boolean deregisterDeathHandler() {
-        if (mDeathEventHandler == null) {
-            Log.e(TAG, "No Death handler present");
+        synchronized (mLock) {
+            if (mDeathEventHandler == null) {
+                Log.e(TAG, "No Death handler present");
+            }
+            mDeathEventHandler = null;
+            return true;
         }
-        mDeathEventHandler = null;
-        return true;
     }
 
 
     private void clearState() {
         synchronized (mLock) {
             mISupplicant = null;
+            mISupplicantVendor = null;
             mISupplicantStaIfaces.clear();
+            mISupplicantVendorStaIfaces.clear();
             mCurrentNetworkLocalConfigs.clear();
             mCurrentNetworkRemoteHandles.clear();
+            mLinkedNetworkLocalAndRemoteConfigs.clear();
+        }
+    }
+
+    private void supplicantvendorServiceDiedHandler() {
+        synchronized (mLock) {
+            mISupplicantVendor = null;
+            mISupplicantVendorStaIfaces.clear();
         }
     }
 
@@ -705,7 +943,11 @@
             final String methodStr = "terminate";
             if (!checkSupplicantAndLogFailure(methodStr)) return;
             try {
-                getSupplicantMockableV1_1().terminate();
+                android.hardware.wifi.supplicant.V1_1.ISupplicant ISupplicantV1_1 = getSupplicantMockableV1_1();
+                if(ISupplicantV1_1 != null)
+                    ISupplicantV1_1.terminate();
+                else
+                    Log.e(TAG, "Cannot terminate ISupplicant. ISupplicant is Null.");
             } catch (RemoteException e) {
                 handleRemoteException(e, methodStr);
             } catch (NoSuchElementException e) {
@@ -725,6 +967,7 @@
             linkToSupplicantDeath((cookie) -> {
                 Log.d(TAG, "ISupplicant died: cookie=" + cookie);
                 if (cookie != waitForDeathCookie) return;
+                supplicantServiceDiedHandler(mDeathRecipientCookie);
                 waitForDeathLatch.countDown();
             }, waitForDeathCookie);
 
@@ -766,6 +1009,17 @@
         }
     }
 
+    protected ISupplicantVendor getSupplicantVendorMockable() throws RemoteException {
+        synchronized (mLock) {
+            try {
+                return ISupplicantVendor.getService();
+            } catch (NoSuchElementException e) {
+                Log.e(TAG, "Failed to get ISupplicant", e);
+                return null;
+            }
+        }
+    }
+
     protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1()
             throws RemoteException, NoSuchElementException {
         synchronized (mLock) {
@@ -806,6 +1060,18 @@
         }
     }
 
+    protected ISupplicantVendorStaIface getVendorStaIfaceMockable(ISupplicantVendorIface iface) {
+        synchronized (mLock) {
+            return ISupplicantVendorStaIface.asInterface(iface.asBinder());
+        }
+    }
+
+    protected ISupplicantVendorStaNetwork getVendorStaNetworkMockable(ISupplicantVendorNetwork network) {
+        synchronized (mLock) {
+            return ISupplicantVendorStaNetwork.asInterface(network.asBinder());
+        }
+    }
+
     protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
             getStaIfaceMockableV1_2(ISupplicantIface iface) {
         synchronized (mLock) {
@@ -875,13 +1141,37 @@
     }
 
     /**
-     * Helper method to look up the network object for the specified iface.
+     * Check if the device is running V2_0 supplicant vendor service.
+     * @return
+     */
+    private boolean isVendor_2_0() {
+        synchronized (mLock) {
+            try {
+                return (getSupplicantVendorMockable() != null);
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.getService exception: " + e);
+                supplicantServiceDiedHandler(mDeathRecipientCookie);
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Helper method to look up the iface object for the specified iface.
      */
     private ISupplicantStaIface getStaIface(@NonNull String ifaceName) {
         return mISupplicantStaIfaces.get(ifaceName);
     }
 
     /**
+     * Helper method to look up the vendor_iface object for the specified iface.
+     */
+    private ISupplicantVendorStaIface getVendorStaIface(@NonNull String ifaceName) {
+        return mISupplicantVendorStaIfaces.get(ifaceName);
+    }
+
+    /**
+
      * Helper method to look up the network object for the specified iface.
      */
     private SupplicantStaNetworkHal getCurrentNetworkRemoteHandle(@NonNull String ifaceName) {
@@ -915,6 +1205,9 @@
                 loge("Failed to add a network!");
                 return null;
             }
+            network.getId();
+            network.setVendorStaNetwork(getVendorNetwork
+                                        (ifaceName, network.getNetworkId()));
             boolean saveSuccess = false;
             try {
                 saveSuccess = network.saveWifiConfiguration(config);
@@ -945,9 +1238,10 @@
      */
     public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
         synchronized (mLock) {
-            logd("connectToNetwork " + config.getKey());
+            boolean isMixedGbkUtf = WifiGbk.isMixedGbkUtf(config); // wifigbk++
+            logd("connectToNetwork " + config.getKey() + " isMixedGbkUtf=" + isMixedGbkUtf);
             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
-            if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) {
+            if (WifiConfigurationUtil.isSameNetwork(config, currentConfig) && !isMixedGbkUtf) {
                 String networkSelectionBSSID = config.getNetworkSelectionStatus()
                         .getNetworkSelectionBSSID();
                 String networkSelectionBSSIDCurrent =
@@ -967,10 +1261,12 @@
             } else {
                 mCurrentNetworkRemoteHandles.remove(ifaceName);
                 mCurrentNetworkLocalConfigs.remove(ifaceName);
+                mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
                 if (!removeAllNetworks(ifaceName)) {
                     loge("Failed to remove existing networks");
                     return false;
                 }
+
                 Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
                         addNetworkAndSaveConfig(ifaceName, config);
                 if (pair == null) {
@@ -1095,6 +1391,7 @@
             // current network on receiving disconnection event from supplicant (b/32898136).
             mCurrentNetworkRemoteHandles.remove(ifaceName);
             mCurrentNetworkLocalConfigs.remove(ifaceName);
+            mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
             return true;
         }
     }
@@ -1353,6 +1650,33 @@
         }
     }
 
+    /**
+     * @return The ISupplicantVendorStaNetwork object for the given SupplicantNetworkId int, returns null if
+     * the call fails
+     */
+    private ISupplicantVendorStaNetwork getVendorNetwork(@NonNull String ifaceName, int id) {
+        synchronized (mLock) {
+            final String methodStr = "getVendorNetwork";
+            ISupplicantVendorStaIface iface = checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return null;
+            Mutable<ISupplicantVendorNetwork> gotNetwork = new Mutable<>();
+            try {
+                iface.getVendorNetwork(id, (SupplicantStatus status, ISupplicantVendorNetwork network) -> {
+                    if (checkStatusAndLogFailure(status, methodStr)) {
+                        gotNetwork.value = network;
+                    }
+                });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            if (gotNetwork.value != null) {
+                return getVendorStaNetworkMockable(gotNetwork.value);
+            } else {
+                return null;
+            }
+        }
+    }
+
     /** See ISupplicantStaNetwork.hal for documentation */
     private boolean registerCallback(
             ISupplicantStaIface iface, ISupplicantStaIfaceCallback callback) {
@@ -1420,6 +1744,22 @@
         }
     }
 
+    /** See ISupplicantVendorStaIface.hal for documentation */
+    private boolean registerVendorCallback(
+            ISupplicantVendorStaIface iface, ISupplicantVendorStaIfaceCallback callback) {
+        synchronized (mLock) {
+            final String methodStr = "registerVendorCallback";
+            if (iface == null) return false;
+            try {
+                SupplicantStatus status =  iface.registerVendorCallback(callback);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+
     /**
      * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns
      * null if the call fails
@@ -2138,6 +2478,36 @@
     }
 
     /**
+     * Querry driver capabilities
+     *
+     * @param ifaceName Name of the interface.
+     * @param capaType ASCII string, capability type ex: key_mgmt
+     * @return String of capabilities fetched from driver
+     */
+    public String getCapabilities(@NonNull String ifaceName, String capaType) {
+        synchronized (mLock) {
+            final String methodStr = "getCapabilities";
+            final Mutable<String> capability = new Mutable<>();
+
+            capability.value = "";
+            ISupplicantVendorStaIface iface =
+               checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return capability.value;
+            try {
+                 iface.getCapabilities(capaType,
+                        (SupplicantStatus status, String capaVal) -> {
+                         if(checkVendorStatusAndLogFailure(status, methodStr)) {
+                       capability.value = capaVal;
+                    }
+                });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return capability.value;
+         }
+    }
+
+    /**
      * Set country code.
      *
      * @param ifaceName Name of the interface.
@@ -2520,6 +2890,19 @@
     }
 
     /**
+     * Returns false if SupplicantVendor is null, and logs failure to call methodStr
+     */
+    private boolean checkSupplicantVendorAndLogFailure(final String methodStr) {
+        synchronized (mLock) {
+            if (mISupplicantVendor == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendor is null");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
      * Returns false if SupplicantStaIface is null, and logs failure to call methodStr
      */
     private ISupplicantStaIface checkSupplicantStaIfaceAndLogFailure(
@@ -2535,6 +2918,21 @@
     }
 
     /**
+     * Returns false if SupplicantVendorStaIface is null, and logs failure to call methodStr
+     */
+    private ISupplicantVendorStaIface checkSupplicantVendorStaIfaceAndLogFailure(
+            @NonNull String ifaceName, final String methodStr) {
+        synchronized (mLock) {
+            ISupplicantVendorStaIface iface = getVendorStaIface(ifaceName);
+            if (iface == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendorStaIface is null");
+                return null;
+            }
+            return iface;
+        }
+    }
+
+    /**
      * Returns false if SupplicantStaNetwork is null, and logs failure to call methodStr
      */
     private SupplicantStaNetworkHal checkSupplicantStaNetworkAndLogFailure(
@@ -2556,7 +2954,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 {
@@ -2569,6 +2967,44 @@
     }
 
     /**
+     * Returns true if provided supplicant vendor status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkSupplicantVendorStatusAndLogFailure(SupplicantStatus status,
+            final String methodStr) {
+        synchronized (mLock) {
+            if (status.code != SupplicantStatusCode.SUCCESS) {
+                Log.e(TAG, "ISupplicantVendor." + methodStr + " failed: " + status);
+                return false;
+            } else {
+                if (mVerboseLoggingEnabled) {
+                    Log.d(TAG, "ISupplicantVendor." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Returns true if provided Vendor status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkVendorStatusAndLogFailure(SupplicantStatus status,
+            final String methodStr) {
+        synchronized (mLock) {
+            if (status.code != SupplicantStatusCode.SUCCESS) {
+                Log.e(TAG, "ISupplicantVendorStaIface." + methodStr + " failed: " + status);
+                return false;
+            } else {
+                if (mVerboseLoggingEnabled) {
+                    Log.d(TAG, "ISupplicantVendorStaIface." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
      * Helper function to log callbacks.
      */
     protected void logCallback(final String methodStr) {
@@ -2593,6 +3029,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.
      */
@@ -2632,6 +3075,81 @@
         }
     }
 
+    private class SupplicantVendorStaIfaceHalCallback extends ISupplicantVendorStaIfaceCallback.Stub {
+        private String mIfaceName;
+        private SupplicantStaIfaceHalCallback mSupplicantStaIfacecallback;
+
+        SupplicantVendorStaIfaceHalCallback(@NonNull String ifaceName, SupplicantStaIfaceHalCallback callback) {
+            mIfaceName = ifaceName;
+            mSupplicantStaIfacecallback = callback;
+        }
+
+        @Override
+        public void onVendorStateChanged(int newState, byte[/* 6 */] bssid, int id,
+                                   ArrayList<Byte> ssid, boolean filsHlpSent) {
+            synchronized (mLock) {
+                logCallback("onVendorStateChanged");
+                SupplicantState newSupplicantState =
+                    SupplicantStaIfaceCallbackImpl.supplicantHidlStateToFrameworkState(newState);
+                WifiSsid wifiSsid = // wifigbk++
+                        WifiGbk.createWifiSsidFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
+                String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
+                if (newSupplicantState == SupplicantState.COMPLETED) {
+                    mWifiMonitor.broadcastNetworkConnectionEvent(
+                            mIfaceName, getCurrentNetworkId(mIfaceName), filsHlpSent, bssidStr);
+                }
+                mWifiMonitor.broadcastSupplicantStateChangeEvent(
+                        mIfaceName, getCurrentNetworkId(mIfaceName), wifiSsid, bssidStr, newSupplicantState);
+            }
+        }
+
+        /* DPP Callbacks Start */
+        @Override
+        public void onDppAuthSuccess(boolean initiator) {
+            logCallback("onDppAuthSuccess");
+            synchronized (mLock) {
+                DppResult result = new DppResult();
+                result.initiator = initiator;
+                mWifiMonitor.broadcastDppEvent(mIfaceName, DPP_EVENT_AUTH_SUCCESS, result);
+            }
+        }
+
+        @Override
+        public void onDppConf(byte type, ArrayList<Byte> ssid, String connector,
+                              ArrayList<Byte> cSignKey, ArrayList<Byte> netAccessKey,
+                              int netAccessExpiry, String passphrase, ArrayList<Byte> psk) {
+            logCallback("onDppConf");
+            synchronized (mLock) {
+                DppResult result = new DppResult();
+                result.configEventType = type;
+                result.ssid = NativeUtil.stringFromByteArrayList(ssid);
+                result.connector = connector;
+                result.cSignKey = NativeUtil.bytesToHexOrQuotedString(cSignKey);
+                result.netAccessKey = NativeUtil.bytesToHexOrQuotedString(netAccessKey);
+                result.netAccessKeyExpiry = netAccessExpiry;
+                result.passphrase = passphrase;
+                result.psk = NativeUtil.stringFromByteArrayList(psk);
+                mWifiMonitor.broadcastDppEvent(mIfaceName, DPP_EVENT_CONF, result);
+            }
+        }
+
+        @Override
+        public void onDppNotCompatible(byte capab, boolean initiator) {}
+
+        @Override
+        public void onDppResponsePending() {}
+
+        @Override
+        public void onDppScanPeerQrCode(ArrayList<Byte> bootstrapData) {}
+
+        @Override
+        public void onDppMissingAuth(byte dppAuthParam) {}
+
+        @Override
+        public void onDppNetworkId(int netID) {}
+        /* DPP Callbacks ends */
+    }
+
     protected class SupplicantStaIfaceHalCallback extends SupplicantStaIfaceCallbackImpl {
         SupplicantStaIfaceHalCallback(@NonNull String ifaceName) {
             super(SupplicantStaIfaceHal.this, ifaceName, mLock, mWifiMonitor);
@@ -3031,6 +3549,317 @@
     }
 
     /**
+     * Add the DPP bootstrap info obtained from QR code.
+     *
+     * @param ifaceName Name of the interface.
+     * @param uri:The URI obtained from the QR code.
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int dppAddBootstrapQrCode(@NonNull String ifaceName, String uri) {
+        if (TextUtils.isEmpty(uri)) return -1;
+        synchronized (mLock) {
+            final String methodStr = "dppAddBootstrapQrCode";
+            final MutableInt handle = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppAddBootstrapQrcode(uri,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * Generate bootstrap URI based on the passed arguments
+     *
+     * @param ifaceName Name of the interface.
+     * @param config – bootstrap generate config
+     *
+     * @return: Handle to strored URI info else -1 on failure
+     */
+    public int dppBootstrapGenerate(@NonNull String ifaceName, WifiDppConfig config) {
+        synchronized (mLock) {
+            final String methodStr = "dppBootstrapGenerate";
+            final MutableInt handle = new MutableInt(-1);
+
+            String chan_list = (TextUtils.isEmpty(config.chan_list)) ? "" : config.chan_list;
+            String mac_addr = (TextUtils.isEmpty(config.mac_addr)) ? "00:00:00:00:00:00" : config.mac_addr;
+            String info = (TextUtils.isEmpty(config.info)) ? "" : config.info;
+            String curve = (TextUtils.isEmpty(config.curve)) ? "" : config.curve;
+            String key = (TextUtils.isEmpty(config.key)) ? "" : config.key;
+
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppBootstrapGenerate(config.bootstrap_type,
+                            chan_list, NativeUtil.macAddressToByteArray(mac_addr),
+                            info, curve, key,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * Get bootstrap URI based on bootstrap ID
+     *
+     * @param ifaceName Name of the interface.
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: URI string else -1 on failure
+     */
+    public String dppGetUri(@NonNull String ifaceName, int bootstrap_id) {
+        synchronized (mLock) {
+            final String methodStr = "dppGetUri";
+            final Mutable<String> URI = new Mutable<>();
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return "-1";
+            try {
+                iface.dppGetUri(bootstrap_id,
+                        (SupplicantStatus status, String uri) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                URI.value = uri;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return URI.value;
+        }
+    }
+
+    /**
+     * Remove bootstrap URI based on bootstrap ID.
+     *
+     * @param ifaceName Name of the interface.
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: 0 – Success or -1 on failure
+     */
+    public int dppBootstrapRemove(@NonNull String ifaceName, int bootstrap_id) {
+        synchronized (mLock) {
+            final String methodStr = "dppBootstrapRemove";
+            final MutableInt handle = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppBootstrapRemove(bootstrap_id,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * start listen on the channel specified waiting to receive
+     * the DPP Authentication request.
+     *
+     * @param ifaceName Name of the interface.
+     * @param frequency: DPP listen frequency
+     * @param dpp_role: Configurator/Enrollee role
+     * @param qr_mutual: Mutual authentication required
+     * @param netrole_ap: network role
+     *
+     * @return: Returns 0 if a DPP-listen work is successfully
+     *  queued and -1 on failure.
+     */
+    public int dppListen(@NonNull String ifaceName, String frequency, int dpp_role,
+                         boolean qr_mutual, boolean netrole_ap) {
+        if (TextUtils.isEmpty(frequency)) return -1;
+        synchronized (mLock) {
+            final String methodStr = "dppListen";
+            final MutableInt handle = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppStartListen(frequency, dpp_role,
+                        qr_mutual, netrole_ap,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * stop ongoing dpp listen.
+     *
+     * @param ifaceName Name of the interface.
+     * @return true if request is sent successfully, false otherwise.
+     */
+    public boolean dppStopListen(@NonNull String ifaceName) {
+        synchronized (mLock) {
+            final String methodStr = "dppStopListen";
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return false;
+            try {
+                SupplicantStatus status = iface.dppStopListen();
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Adds the DPP configurator
+     *
+     * @param ifaceName Name of the interface.
+     * @param curve curve used for dpp encryption
+     * @param key private key
+     * @param expiry timeout in seconds
+     *
+     * @return: Identifier of the added configurator or -1 on failure
+     */
+    public int dppConfiguratorAdd(@NonNull String ifaceName, String curve,
+                                  String key, int expiry) {
+        String curve_t = (TextUtils.isEmpty(curve)) ? "" : curve;
+        String key_t = (TextUtils.isEmpty(key)) ? "" : key;
+        synchronized (mLock) {
+            final String methodStr = "dppConfiguratorAdd";
+            final MutableInt handle = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppConfiguratorAdd(curve_t, key_t, expiry,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * Remove the added configurator through dppConfiguratorAdd.
+     *
+     * @param ifaceName Name of the interface.
+     * @param config_id: DPP Configurator ID
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int dppConfiguratorRemove(@NonNull String ifaceName, int config_id) {
+        synchronized (mLock) {
+            final String methodStr = "dppConfiguratorRemove";
+            final MutableInt handle = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppConfiguratorRemove(config_id,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                handle.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return handle.value;
+        }
+    }
+
+    /**
+     * Start DPP authentication and provisioning with the specified peer
+     *
+     * @param ifaceName Name of the interface.
+     * @param config – dpp auth init config
+     *
+     * @return: 0 if DPP Authentication request was transmitted and -1 on failure
+     */
+    public int  dppStartAuth(@NonNull String ifaceName, WifiDppConfig config) {
+        String ssid = (TextUtils.isEmpty(config.ssid)) ? "" : config.ssid;
+        String passphrase = (TextUtils.isEmpty(config.passphrase)) ? "" : config.passphrase;
+        synchronized (mLock) {
+            final String methodStr = "dppStartAuth";
+            final MutableInt Status = new MutableInt(-1);
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return -1;
+            try {
+                iface.dppStartAuth(config.peer_bootstrap_id,
+                            config.own_bootstrap_id, config.dpp_role,
+                            ssid, passphrase, (config.isAp > 0) ? true : false,
+                            (config.isDpp > 0) ? true: false, config.conf_id, config.expiry,
+                        (SupplicantStatus status, int hdl) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                Status.value = hdl;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return Status.value;
+        }
+    }
+
+    /**
+     * Retrieve Private key to be used for configurator
+     *
+     * @param ifaceName Name of the interface.
+     * @param id: id of configurator obj
+     *
+     * @return: Key string else -1 on failure
+     */
+    public String dppConfiguratorGetKey(@NonNull String ifaceName, int id) {
+        synchronized (mLock) {
+            final String methodStr = "dppConfiguratorGetKey";
+            final Mutable<String> KEY = new Mutable<>();
+            ISupplicantVendorStaIface iface =
+                   checkSupplicantVendorStaIfaceAndLogFailure(ifaceName, methodStr);
+            if (iface == null) return "-1";
+            try {
+                iface.dppConfiguratorGetKey(id,
+                        (SupplicantStatus status, String key) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                KEY.value = key;
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return KEY.value;
+        }
+    }
+
+    /*
      * Adds a DPP peer URI to the URI list.
      *
      *  This is a v1.2+ HAL feature.
@@ -3301,4 +4130,189 @@
         return false;
     }
 
+    protected vendor.qti.hardware.wifi.supplicant.V2_1.ISupplicantVendorStaIface
+    getSupplicantVendorStaIfaceV2_1Mockable(ISupplicantVendorStaIface vendorIfaceV2_0) {
+        if (vendorIfaceV2_0 == null) return null;
+        return vendor.qti.hardware.wifi.supplicant.V2_1.ISupplicantVendorStaIface.castFrom(
+                vendorIfaceV2_0);
+    }
+
+    public WifiNative.WifiGenerationStatus getWifiGenerationStatus(@NonNull String ifaceName) {
+        synchronized (mLock) {
+            final String methodStr = "getWifiGenerationStatus";
+            final Mutable<WifiNative.WifiGenerationStatus> STATUS = new Mutable<>();
+            ISupplicantVendorStaIface vendorIfaceV2_0 = getVendorStaIface(ifaceName);
+            if (vendorIfaceV2_0 == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendorStaIface is null");
+                return null;
+            }
+
+            vendor.qti.hardware.wifi.supplicant.V2_1.ISupplicantVendorStaIface vendorIfaceV2_1;
+            vendorIfaceV2_1 = getSupplicantVendorStaIfaceV2_1Mockable(vendorIfaceV2_0);
+            if (vendorIfaceV2_1 == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", V2_1.ISupplicantVendorStaIface is null");
+                return null;
+            }
+
+            try {
+                vendorIfaceV2_1.getWifiGenerationStatus((SupplicantStatus status, WifiGenerationStatus generationStatus) -> {
+                            if (checkVendorStatusAndLogFailure(status, methodStr)) {
+                                STATUS.value = new WifiNative.WifiGenerationStatus(generationStatus.generation,
+                                                                                   generationStatus.vhtMax8SpatialStreamsSupport,
+                                                                                   generationStatus.twtSupport);
+                            }
+                        });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return STATUS.value;
+        }
+    }
+
+    protected vendor.qti.hardware.wifi.supplicant.V2_2.ISupplicantVendorStaIface
+        getSupplicantVendorStaIfaceV2_2Mockable(ISupplicantVendorStaIface vendorIfaceV2_0) {
+        if (vendorIfaceV2_0 == null) return null;
+        return vendor.qti.hardware.wifi.supplicant.V2_2.ISupplicantVendorStaIface.castFrom(
+                vendorIfaceV2_0);
+    }
+
+    /**
+     * run Driver command
+     *
+     * @param ifaceName Interface Name
+     * @param command Driver Command
+     */
+    public String doDriverCmd(String ifaceName, String command)
+    {
+        synchronized (mLock) {
+            final String methodStr = "doDriverCmd";
+            final Mutable<String> reply = new Mutable<>();
+
+            reply.value = "";
+            ISupplicantVendorStaIface vendorIfaceV2_0 = getVendorStaIface(ifaceName);
+            if (vendorIfaceV2_0 == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendorStaIface is null");
+                return null;
+            }
+
+            vendor.qti.hardware.wifi.supplicant.V2_2.ISupplicantVendorStaIface vendorIfaceV2_2;
+            vendorIfaceV2_2 = getSupplicantVendorStaIfaceV2_2Mockable(vendorIfaceV2_0);
+            if (vendorIfaceV2_2 == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", V2_2.ISupplicantVendorStaIface is null");
+                return null;
+            }
+
+            try {
+                vendorIfaceV2_2.doDriverCmd(command,
+                        (SupplicantStatus status, String rply) -> {
+                        if(checkVendorStatusAndLogFailure(status, methodStr)) {
+                            reply.value = rply;
+                     }
+                });
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+            }
+            return reply.value;
+         }
+    }
+
+    protected int getCurrentNetworkRemoteId(@NonNull String ifaceName) {
+        synchronized (mLock) {
+            SupplicantStaNetworkHal networkHal = getCurrentNetworkRemoteHandle(ifaceName);
+            if (networkHal == null) {
+                return WifiConfiguration.INVALID_NETWORK_ID;
+            }
+            return networkHal.getNetworkId();
+        }
+    }
+
+    protected void updateCurrentNetworkHandles(@NonNull String ifaceName,
+            @NonNull Pair<SupplicantStaNetworkHal, WifiConfiguration> networkHandles) {
+        mCurrentNetworkRemoteHandles.put(ifaceName, networkHandles.first);
+        mCurrentNetworkLocalConfigs.put(ifaceName, networkHandles.second);
+    }
+
+    protected ArrayList<Pair<SupplicantStaNetworkHal, WifiConfiguration>>
+            getLinkedNetworksHandles(@NonNull String ifaceName) {
+        return mLinkedNetworkLocalAndRemoteConfigs.get(ifaceName);
+    }
+
+    public boolean updateLinkedNetworks(@NonNull String ifaceName, int networkId,
+                           HashMap<String, WifiConfiguration> linkedConfigurations) {
+        synchronized (mLock) {
+            WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
+            SupplicantStaNetworkHal currentHandle = getCurrentNetworkRemoteHandle(ifaceName);
+
+            if (currentConfig == null || currentHandle == null) {
+                Log.e(TAG, "current network not configured yet.");
+                return false;
+            }
+
+            if (currentConfig.networkId != networkId) {
+                Log.e(TAG, "current network id is not matching");
+                return false;
+            }
+
+            if (!currentHandle.getId()) {
+                Log.e(TAG, "current network getId failed");
+                return false;
+            }
+
+            if (!removeLinkedNetworks(ifaceName, currentHandle.getNetworkId())) {
+                Log.e(TAG, "couldn't remove existing linked networks");
+                return false;
+            }
+
+            mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
+
+            if (linkedConfigurations == null || linkedConfigurations.size() == 0) {
+                Log.i(TAG, "cleared linked networks");
+                return true;
+            }
+
+            ArrayList<Pair<SupplicantStaNetworkHal, WifiConfiguration>> linkedNetworkHandles
+                = new ArrayList<Pair<SupplicantStaNetworkHal, WifiConfiguration>>();
+
+            linkedNetworkHandles.add(new Pair(mCurrentNetworkRemoteHandles.get(ifaceName),
+                                              mCurrentNetworkLocalConfigs.get(ifaceName)));
+            for (String linkedNetwork : linkedConfigurations.keySet()) {
+                Log.i(TAG, "add linked network: " + linkedNetwork);
+                Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
+                        addNetworkAndSaveConfig(ifaceName, linkedConfigurations.get(linkedNetwork));
+                if (pair == null) {
+                    Log.e(TAG, "failed to add/save linked network: " + linkedNetwork);
+                    return false;
+                }
+                pair.first.enable(true);
+                linkedNetworkHandles.add(pair);
+            }
+
+            mLinkedNetworkLocalAndRemoteConfigs.put(ifaceName, linkedNetworkHandles);
+
+            return true;
+        }
+    }
+
+    /**
+     * Remove linked networks from supplicant
+     *
+     * @param ifaceName Name of the interface.
+     */
+    private boolean removeLinkedNetworks(@NonNull String ifaceName, int currentNetworkId) {
+        synchronized (mLock) {
+            ArrayList<Integer> networks = listNetworks(ifaceName);
+            if (networks == null) {
+                Log.e(TAG, "removeLinkedNetworks failed, got null networks");
+                return false;
+            }
+            for (int id : networks) {
+                if (currentNetworkId == id) continue;
+                if (!removeNetwork(ifaceName, id)) {
+                    Log.e(TAG, "removeLinkedNetworks failed to remove network: " + id);
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
 }
diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
index 68623fb..46bb047 100644
--- a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
@@ -16,6 +16,7 @@
 package com.android.server.wifi;
 
 import android.content.Context;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorStaNetwork;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback;
 import android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
@@ -93,6 +94,7 @@
     private final String mIfaceName;
     private final WifiMonitor mWifiMonitor;
     private ISupplicantStaNetwork mISupplicantStaNetwork;
+    private ISupplicantVendorStaNetwork mISupplicantVendorStaNetwork;
     private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback;
 
     private boolean mVerboseLoggingEnabled = false;
@@ -289,8 +291,9 @@
             if (config == null) return false;
             /** SSID */
             if (config.SSID != null) {
-                if (!setSsid(NativeUtil.decodeSsid(config.SSID))) {
-                    Log.e(TAG, "failed to set SSID: " + config.SSID);
+                String ssid = WifiGbk.getRealSsid(config); // wifigbk++
+                if (!setSsid(NativeUtil.decodeSsid(ssid))) {
+                    Log.e(TAG, "failed to set SSID: " + ssid);
                     return false;
                 }
             }
@@ -324,6 +327,15 @@
                     Log.e(TAG, "failed to set Key Management");
                     return false;
                 }
+                if (!setVendorKeyMgmt(wifiConfigurationToSupplicantVendorKeyMgmtMask(keyMgmtMask)))
+                    Log.e(TAG, "failed to set Vendor Key Management");
+
+		// Check and set DPP configurations.
+                if (keyMgmtMask.get(WifiConfiguration.KeyMgmt.DPP) && !saveDppConfig(config)) {
+                    Log.e(TAG, "Failed to set DPP configurations.");
+                        return false;
+                }
+
                 // Check and set SuiteB configurations.
                 if (keyMgmtMask.get(WifiConfiguration.KeyMgmt.SUITE_B_192)
                         && !saveSuiteBConfig(config)) {
@@ -337,6 +349,12 @@
                 Log.e(TAG, "failed to set Security Protocol");
                 return false;
             }
+            /** Vendor Security Protocol */
+            if (config.allowedProtocols.cardinality() != 0
+                    && !setVendorProto(wifiConfigurationToSupplicantVendorProtoMask(config.allowedProtocols))) {
+                Log.e(TAG, "failed to set Vendor Security Protocol");
+            }
+
             /** Auth Algorithm */
             if (config.allowedAuthAlgorithms.cardinality() != 0
                     && !setAuthAlg(wifiConfigurationToSupplicantAuthAlgMask(
@@ -555,6 +573,41 @@
     }
 
     /**
+     * Save network variables from the provided DPP configuration to wpa_supplicant.
+     *
+     * @param config WifiConfiguration object to be saved (only DPP configs).
+     * @return true if succeeds, false otherwise.
+     */
+    private boolean saveDppConfig(WifiConfiguration config) {
+        /** DppConnector */
+        if (config.dppConnector != null
+                && !setDppConnector(config.dppConnector)) {
+            Log.e(TAG, "failed to set DPP connector");
+            return false;
+        }
+        /** DppNetAccessKey */
+        if (config.dppNetAccessKey != null
+                && !setDppNetAccessKey(NativeUtil.stringToByteArrayList(config.dppNetAccessKey))) {
+            Log.e(TAG, "failed to set DPP Net Access key");
+            return false;
+        }
+        /** DppNetAccessKeyExipry */
+        if (config.dppNetAccessKeyExpiry >= 0
+                && !setDppNetAccessKeyExpiry(config.dppNetAccessKeyExpiry)) {
+            Log.e(TAG, "failed to set DPP Net Access Key Expiry time");
+            return false;
+        }
+        /** DppCsign */
+        if (config.dppCsign != null
+                && !setDppCsign(NativeUtil.stringToByteArrayList(config.dppCsign))) {
+            Log.e(TAG, "failed to set DPP c-sign");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
      * Save network variables from the provided SuiteB configuration to wpa_supplicant.
      *
      * @param config WifiConfiguration object to be saved
@@ -706,6 +759,13 @@
                 return false;
             }
 
+	    /** SIM Number */
+            eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.KEY_SIMNUM);
+            if (!TextUtils.isEmpty(eapParam)
+                && !setVendorSimNumber(Integer.parseInt(eapParam))) {
+                Log.e(TAG, ssid + ": failed to set VendorSimNumber : " + eapParam);
+            }
+
             /**
              * OCSP (Online Certificate Status Protocol)
              * For older HAL compatibility, omit this step to avoid breaking
@@ -811,6 +871,8 @@
                             .FILS_SHA384;
                     break;
                 case WifiConfiguration.KeyMgmt.WPA2_PSK: // This should never happen
+                case WifiConfiguration.KeyMgmt.DPP:
+                    break;
                 default:
                     throw new IllegalArgumentException(
                             "Invalid protoMask bit in keyMgmt: " + bit);
@@ -819,6 +881,32 @@
         return mask;
     }
 
+    /**
+     * Maps WifiConfiguration Key Management BitSet to Supplicant Vendor HIDL bitmask int
+     * TODO(b/32571829): Update mapping when fast transition keys are added
+     * @return bitmask int describing the allowed Key Management schemes, readable by the Supplicant
+     *         HIDL hal
+     */
+    private static int wifiConfigurationToSupplicantVendorKeyMgmtMask(BitSet keyMgmt) {
+        int mask = 0;
+        for (int bit = keyMgmt.nextSetBit(0); bit != -1; bit = keyMgmt.nextSetBit(bit + 1)) {
+            switch (bit) {
+                case WifiConfiguration.KeyMgmt.DPP:
+                    mask |= ISupplicantVendorStaNetwork.VendorKeyMgmtMask.DPP;
+                    break;
+                case WifiConfiguration.KeyMgmt.OWE: //This is now supported with V1_2.ISupplicantStaNetwork.KeyMgmtMask
+                case WifiConfiguration.KeyMgmt.SAE:
+                case WifiConfiguration.KeyMgmt.SUITE_B_192:
+		case WifiConfiguration.KeyMgmt.FILS_SHA256:
+		case WifiConfiguration.KeyMgmt.FILS_SHA384:
+                    break;
+                default:
+                    Log.e(TAG, "Invalid VendorKeyMgmtMask bit in keyMgmt: " + bit);
+            }
+        }
+        return mask;
+    }
+
     private static int wifiConfigurationToSupplicantProtoMask(BitSet protoMask) {
         int mask = 0;
         for (int bit = protoMask.nextSetBit(0); bit != -1;
@@ -845,6 +933,18 @@
         return mask;
     }
 
+    private static int wifiConfigurationToSupplicantVendorProtoMask(BitSet protoMask) {
+        int mask = 0;
+        for (int bit = protoMask.nextSetBit(0); bit != -1; bit = protoMask.nextSetBit(bit + 1)) {
+            switch (bit) {
+                    //TODO for vendor proto mask
+                default:
+		    Log.e(TAG, "Invalid protoMask bit in wificonfig: " + bit);
+            }
+        }
+        return mask;
+    };
+
     private static int wifiConfigurationToSupplicantAuthAlgMask(BitSet authAlgMask) {
         int mask = 0;
         for (int bit = authAlgMask.nextSetBit(0); bit != -1;
@@ -1138,6 +1238,9 @@
                 android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
                         .GroupCipherMask.GCMP_256, bitset, WifiConfiguration.GroupCipher.GCMP_256);
         mask = supplicantMaskValueToWifiConfigurationBitSet(
+                mask, ISupplicantVendorStaNetwork.VendorGroupCipherMask.GCMP_256, bitset,
+                WifiConfiguration.GroupCipher.GCMP_256);
+        mask = supplicantMaskValueToWifiConfigurationBitSet(
                 mask, ISupplicantStaNetwork.GroupCipherMask.GTK_NOT_USED, bitset,
                 WifiConfiguration.GroupCipher.GTK_NOT_USED);
         mask = supplicantMaskValueToWifiConfigurationBitSet(mask,
@@ -1247,7 +1350,7 @@
     }
 
     /** See ISupplicantNetwork.hal for documentation */
-    private boolean getId() {
+    public boolean getId() {
         synchronized (mLock) {
             final String methodStr = "getId";
             if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
@@ -1269,6 +1372,22 @@
         }
     }
 
+    /** get network current network */
+    public int getNetworkId() {
+           return mNetworkId;
+    }
+
+    /** set local vendor sta network, if it not null */
+    public void setVendorStaNetwork(ISupplicantVendorStaNetwork vendor_network) {
+           System.out.println("stanetwork getId >>" + mNetworkId);
+           if (vendor_network != null) {
+               Log.e(TAG, "set ISupplicantVendorStaNetwork successfull");
+               mISupplicantVendorStaNetwork = vendor_network;
+           } else {
+               Log.e(TAG, "Failed to set ISupplicantVendorStaNetwork due to null");
+           }
+    }
+
     /** See ISupplicantStaNetwork.hal for documentation */
     private boolean registerCallback(ISupplicantStaNetworkCallback callback) {
         synchronized (mLock) {
@@ -1379,6 +1498,21 @@
     }
 
     /** See ISupplicantStaNetwork.hal for documentation */
+    private boolean setVendorKeyMgmt(int keyMgmtMask) {
+        synchronized (mLock) {
+            final String methodStr = "setVendorKeyMgmt";
+            Log.e(TAG, "Vendor Key Management " + keyMgmtMask);
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setVendorKeyMgmt(keyMgmtMask);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+    /** See ISupplicantStaNetwork.hal for documentation */
     private boolean setProto(int protoMask) {
         synchronized (mLock) {
             final String methodStr = "setProto";
@@ -1400,6 +1534,20 @@
             }
         }
     }
+    /** See ISupplicantVendorStaNetwork.hal for documentation */
+    private boolean setVendorProto(int protoMask) {
+        synchronized (mLock) {
+            final String methodStr = "setVendorProto";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setVendorProto(protoMask);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
 
     /** See ISupplicantStaNetwork.hal for documentation */
     private boolean setAuthAlg(int authAlgMask) {
@@ -1906,6 +2054,75 @@
             }
         }
     }
+    /** See ISupplicantVendorStaNetwork.hal for documentation */
+    private boolean setDppConnector(String connector) {
+        synchronized (mLock) {
+            final String methodStr = "setDppConnector";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setDppConnector(connector);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+    /** See ISupplicantVendorStaNetwork.hal for documentation */
+    private boolean setDppNetAccessKey(java.util.ArrayList<Byte> netAccessKey) {
+        synchronized (mLock) {
+            final String methodStr = "setDppNetAccessKey";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setDppNetAccessKey(netAccessKey);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+    /** See ISupplicantVendorStaNetwork.hal for documentation */
+    private boolean setDppNetAccessKeyExpiry(int expiry) {
+        synchronized (mLock) {
+            final String methodStr = "setDppNetAccessKeyExpiry";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setDppNetAccessKeyExpiry(expiry);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+    /** See ISupplicantVendorStaNetwork.hal for documentation */
+    private boolean setDppCsign(java.util.ArrayList<Byte> csign) {
+        synchronized (mLock) {
+            final String methodStr = "setDppCsign";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setDppCsign(csign);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
+    private boolean setVendorSimNumber(int SimNum) {
+        synchronized (mLock) {
+            final String methodStr = "setVendorSimNumber";
+            if (!checkISupplicantVendorStaNetworkAndLogFailure(methodStr)) return false;
+            try {
+                SupplicantStatus status =  mISupplicantVendorStaNetwork.setVendorSimNumber(SimNum);
+                return checkVendorStatusAndLogFailure(status, methodStr);
+            } catch (RemoteException e) {
+                handleRemoteException(e, methodStr);
+                return false;
+            }
+        }
+    }
 
     /** See ISupplicantStaNetwork.hal for documentation */
     private boolean setIdStr(String idString) {
@@ -2873,7 +3090,7 @@
     }
 
     /** See ISupplicantStaNetwork.hal for documentation */
-    private boolean enable(boolean noConnect) {
+    public boolean enable(boolean noConnect) {
         synchronized (mLock) {
             final String methodStr = "enable";
             if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
@@ -3383,6 +3600,24 @@
     }
 
     /**
+     * Returns true if provided status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkVendorStatusAndLogFailure(SupplicantStatus status, final String methodStr) {
+        synchronized (mLock) {
+            if (status.code != SupplicantStatusCode.SUCCESS) {
+                Log.e(TAG, "ISupplicantVendorStaNetwork." + methodStr + " failed: " + status);
+                return false;
+            } else {
+                if (mVerboseLoggingEnabled) {
+                    Log.d(TAG, "ISupplicantVendorStaNetwork." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
      * Helper function to log callbacks.
      */
     private void logCallback(final String methodStr) {
@@ -3406,6 +3641,19 @@
         }
     }
 
+    /**
+     * Returns false if ISupplicantVendorStaNetwork is null, and logs failure of methodStr
+     */
+    private boolean checkISupplicantVendorStaNetworkAndLogFailure(final String methodStr) {
+        synchronized (mLock) {
+            if (mISupplicantVendorStaNetwork == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendorStaNetwork is null");
+                return false;
+            }
+            return true;
+        }
+    }
+
     private void handleRemoteException(RemoteException e, String methodStr) {
         synchronized (mLock) {
             mISupplicantStaNetwork = null;
diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index 3de9971..8ec0ab5 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -21,9 +21,11 @@
 import android.content.IntentFilter;
 import android.net.MacAddress;
 import android.net.util.MacAddressUtils;
+import android.net.wifi.ScanResult;
 import android.net.wifi.SoftApConfiguration;
 import android.os.Handler;
 import android.os.Process;
+import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -95,6 +97,11 @@
         }
     }
 
+    // Dual SAP config
+    private boolean mDualSapStatus = false;
+
+    private int mWifiStandard = ScanResult.WIFI_STANDARD_LEGACY;
+
     WifiApConfigStore(Context context,
             WifiInjector wifiInjector,
             Handler handler,
@@ -119,6 +126,24 @@
         mMacAddressUtil = wifiInjector.getMacAddressUtil();
     }
 
+   /* Additional APIs(get/set) to support SAP + SAP Feature */
+
+    public synchronized String getBridgeInterface() {
+        String bridgeInterfaceName = mContext.getResources()
+                   .getString(R.string.config_vendor_wifi_tether_bridge_interface_name);
+        if (bridgeInterfaceName == null || TextUtils.isEmpty(bridgeInterfaceName))
+            return "wifi_br0"; // Return default value
+        return bridgeInterfaceName;
+    }
+
+    public synchronized boolean getDualSapStatus() {
+        return mDualSapStatus;
+    }
+
+    public synchronized void setDualSapStatus(boolean enable) {
+        mDualSapStatus = enable;
+    }
+
     /**
      * Return the current soft access point configuration.
      */
@@ -246,7 +271,9 @@
 
         // some countries are unable to support 5GHz only operation, always allow for 2GHz when
         // config doesn't force channel
-        if (config.getChannel() == 0 && (config.getBand() & SoftApConfiguration.BAND_2GHZ) == 0) {
+        // Do not explicitly mark 2G support when BOTH 2G+5G band is requested in DBS mode.
+        if (config.getChannel() == 0 && ((config.getBand() & SoftApConfiguration.BAND_2GHZ) == 0)
+                && (config.getBand() != SoftApConfiguration.BAND_DUAL)) {
             Log.w(TAG, "Supplied ap config band without 2.4G, add allowing for 2.4GHz");
             if (convertedConfigBuilder == null) {
                 convertedConfigBuilder = new SoftApConfiguration.Builder(config);
@@ -431,10 +458,11 @@
             return false;
         }
 
-        if (authType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
+        if (authType == SoftApConfiguration.SECURITY_TYPE_OPEN
+                || authType == SoftApConfiguration.SECURITY_TYPE_OWE) {
             // open networks should not have a password
             if (hasPreSharedKey) {
-                Log.d(TAG, "open softap network should not have a password");
+                Log.d(TAG, "open or OWE softap network should not have a password");
                 return false;
             }
         } else if (authType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
@@ -452,7 +480,7 @@
             }
         } else {
             // this is not a supported security type
-            Log.d(TAG, "softap configs must either be open or WPA2 PSK networks");
+            Log.d(TAG, "softap configs must either be open or WPA2 PSK or OWE or SAE networks");
             return false;
         }
 
@@ -472,4 +500,12 @@
         }
         return sb.toString();
     }
+
+    public void setWifiStandard(int standard) {
+        mWifiStandard = standard;
+    }
+
+    public int getWifiStandard() {
+        return mWifiStandard;
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java
index 0513e5c..f5d2c81 100644
--- a/service/java/com/android/server/wifi/WifiCandidates.java
+++ b/service/java/com/android/server/wifi/WifiCandidates.java
@@ -194,14 +194,14 @@
             this.mFrequency = frequency;
             this.mPerBssid = perBssid;
             this.mLastSelectionWeight = lastSelectionWeight;
-            this.mIsCurrentNetwork = isCurrentNetwork;
+            this.mIsCurrentNetwork = isCurrentNetwork || config.isAutoConnectionEnabled;
             this.mIsCurrentBssid = isCurrentBssid;
             this.mIsMetered = isMetered;
             this.mHasNoInternetAccess = config.hasNoInternetAccess();
             this.mIsNoInternetAccessExpected = config.isNoInternetAccessExpected();
             this.mIsOpenNetwork = WifiConfigurationUtil.isConfigForOpenNetwork(config);
             this.mPasspoint = config.isPasspoint();
-            this.mEphemeral = config.isEphemeral();
+            this.mEphemeral = config.isEphemeral() && !config.isAutoConnectionEnabled;
             this.mTrusted = config.trusted;
             this.mCarrierOrPrivileged = isCarrierOrPrivileged;
             this.mPredictedThroughputMbps = predictedThroughputMbps;
diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
index d483047..486be33 100644
--- a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
+++ b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wifi;
 
+import static android.Manifest.permission.NETWORK_SETTINGS;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.AlertDialog;
@@ -96,6 +98,10 @@
     @VisibleForTesting
     public static final String NOTIFICATION_USER_DISMISSED_INTENT_ACTION =
             "com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED";
+    /** Intent when user clicked on the notification. */
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_CLICKED_INTENT_ACTION =
+            "com.android.server.wifi.action.CarrierNetwork.USER_CLICKED";
     @VisibleForTesting
     public static final String EXTRA_CARRIER_NAME =
             "com.android.server.wifi.extra.CarrierNetwork.CARRIER_NAME";
@@ -223,14 +229,16 @@
 
                     switch (intent.getAction()) {
                         case NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION:
-                            Log.i(TAG, "User clicked to allow carrier");
-                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
-                            // Collapse the notification bar
-                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                            handleUserAllowCarrierExemptionAction(carrierName, carrierId);
                             break;
                         case NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION:
                             handleUserDisallowCarrierExemptionAction(carrierName, carrierId);
                             break;
+                        case NOTIFICATION_USER_CLICKED_INTENT_ACTION:
+                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
+                            // Collapse the notification bar
+                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                            break;
                         case NOTIFICATION_USER_DISMISSED_INTENT_ACTION:
                             handleUserDismissAction();
                             return; // no need to cancel a dismissed notification, return.
@@ -297,8 +305,9 @@
         mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION);
+        mIntentFilter.addAction(NOTIFICATION_USER_CLICKED_INTENT_ACTION);
 
-        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler);
+        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, NETWORK_SETTINGS, handler);
         configStore.registerStoreData(wifiInjector.makeImsiProtectionExemptionStoreData(
                 new ImsiProtectionExemptionDataSource()));
 
@@ -442,9 +451,29 @@
         return matchSubId;
     }
 
+
+    private int getMatchingSubIdFromSimSlotIndex(int simSlotIndex) {
+        List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+        if (subInfoList == null || subInfoList.isEmpty()) {
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+
+        for (SubscriptionInfo subInfo : subInfoList) {
+            if (subInfo.getSimSlotIndex() == simSlotIndex)
+                return subInfo.getSubscriptionId();
+        }
+
+        return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
+
     private int getBestMatchSubscriptionIdForEnterprise(WifiConfiguration config) {
         if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
             return getMatchingSubId(config.carrierId);
+        } else if (config.enterpriseConfig != null
+                   && config.enterpriseConfig.getSimNum() != null
+                   && !config.enterpriseConfig.getSimNum().isEmpty()) {
+            int simSlotIndex = Integer.parseInt(config.enterpriseConfig.getSimNum());
+            return getMatchingSubIdFromSimSlotIndex(simSlotIndex - 1);
         }
         // Legacy WifiConfiguration without carrier ID
         if (config.enterpriseConfig == null
@@ -1448,6 +1477,9 @@
                 .setStyle(new Notification.BigTextStyle()
                         .bigText(mResources.getString(
                                 R.string.wifi_suggestion_imsi_privacy_content)))
+                .setContentIntent(getPrivateBroadcast(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                        Pair.create(EXTRA_CARRIER_NAME, carrierName),
+                        Pair.create(EXTRA_CARRIER_ID, carrierId)))
                 .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
                         Pair.create(EXTRA_CARRIER_NAME, carrierName),
                         Pair.create(EXTRA_CARRIER_ID, carrierId)))
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index a8bfc82..e50e169 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -17,6 +17,8 @@
 package com.android.server.wifi;
 
 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLE_REASON_INFOS;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WHITELIST_ROAMING_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -56,6 +58,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
 import com.android.server.wifi.util.LruConnectionTracker;
 import com.android.server.wifi.util.MissingCounterTimerLockList;
+import com.android.server.wifi.util.ScanResultUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 import com.android.wifi.resources.R;
@@ -313,7 +316,7 @@
      * This is keeping track of the next network ID to be assigned. Any new networks will be
      * assigned |mNextNetworkId| as network ID.
      */
-    private int mNextNetworkId = 0;
+    private static int mNextNetworkId = 0;
     /**
      * This is used to remember which network was selected successfully last by an app. This is set
      * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set.
@@ -475,23 +478,11 @@
      * @return persistent MAC address for this WifiConfiguration
      */
     private MacAddress getPersistentMacAddress(WifiConfiguration config) {
-        // mRandomizedMacAddressMapping had been the location to save randomized MAC addresses.
-        String persistentMacString = mRandomizedMacAddressMapping.get(
-                config.getKey());
-        // Use the MAC address stored in the storage if it exists and is valid. Otherwise
-        // use the MAC address calculated from a hash function as the persistent MAC.
-        if (persistentMacString != null) {
-            try {
-                return MacAddress.fromString(persistentMacString);
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "Error creating randomized MAC address from stored value.");
-                mRandomizedMacAddressMapping.remove(config.getKey());
-            }
-        }
-        MacAddress result = mMacAddressUtil.calculatePersistentMac(config.getKey(),
+        String key = config.getKey() + "-staId-" + config.staId;
+        MacAddress result = mMacAddressUtil.calculatePersistentMac(key,
                 mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID));
         if (result == null) {
-            result = mMacAddressUtil.calculatePersistentMac(config.getKey(),
+            result = mMacAddressUtil.calculatePersistentMac(key,
                     mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID));
         }
         if (result == null) {
@@ -502,6 +493,7 @@
                 result = MacAddressUtils.createRandomUnicastAddress();
             }
         }
+        Log.d(TAG, "Got persistent mac address for config=" + key + " mac=" + result);
         return result;
     }
 
@@ -1021,6 +1013,8 @@
             }
         }
 
+        internalConfig.shareThisAp = externalConfig.shareThisAp;
+
         // Copy over the |WifiEnterpriseConfig| parameters if set.
         if (externalConfig.enterpriseConfig != null) {
             internalConfig.enterpriseConfig.copyFromExternal(
@@ -1038,6 +1032,23 @@
         internalConfig.macRandomizationSetting = externalConfig.macRandomizationSetting;
         internalConfig.carrierId = externalConfig.carrierId;
         internalConfig.isHomeProviderNetwork = externalConfig.isHomeProviderNetwork;
+
+        // Copy over the DPP configuration parameters if set.
+        if (externalConfig.dppConnector != null) {
+            internalConfig.dppConnector = externalConfig.dppConnector;
+        }
+        if (externalConfig.dppNetAccessKey != null) {
+            internalConfig.dppNetAccessKey = externalConfig.dppNetAccessKey;
+        }
+        if (externalConfig.dppNetAccessKeyExpiry >= 0) {
+            internalConfig.dppNetAccessKeyExpiry = externalConfig.dppNetAccessKeyExpiry;
+        }
+        if (externalConfig.dppCsign != null) {
+            internalConfig.dppCsign = externalConfig.dppCsign;
+        }
+
+        // Copy auto connection enabled flag
+        internalConfig.isAutoConnectionEnabled = externalConfig.isAutoConnectionEnabled;
     }
 
     /**
@@ -1057,16 +1068,21 @@
 
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
         configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
 
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
         configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
 
         configuration.allowedGroupManagementCiphers
                 .set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
+        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_CMAC_256);
+
+        configuration.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
 
         configuration.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
         configuration.setProxySettings(IpConfiguration.ProxySettings.NONE);
@@ -1092,7 +1108,7 @@
 
         // First allocate a new network ID for the configuration.
         newInternalConfig.networkId = mNextNetworkId++;
-
+        newInternalConfig.staId = mWifiConfigStore.getStaId();
         // First set defaults in the new configuration created.
         setDefaultsInWifiConfiguration(newInternalConfig);
 
@@ -1106,7 +1122,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;
@@ -1775,7 +1790,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) {
@@ -2315,9 +2330,14 @@
         // Add the scan detail to this network's scan detail cache.
         scanDetailCache.put(scanDetail);
 
-        // Since we added a scan result to this configuration, re-attempt linking.
-        // TODO: Do we really need to do this after every scan result?
-        attemptNetworkLinking(config);
+        // Disable linking networks here when whitelist roaming feature enabled to make
+        // sure whitelist networks will be linked only when STA is in connected and
+        // internet access validated state.
+        if (!mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED)) {
+            // Since we added a scan result to this configuration, re-attempt linking.
+            // TODO: Do we really need to do this after every scan result?
+            attemptNetworkLinking(config);
+        }
     }
 
     /**
@@ -2485,7 +2505,9 @@
                 }
                 return true;
             }
-        } else {
+            // Don't link based on BSSID partial match when whitelist roaming feature enabled
+            // to make sure networks with different default gateways won't be linked.
+        } else if (!mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED)) {
             // We do not know BOTH default gateways hence we will try to link
             // hoping that WifiConfigurations are indeed behind the same gateway.
             // once both WifiConfiguration have been tried and thus once both default gateways
@@ -2584,6 +2606,9 @@
             if (linkConfig.ephemeral) {
                 continue;
             }
+            if (!linkConfig.getNetworkSelectionStatus().isNetworkEnabled()) {
+                continue;
+            }
             // Network Selector will be allowed to dynamically jump from a linked configuration
             // to another, hence only link configurations that have WPA_PSK security type.
             if (!linkConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
@@ -2902,14 +2927,22 @@
         // Remove any private networks of the old user before switching the userId.
         for (WifiConfiguration config : getConfiguredNetworks()) {
             if ((!config.shared && !mWifiPermissionsUtil
-                    .doesUidBelongToCurrentUser(config.creatorUid))) {
+                    .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();
@@ -2927,6 +2960,7 @@
             Map<String, String> macAddressMapping) {
         for (WifiConfiguration configuration : configurations) {
             configuration.networkId = mNextNetworkId++;
+            configuration.staId = mWifiConfigStore.getStaId();
             if (mVerboseLoggingEnabled) {
                 Log.v(TAG, "Adding network from shared store " + configuration.getKey());
             }
@@ -2948,6 +2982,7 @@
     private void loadInternalDataFromUserStore(List<WifiConfiguration> configurations) {
         for (WifiConfiguration configuration : configurations) {
             configuration.networkId = mNextNetworkId++;
+            configuration.staId = mWifiConfigStore.getStaId();
             if (mVerboseLoggingEnabled) {
                 Log.v(TAG, "Adding network from user store " + configuration.getKey());
             }
@@ -3041,7 +3076,7 @@
             Log.i(TAG, "Handling user unlock before loading from store.");
             List<WifiConfigStore.StoreFile> userStoreFiles =
                     WifiConfigStore.createUserFiles(
-                            mCurrentUserId, mFrameworkFacade.isNiapModeOn(mContext));
+                            mCurrentUserId, mFrameworkFacade.isNiapModeOn(mContext),mWifiConfigStore.getStaId());
             if (userStoreFiles == null) {
                 Log.wtf(TAG, "Failed to create user store files");
                 return false;
@@ -3054,10 +3089,8 @@
         } catch (IOException | IllegalStateException e) {
             Log.wtf(TAG, "Reading from new store failed. All saved networks are lost!", e);
             return false;
-        } catch (XmlPullParserException e) {
-            Log.wtf(TAG, "XML deserialization of store failed. All saved networks are lost!", e);
-            return false;
-        }
+        } // XmlPullParserException is handled by config store file itself.
+
         loadInternalData(mNetworkListSharedStoreData.getConfigurations(),
                 mNetworkListUserStoreData.getConfigurations(),
                 mRandomizedMacStoreData.getMacMapping());
@@ -3089,11 +3122,8 @@
         } catch (IOException | IllegalStateException e) {
             Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e);
             return false;
-        } catch (XmlPullParserException e) {
-            Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are "
-                    + "lost!", e);
-            return false;
-        }
+        } // XmlPullParserException is handled by config store file itself.
+
         loadInternalDataFromUserStore(mNetworkListUserStoreData.getConfigurations());
         return true;
     }
@@ -3293,4 +3323,210 @@
     public Comparator<WifiConfiguration> getScanListComparator() {
         return mScanListComparator;
     }
+
+    /**
+     * Retrieves the configured network corresponding to the provided configKey
+     * without any masking.
+     *
+     * WARNING: Don't use this to pass network configurations except in the wifi stack, when
+     * there is a need for passwords and randomized MAC address.
+     *
+     * @param configKey configKey of the requested network.
+     * @return Copy of WifiConfiguration object if found, null otherwise.
+     */
+    public WifiConfiguration getConfiguredNetworkWithoutMasking(String configKey) {
+        WifiConfiguration config = getInternalConfiguredNetwork(configKey);
+        if (config == null) {
+            return null;
+        }
+        return new WifiConfiguration(config);
+    }
+
+    /**
+     * This method runs through all the saved networks and checks if the provided network can be
+     * linked with any of them.
+     *
+     * @param networkId networkId corresponding to the network that needs to be
+     *               checked for potential links.
+     */
+    public HashMap<String, Integer> updateAndGetLinkedConfiguration(int networkId) {
+        if (networkId == WifiConfiguration.INVALID_NETWORK_ID) {
+            return null;
+        }
+
+        WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(networkId);
+        if (internalConfig == null) {
+            Log.e(TAG, "Cannot find network with networkId " + networkId);
+            return null;
+        }
+
+        internalConfig.linkedConfigurations = new HashMap<>();
+        attemptNetworkLinking(internalConfig);
+
+        return new HashMap<String, Integer>(internalConfig.linkedConfigurations);
+    }
+
+    private String getLowerCaseSsidPrefix(String ssid, String suffix) {
+         if (ssid == null || suffix == null) {
+             return null;
+         }
+
+         String ssidLower = ssid.toLowerCase();
+         String suffixLower = suffix.toLowerCase();
+         int suffixIndex = ssidLower.indexOf(suffixLower);
+         if (suffixIndex < 1) {
+             return null;
+         }
+
+         return ssidLower.substring(0, suffixIndex);
+    }
+
+    private boolean isQualifiedForNetworkLinking(WifiConfiguration config, String currentBssid) {
+        if (config == null || config.ephemeral)
+            return false;
+
+        // config AKM should be PSK
+        if (!WifiConfigurationUtil.isConfigForPskNetwork(config))
+            return false;
+
+
+        // SSID should contain "2g"/"2G" with valid prefix
+        if (getLowerCaseSsidPrefix(config.getPrintableSsid(), "2g") == null) {
+            return false;
+        }
+
+        // no.of bssids of the SSID in scan cache should be less than configured limit
+        ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(config.networkId);
+        if (scanDetailCache == null || scanDetailCache.size() == 0 ||
+            scanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) {
+            return false;
+        }
+
+        // current BSSID shouldn't be 5G network
+        if (currentBssid != null) {
+            ScanDetail scanDetail = scanDetailCache.getScanDetail(currentBssid);
+            if (scanDetail != null) {
+                ScanResult result = scanDetail.getScanResult();
+                if (result.is5GHz())
+                    return false;
+            }
+        }
+
+        // no 5Ghz bssid should present in scan cache
+        for (ScanDetail scanDetail : scanDetailCache.values()) {
+            ScanResult result = scanDetail.getScanResult();
+            if (result.is5GHz())
+                return false;
+        }
+
+        return true;
+    }
+
+    public void addOrUpdateAutoConnectNetworks(int networkId, String currentBssid,
+                    List<ScanDetail> scanDetails) {
+        if (!mWifiInjector.getSettingsConfigStore().get(WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED)) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "Auto connecting new networks disabled");
+            }
+            return;
+        }
+
+        // clear auto connection enabled flag for all netwroks
+        for (WifiConfiguration config : getInternalConfiguredNetworks()) {
+            config.isAutoConnectionEnabled = false;
+        }
+
+        WifiConfiguration currentConfig = getInternalConfiguredNetwork(networkId);
+        if (currentConfig == null || currentBssid == null || scanDetails == null
+            || !isQualifiedForNetworkLinking(currentConfig, currentBssid)) {
+            return;
+        }
+
+        String ssid2gPrefix = getLowerCaseSsidPrefix(currentConfig.getPrintableSsid(), "2g");
+        Log.i(TAG, "ssid2gPrefix = " + ssid2gPrefix);
+
+        for (ScanDetail scanDetail : scanDetails) {
+            ScanResult scanResult = scanDetail.getScanResult();
+            if (scanResult.is24GHz() || !ScanResultUtil.isScanResultForPskNetwork(scanResult))
+                continue;
+
+            if (!currentBssid.regionMatches(true, 0, scanResult.BSSID, 0,
+                     LINK_CONFIGURATION_BSSID_MATCH_LENGTH))
+                continue;
+
+             // SSID should contain "5g"/"5G" with valid prefix
+            String ssid5gPrefix = getLowerCaseSsidPrefix(scanResult.SSID, "5g");
+            Log.i(TAG, "ssid5gPrefix: " + ssid5gPrefix);
+            if(ssid5gPrefix == null || !ssid5gPrefix.equals(ssid2gPrefix)) {
+                continue;
+            }
+
+            WifiConfiguration config = getConfiguredNetworkForScanDetail(scanDetail);
+            if (config != null) {
+                if (config.ephemeral && config.getNetworkSelectionStatus().isNetworkEnabled()) {
+                    config.isAutoConnectionEnabled = true;
+                }
+                continue;
+            }
+
+            WifiConfiguration ephemeralConfig =
+                     ScanResultUtil.createNetworkFromScanResult(scanResult);
+
+            ephemeralConfig.staId = currentConfig.staId;
+            ephemeralConfig.ephemeral = true;
+            ephemeralConfig.isAutoConnectionEnabled = true;
+            ephemeralConfig.creatorUid = currentConfig.creatorUid;
+            ephemeralConfig.creatorName = currentConfig.creatorName;
+            ephemeralConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+            ephemeralConfig.requirePmf = false;
+            ephemeralConfig.preSharedKey = currentConfig.preSharedKey;
+            ephemeralConfig.noInternetAccessExpected = currentConfig.noInternetAccessExpected;
+            ephemeralConfig.setIpConfiguration(new IpConfiguration(currentConfig.getIpConfiguration()));
+            NetworkUpdateResult result = addOrUpdateNetwork(ephemeralConfig, currentConfig.creatorUid);
+            if (!result.isSuccess()) {
+                Log.e(TAG, "Failed to add ephemeral network" + ephemeralConfig.getKey());
+                continue;
+            }
+            if (!updateNetworkSelectionStatus(result.getNetworkId(),
+                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED)) {
+                Log.e(TAG, "Failed to make ephemeral network "
+                                + ephemeralConfig.getKey() + " selectable");
+                continue;
+            }
+
+            WifiConfiguration internalConfig = getInternalConfiguredNetwork(result.getNetworkId());
+
+            if (internalConfig == null) {
+                Log.e(TAG, "Failed to fetch configured ephemeral network "
+                                + ephemeralConfig.getKey());
+                continue;
+            }
+
+            Log.i(TAG, "added ephemeral network " + internalConfig.getKey()
+                        + " to attempt auto connection with credentials of " + currentConfig.getKey());
+        }
+    }
+
+    public boolean saveAutoConnectedNewNetwork(int networkId) {
+         WifiConfiguration internalConfig = getInternalConfiguredNetwork(networkId);
+        if (internalConfig == null || !internalConfig.ephemeral
+                    || !internalConfig.isAutoConnectionEnabled) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "Auto connect network not found!");
+            }
+            return false;
+        }
+
+        internalConfig.ephemeral = false;
+        internalConfig.isAutoConnectionEnabled = false;
+
+        saveToStore(true);
+        sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_ADDED);
+        for (OnNetworkUpdateListener listener : mListeners) {
+            listener.onNetworkAdded(
+                    createExternalWifiConfiguration(internalConfig, true, Process.WIFI_UID));
+        }
+
+        return true;
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index 2853bba..cbf52da 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -17,7 +17,8 @@
 package com.android.server.wifi;
 
 import static java.lang.Math.toIntExact;
-
+import static android.net.wifi.WifiManager.STA_PRIMARY;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -91,16 +92,32 @@
      * Config store file for general user store file.
      */
     public static final int STORE_FILE_USER_GENERAL = 2;
-    /**
-     * Config store file for network suggestions user store file.
+     /**
+	 * Config store file for network suggestions user store file.
      */
     public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3;
 
+    /**
+     * Config store file for Secondary shared store file.
+     */
+    public static final int QTI_STORE_FILE_SHARED_SECONDARY = 4;
+    /**
+     * Config store file for secondary user store file.
+     */
+    public static final int QTI_STORE_FILE_USER_SECONDARY = 5;
+    /**
+     * mStaId: Identity of station.
+     * Can be WifiManafer.STA_PRIMARY or WifiManafer.STA_SECONDARY
+     */
+    private int mStaId = STA_PRIMARY;
+
     @IntDef(prefix = { "STORE_FILE_" }, value = {
             STORE_FILE_SHARED_GENERAL,
             STORE_FILE_SHARED_SOFTAP,
             STORE_FILE_USER_GENERAL,
-            STORE_FILE_USER_NETWORK_SUGGESTIONS
+            STORE_FILE_USER_NETWORK_SUGGESTIONS,
+            QTI_STORE_FILE_SHARED_SECONDARY,
+            QTI_STORE_FILE_USER_SECONDARY
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface StoreFileId { }
@@ -170,6 +187,14 @@
     private static final String STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS =
             "WifiConfigStoreNetworkSuggestions.xml";
     /**
+     * Config store file name string for Secondary shared store file.
+     */
+    private static String QTI_STORE_FILE_NAME_SHARED_SECONDARY = "QtiWifiConfigStore_2.xml";
+    /**
+     * Config store file name string for general user store file.
+     */
+    private static String QTI_STORE_FILE_NAME_USER_SECONDARY= "QtiWifiConfigStore_2.xml";
+    /**
      * Mapping of Store file Id to Store file names.
      */
     private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
@@ -178,6 +203,8 @@
                 put(STORE_FILE_SHARED_SOFTAP, STORE_FILE_NAME_SHARED_SOFTAP);
                 put(STORE_FILE_USER_GENERAL, STORE_FILE_NAME_USER_GENERAL);
                 put(STORE_FILE_USER_NETWORK_SUGGESTIONS, STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS);
+                put(QTI_STORE_FILE_SHARED_SECONDARY,QTI_STORE_FILE_NAME_SHARED_SECONDARY);
+                put(QTI_STORE_FILE_USER_SECONDARY,QTI_STORE_FILE_NAME_USER_SECONDARY);
             }};
     /**
      * Handler instance to post alarm timeouts to
@@ -193,13 +220,13 @@
     private final Clock mClock;
     private final WifiMetrics mWifiMetrics;
     /**
-     * Shared config store file instance. There are 2 shared store files:
-     * {@link #STORE_FILE_NAME_SHARED_GENERAL} & {@link #STORE_FILE_NAME_SHARED_SOFTAP}.
+     * Shared config store file instance. There are 3 shared store files:
+     * {@link #STORE_FILE_NAME_SHARED_GENERAL},{@link #QTI_STORE_FILE_NAME_SHARED_SECONDARY}  & {@link #STORE_FILE_NAME_SHARED_SOFTAP}.
      */
     private final List<StoreFile> mSharedStores;
     /**
-     * User specific store file instances. There are 2 user store files:
-     * {@link #STORE_FILE_NAME_USER_GENERAL} & {@link #STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS}.
+     * User specific store file instances. There are 3 user store files:
+     * {@link #STORE_FILE_NAME_USER_GENERAL}, {@link #QTI_STORE_FILE_NAME_USER_SECONDARY}  & {@link #STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS}.
      */
     private List<StoreFile> mUserStores;
     /**
@@ -258,6 +285,37 @@
     }
 
     /**
+     * Create a new instance of WifiConfigStore.
+     *
+     * @param context     context to use for retrieving the alarm manager.
+     * @param looper      looper instance to post alarm timeouts to.
+     * @param clock       clock instance to retrieve timestamps for alarms.
+     * @param wifiMetrics Metrics instance.
+     * @param staId: Station Identity.
+     */
+    public WifiConfigStore(Context context, Handler handler, Clock clock, WifiMetrics wifiMetrics,
+            boolean shouldEncryptCredentials, int staId) {
+        Log.e(TAG,":Enter staId = "+ staId);
+        mStaId = staId;
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mEventHandler = handler;
+        mClock = clock;
+        mWifiMetrics = wifiMetrics;
+        mStoreDataList = new ArrayList<>();
+
+        // Initialize the store files.
+        mSharedStores = createSharedFiles(shouldEncryptCredentials, staId);
+        // The user store is initialized to null, this will be set when the user unlocks and
+        // CE storage is accessible via |switchUserStoresAndRead|.
+        mUserStores = null;
+    }
+
+    public int getStaId()
+    {
+        return mStaId;
+    }
+
+    /**
      * Set the user store files.
      * (Useful for mocking in unit tests).
      * @param userStores List of {@link StoreFile} created using
@@ -281,7 +339,7 @@
             Log.e(TAG, "Unable to register null store data");
             return false;
         }
-        int storeFileId = storeData.getStoreFileId();
+        int storeFileId = storeData.getStoreFileId(mStaId);
         if (STORE_ID_TO_FILE_NAME.get(storeFileId) == null) {
             Log.e(TAG, "Invalid shared store file specified" + storeFileId);
             return false;
@@ -338,13 +396,22 @@
      * @param shouldEncryptCredentials Whether to encrypt credentials or not.
      * @return new instance of the store file or null if the directory cannot be created.
      */
-    public static @NonNull List<StoreFile> createSharedFiles(boolean shouldEncryptCredentials) {
+    public static @NonNull List<StoreFile> createSharedFiles(boolean shouldEncryptCredentials, int staId) {
+        List<Integer> fileIds;
+        if(staId == STA_SECONDARY) {
+            fileIds = Arrays.asList(QTI_STORE_FILE_SHARED_SECONDARY);
+        } else {
+            fileIds = Arrays.asList(STORE_FILE_SHARED_GENERAL, STORE_FILE_SHARED_SOFTAP);
+        }
         return createFiles(
                 Environment.getWifiSharedDirectory(),
-                Arrays.asList(STORE_FILE_SHARED_GENERAL, STORE_FILE_SHARED_SOFTAP),
+                fileIds,
                 UserHandle.ALL,
                 shouldEncryptCredentials);
     }
+    public static @NonNull List<StoreFile> createSharedFiles(boolean shouldEncryptCredentials) {
+        return createSharedFiles(shouldEncryptCredentials, STA_PRIMARY);
+    }
 
     /**
      * Create new instances of the user specific store files.
@@ -355,16 +422,24 @@
      * @return List of new instances of the store files created or null if the directory cannot be
      * created.
      */
-    public static @Nullable List<StoreFile> createUserFiles(int userId,
-            boolean shouldEncryptCredentials) {
+    public static @Nullable List<StoreFile> createUserFiles(int userId,boolean shouldEncryptCredentials, int staId) {
         UserHandle userHandle = UserHandle.of(userId);
+        List<Integer> fileIds;
+        if (staId == STA_SECONDARY) {
+            fileIds = Arrays.asList(QTI_STORE_FILE_USER_SECONDARY);
+        } else {
+            fileIds = Arrays.asList(STORE_FILE_USER_GENERAL, STORE_FILE_USER_NETWORK_SUGGESTIONS);
+        }
         return createFiles(
                 Environment.getWifiUserDirectory(userId),
-                Arrays.asList(STORE_FILE_USER_GENERAL, STORE_FILE_USER_NETWORK_SUGGESTIONS),
+                fileIds,
                 userHandle,
                 shouldEncryptCredentials);
     }
 
+    public static @Nullable List<StoreFile> createUserFiles(int userId, boolean shouldEncryptCredentials) {
+        return createUserFiles(userId, shouldEncryptCredentials, STA_PRIMARY);
+    }
     /**
      * Enable verbose logging.
      */
@@ -379,7 +454,7 @@
     private List<StoreData> retrieveStoreDataListForStoreFile(@NonNull StoreFile storeFile) {
         return mStoreDataList
                 .stream()
-                .filter(s -> s.getStoreFileId() == storeFile.getFileId())
+                .filter(s -> s.getStoreFileId(mStaId) == storeFile.getFileId())
                 .collect(Collectors.toList());
     }
 
@@ -586,10 +661,9 @@
 
     /**
      * Helper method to read from the shared store files.
-     * @throws XmlPullParserException
      * @throws IOException
      */
-    private void readFromSharedStoreFiles() throws XmlPullParserException, IOException {
+    private void readFromSharedStoreFiles() throws IOException {
         for (StoreFile sharedStoreFile : mSharedStores) {
             byte[] sharedDataBytes =
                     readDataFromMigrationSharedStoreFile(sharedStoreFile.getFileId());
@@ -608,16 +682,23 @@
                 WifiMigration.removeSharedConfigStoreFile(
                         getMigrationStoreFileId(sharedStoreFile.getFileId()));
             }
-            deserializeData(sharedDataBytes, sharedStoreFile);
+
+            try {
+                deserializeData(sharedDataBytes, sharedStoreFile);
+            } catch (XmlPullParserException e) {
+                Log.wtf(TAG, "XML deserialization of shared store file "
+                        + sharedStoreFile.getName()
+                        + " failed. All saved networks are lost!", e);
+                sharedStoreFile.recovery();
+            }
         }
     }
 
     /**
      * Helper method to read from the user store files.
-     * @throws XmlPullParserException
      * @throws IOException
      */
-    private void readFromUserStoreFiles() throws XmlPullParserException, IOException {
+    private void readFromUserStoreFiles() throws IOException {
         for (StoreFile userStoreFile : mUserStores) {
             byte[] userDataBytes = readDataFromMigrationUserStoreFile(
                     userStoreFile.getFileId(), userStoreFile.mUserHandle);
@@ -637,7 +718,15 @@
                         getMigrationStoreFileId(userStoreFile.getFileId()),
                         userStoreFile.mUserHandle);
             }
-            deserializeData(userDataBytes, userStoreFile);
+
+            try {
+                deserializeData(userDataBytes, userStoreFile);
+            } catch (XmlPullParserException e) {
+                Log.wtf(TAG, "XML deserialization of shared store file "
+                        + userStoreFile.getName()
+                        + " failed. All saved networks are lost!", e);
+                userStoreFile.recovery();
+            }
         }
     }
 
@@ -646,7 +735,7 @@
      * The method reads the user specific configurations from user specific config store and the
      * shared configurations from the shared config store.
      */
-    public void read() throws XmlPullParserException, IOException {
+    public void read() throws IOException {
         // Reset both share and user store data.
         for (StoreFile sharedStoreFile : mSharedStores) {
             resetStoreData(sharedStoreFile);
@@ -677,7 +766,7 @@
      * @param userStores List of {@link StoreFile} created using {@link #createUserFiles(int)}.
      */
     public void switchUserStoresAndRead(@NonNull List<StoreFile> userStores)
-            throws XmlPullParserException, IOException {
+            throws IOException {
         Preconditions.checkNotNull(userStores);
         // Reset user store data.
         if (mUserStores != null) {
@@ -826,9 +915,9 @@
             pw.print(" ");
             pw.print("Name: " + storeData.getName());
             pw.print(", ");
-            pw.print("File Id: " + storeData.getStoreFileId());
+            pw.print("File Id: " + storeData.getStoreFileId(mStaId));
             pw.print(", ");
-            pw.println("File Name: " + STORE_ID_TO_FILE_NAME.get(storeData.getStoreFileId()));
+            pw.println("File Name: " + STORE_ID_TO_FILE_NAME.get(storeData.getStoreFileId(mStaId)));
         }
         pw.println("WifiConfigStore - Store Data End ----");
     }
@@ -880,6 +969,11 @@
             mEncryptionUtil = encryptionUtil;
         }
 
+        public void recovery() {
+            File savedErrorFile = new File(mAtomicFile.getBaseFile().getPath() + ".err");
+            FileUtils.rename(mAtomicFile.getBaseFile(), savedErrorFile);
+        }
+
         public String getName() {
             return mAtomicFile.getBaseFile().getName();
         }
@@ -1014,6 +1108,8 @@
          * This should be one of {@link #STORE_FILE_SHARED_GENERAL},
          * {@link #STORE_FILE_USER_GENERAL} or
          * {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}.
+         * {@link #QTI_STORE_FILE_SHARED_SECONDARY}
+         * {@link #QTI_STORE_FILE_USER_SECONDARY}
          *
          * Note: For most uses, the shared or user general store is sufficient. Creating and
          * managing store files are expensive. Only use specific store files if you have a large
@@ -1022,5 +1118,11 @@
          * @return Id of the file where this data needs to be persisted.
          */
         @StoreFileId int getStoreFileId();
+        default @StoreFileId int getStoreFileId(int staId)
+        {
+            if (staId == STA_SECONDARY)
+                return QTI_STORE_FILE_USER_SECONDARY;
+            return STORE_FILE_USER_GENERAL;
+        }
     }
 }
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index b12b816..3432c8f 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -56,7 +56,8 @@
      */
     private static final int ENCLOSING_QUOTES_LEN = 2;
     private static final int SSID_UTF_8_MIN_LEN = 1 + ENCLOSING_QUOTES_LEN;
-    private static final int SSID_UTF_8_MAX_LEN = 32 + ENCLOSING_QUOTES_LEN;
+    private static final int SSID_UTF_8_MAX_LEN = // wifigbk++
+                        WifiGbk.MAX_SSID_UTF_LENGTH + ENCLOSING_QUOTES_LEN;
     private static final int SSID_HEX_MIN_LEN = 2;
     private static final int SSID_HEX_MAX_LEN = 64;
     private static final int PSK_ASCII_MIN_LEN = 8 + ENCLOSING_QUOTES_LEN;
@@ -224,16 +225,23 @@
             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;
             }
+            if (getEapSimNum(existingEnterpriseConfig) != getEapSimNum(newEnterpriseConfig)){
+                return true;
+            }
             if (!TextUtils.equals(existingEnterpriseConfig.getIdentity(),
                                   newEnterpriseConfig.getIdentity())) {
                 return true;
             }
-            if (!existingEnterpriseConfig.isAuthenticationSimBased()
-                    && !TextUtils.equals(existingEnterpriseConfig.getAnonymousIdentity(),
+            if (!TextUtils.equals(existingEnterpriseConfig.getAnonymousIdentity(),
                     newEnterpriseConfig.getAnonymousIdentity())) {
                 return true;
             }
@@ -246,6 +254,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) {
@@ -255,6 +278,15 @@
         return false;
     }
 
+    public static int getEapSimNum(WifiEnterpriseConfig enterpriseConfig){
+        int mSimNum =0;
+        if (enterpriseConfig.getSimNum() != null
+                             && !enterpriseConfig.getSimNum().isEmpty()) {
+            mSimNum = Integer.parseInt(enterpriseConfig.getSimNum());
+        }
+        return mSimNum;
+    }
+
     /**
      * Compare existing and new WifiConfiguration objects after a network update and return if
      * credential parameters have changed or not.
@@ -307,6 +339,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/WifiConnectivityHelper.java b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
index 248877f..136d8ca 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
@@ -18,6 +18,7 @@
 
 import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING;
 
+import android.annotation.NonNull;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -39,9 +40,11 @@
     private boolean mFirmwareRoamingSupported = false;
     private int mMaxNumBlacklistBssid = INVALID_LIST_SIZE;
     private int mMaxNumWhitelistSsid = INVALID_LIST_SIZE;
+    private String mInterfaceName;
 
     WifiConnectivityHelper(WifiNative wifiNative) {
         mWifiNative = wifiNative;
+        mInterfaceName = null;
     }
 
     /**
@@ -60,7 +63,7 @@
         mMaxNumWhitelistSsid = INVALID_LIST_SIZE;
 
         long fwFeatureSet =
-                mWifiNative.getSupportedFeatureSet(mWifiNative.getClientInterfaceName());
+                mWifiNative.getSupportedFeatureSet(getInterfaceName());
         Log.d(TAG, "Firmware supported feature set: " + Long.toHexString(fwFeatureSet));
 
         if ((fwFeatureSet & WIFI_FEATURE_CONTROL_ROAMING) == 0) {
@@ -69,7 +72,7 @@
         }
 
         WifiNative.RoamingCapabilities roamingCap = new WifiNative.RoamingCapabilities();
-        if (mWifiNative.getRoamingCapabilities(mWifiNative.getClientInterfaceName(), roamingCap)) {
+        if (mWifiNative.getRoamingCapabilities(getInterfaceName(), roamingCap)) {
             if (roamingCap.maxBlacklistSize < 0 || roamingCap.maxWhitelistSize < 0) {
                 Log.e(TAG, "Invalid firmware roaming capabilities: max num blacklist bssid="
                         + roamingCap.maxBlacklistSize + " max num whitelist ssid="
@@ -160,6 +163,20 @@
         roamConfig.blacklistBssids = blacklistBssids;
         roamConfig.whitelistSsids = whitelistSsids;
 
-        return mWifiNative.configureRoaming(mWifiNative.getClientInterfaceName(), roamConfig);
+        return mWifiNative.configureRoaming(getInterfaceName(), roamConfig);
+    }
+    /**
+     * Set interface name to be used for helper methods in this class.
+     *
+     * @param iface interface name to be used for WifiNative API calls.
+     */
+    public void setInterfaceName(@NonNull String iface) {
+        mInterfaceName = iface;
+    }
+
+    private String getInterfaceName() {
+        return (mInterfaceName == null) ?
+                  mWifiNative.getClientInterfaceName() :
+                  mInterfaceName;
     }
 }
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 2ce0bc0..63815d8 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WHITELIST_ROAMING_ENABLED;
 
 import android.annotation.NonNull;
 import android.app.AlarmManager;
@@ -31,6 +32,7 @@
 import android.net.wifi.WifiManager.DeviceMobilityState;
 import android.net.wifi.WifiNetworkSuggestion;
 import android.net.wifi.WifiScanner;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.net.wifi.WifiScanner.PnoSettings;
 import android.net.wifi.WifiScanner.ScanSettings;
 import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -160,6 +162,7 @@
     private boolean mAutoJoinEnabled = false; // disabled by default, enabled by external triggers
     private boolean mRunning = false;
     private boolean mScreenOn = false;
+    private int mMiracastMode = WifiP2pManager.MIRACAST_DISABLED;
     private int mWifiState = WIFI_STATE_UNKNOWN;
     private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE;
     private boolean mAutoJoinEnabledExternal = true; // enabled by default
@@ -175,6 +178,8 @@
     private boolean mPnoScanStarted = false;
     private boolean mPeriodicScanTimerSet = false;
     private boolean mDelayedPartialScanTimerSet = false;
+    private boolean mAllowConnectionOnPartialScanResults = false;
+    private boolean mWasLastConnectionAttemptedWithPartialResults = false;
 
     // Used for Initial Scan metrics
     private boolean mFailedInitialPartialScan = false;
@@ -297,14 +302,16 @@
      *         false - if no candidate is selected by WifiNetworkSelector
      */
     private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName,
-            boolean isFullScan) {
+            boolean isFullScan, boolean isPartialScanResults) {
         mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(
                 mStateMachine.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ);
 
         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
@@ -313,10 +320,31 @@
             return false;
         }
 
+        if (isPartialScanResults) {
+            if (!mContext.getResources().getBoolean(
+                    R.bool.config_wifi_framework_enable_quick_connect)) {
+                return false;
+            }
+            if (mAllowConnectionOnPartialScanResults ||
+                 ((mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan))
+                   && (mInitialScanState != INITIAL_SCAN_STATE_COMPLETE))) {
+                return false;
+            }
+        }
+        if (mStateMachine.isDisconnected()) {
+            mWasLastConnectionAttemptedWithPartialResults = false;
+        }
+        // Do not select network with partial network if we are already connected
+        if (isPartialScanResults && (mStateMachine.isConnected() ||
+            mWasLastConnectionAttemptedWithPartialResults)) {
+            return false;
+        }
+
         localLog(listenerName + " onResults: start network selection");
 
+        List<ScanDetail> filteredScans = mStateMachine.qtiGetFilteredScan(scanDetails);
         List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan(
-                scanDetails, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(),
+                filteredScans, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(),
                 mStateMachine.isDisconnected(), mUntrustedConnectionAllowed);
         mLatestCandidates = candidates;
         mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis();
@@ -335,6 +363,7 @@
         if (candidate != null) {
             localLog(listenerName + ":  WNS candidate-" + candidate.SSID);
             connectToNetwork(candidate);
+            mWasLastConnectionAttemptedWithPartialResults = isPartialScanResults;
             return true;
         } else {
             if (mWifiState == WIFI_STATE_DISCONNECTED) {
@@ -452,6 +481,7 @@
     private class AllSingleScanListener implements WifiScanner.ScanListener {
         private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>();
         private int mNumScanResultsIgnoredDueToSingleRadioChain = 0;
+        private boolean mPartialScanResults = false;
 
         public void clearScanDetails() {
             mScanDetails.clear();
@@ -505,7 +535,7 @@
                         + mNumScanResultsIgnoredDueToSingleRadioChain);
             }
             boolean wasConnectAttempted = handleScanResults(mScanDetails,
-                    ALL_SINGLE_SCAN_LISTENER, isFullBandScanResults);
+                    ALL_SINGLE_SCAN_LISTENER, isFullBandScanResults, mPartialScanResults);
             clearScanDetails();
 
             // Update metrics to see if a single scan detected a valid network
@@ -524,6 +554,11 @@
             if (mInitialScanState == INITIAL_SCAN_STATE_AWAITING_RESPONSE) {
                 // Done with initial scan
                 setInitialScanState(INITIAL_SCAN_STATE_COMPLETE);
+                if (!wasConnectAttempted && mPartialScanResults) {
+                    Log.i(TAG, "Connection not attempted with the reduced initial scans, due "
+                          + "to partial scan timer");
+                    return;
+                }
 
                 if (wasConnectAttempted) {
                     Log.i(TAG, "Connection attempted with the reduced initial scans");
@@ -547,6 +582,14 @@
         }
 
         @Override
+        public void onPartialScanResults(WifiScanner.ScanData[] scanDatas) {
+            Log.d(TAG, "onPartialScanResults invoked");
+            mPartialScanResults = true;
+            onResults(scanDatas);
+            mPartialScanResults = false;
+        }
+
+        @Override
         public void onFullResult(ScanResult fullScanResult) {
             if (!mWifiEnabled || !mAutoJoinEnabled) {
                 return;
@@ -692,7 +735,7 @@
             }
 
             boolean wasConnectAttempted;
-            wasConnectAttempted = handleScanResults(mScanDetails, PNO_SCAN_LISTENER, false);
+            wasConnectAttempted = handleScanResults(mScanDetails, PNO_SCAN_LISTENER, false, false);
             clearScanDetails();
             mScanRestartCount = 0;
 
@@ -920,7 +963,8 @@
         if (currentConnectedNetwork != null
                 && (currentConnectedNetwork.networkId == candidate.networkId
                 //TODO(b/36788683): re-enable linked configuration check
-                /* || currentConnectedNetwork.isLinked(candidate) */)) {
+                 || (mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED)
+                      && currentConnectedNetwork.isLinked(candidate)))) {
             // Framework initiates roaming only if firmware doesn't support
             // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING}.
             if (mConnectivityHelper.isFirmwareRoamingSupported()) {
@@ -936,7 +980,7 @@
             // Framework specifies the connection target BSSID if firmware doesn't support
             // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING} or the
             // candidate configuration contains a specified BSSID.
-            if (mConnectivityHelper.isFirmwareRoamingSupported() && (candidate.BSSID == null
+            if (!mStateMachine.isActiveDualMode() && mConnectivityHelper.isFirmwareRoamingSupported() && (candidate.BSSID == null
                       || candidate.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY))) {
                 targetBssid = ClientModeImpl.SUPPLICANT_BSSID_ANY;
                 localLog("connectToNetwork: Connect to " + candidate.SSID + ":" + targetBssid
@@ -1158,6 +1202,13 @@
                     setInitialScanState(INITIAL_SCAN_STATE_AWAITING_RESPONSE);
                     mWifiMetrics.incrementInitialPartialScanCount();
                 }
+
+                // Scheduling for scan if initial scan skipped
+                if (mInitialScanState == INITIAL_SCAN_STATE_COMPLETE) {
+                    schedulePeriodicScanTimer(
+                        getScheduledSingleScanIntervalMs(mCurrentSingleScanScheduleIndex));
+                }
+
                 // No scheduling for another scan (until we get the results)
                 return;
             }
@@ -1253,6 +1304,17 @@
 
     // Start a single scan
     private void startForcedSingleScan(boolean isFullBandScan, WorkSource workSource) {
+        // Any scans will impact wifi performance including WFD performance,
+        // So at least ignore scans triggered internally by ConnectivityManager
+        // when WFD session is active. We still allow connectivity scans initiated
+        // by other work source.
+        if (WIFI_WORK_SOURCE.equals(workSource) &&
+            (mMiracastMode == WifiP2pManager.MIRACAST_SOURCE ||
+            mMiracastMode == WifiP2pManager.MIRACAST_SINK)) {
+            Log.d(TAG,"ignore connectivity scan, MiracastMode:" + mMiracastMode);
+            return;
+        }
+
         mPnoScanListener.resetLowRssiNetworkRetryDelay();
 
         ScanSettings settings = new ScanSettings();
@@ -1584,6 +1646,15 @@
     }
 
     /**
+     * Save current miracast mode, it will be used to ignore
+     * connectivity scan during the time when miracast is enabled.
+     */
+    public void saveMiracastMode(int mode) {
+        Log.d(TAG,"saveMiracastMode: mode=" + mode);
+        mMiracastMode = mode;
+    }
+
+    /**
      * Helper function that converts the WIFI_STATE_XXX constants to string
      */
     private static String stateToString(int state) {
@@ -1758,7 +1829,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) {
@@ -1924,6 +1996,7 @@
         if (mWifiEnabled && !enable) {
             mNetworkSelector.resetOnDisable();
             mBssidBlocklistMonitor.clearBssidBlocklist();
+            mWasLastConnectionAttemptedWithPartialResults = false;
         }
         mWifiEnabled = enable;
         updateRunningState();
@@ -1949,6 +2022,12 @@
         }
     }
 
+    /**
+     * Allow quick connect with partial scan results
+     */
+    public void allowConnectOnPartialScanResults(boolean enable) {
+        mAllowConnectionOnPartialScanResults = enable;
+    }
     @VisibleForTesting
     int getLowRssiNetworkRetryDelay() {
         return mPnoScanListener.getLowRssiNetworkRetryDelay();
diff --git a/service/java/com/android/server/wifi/WifiCountryCode.java b/service/java/com/android/server/wifi/WifiCountryCode.java
index 3d05571..c686624 100644
--- a/service/java/com/android/server/wifi/WifiCountryCode.java
+++ b/service/java/com/android/server/wifi/WifiCountryCode.java
@@ -20,7 +20,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.wifi.WifiManager;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -80,6 +82,12 @@
         Log.d(TAG, "mDefaultCountryCode " + mDefaultCountryCode);
     }
 
+    public WifiCountryCode(
+            WifiNative wifiNative,
+            String oemDefaultCountryCode) {
+        this(null, null, wifiNative, oemDefaultCountryCode);
+    }
+
     /**
      * Enable verbose logging for WifiCountryCode.
      */
@@ -91,6 +99,18 @@
         }
     }
 
+    private void sendCountryCodeChangedBroadcast() {
+        if (mContext == null) {
+            return;
+        }
+
+        Log.d(TAG, "sending WIFI_COUNTRY_CODE_CHANGED_ACTION");
+        Intent intent = new Intent(WifiManager.WIFI_COUNTRY_CODE_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_COUNTRY_CODE, getCountryCode());
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
     private void initializeTelephonyCountryCodeIfNeeded() {
         // If we don't have telephony country code set yet, poll it.
         if (mTelephonyCountryCode == null) {
@@ -192,7 +212,7 @@
         } else {
             Log.d(TAG, "skip update supplicant not ready yet");
         }
-
+        sendCountryCodeChangedBroadcast();
         return true;
     }
 
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index 6fc75c6..f50f0e3 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -24,6 +24,10 @@
 import android.util.Base64;
 import android.util.Log;
 import android.util.SparseLongArray;
+import android.content.Intent;
+
+import android.net.wifi.WifiManager;
+import android.os.UserHandle;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.wifi.util.ByteArrayRingBuffer;
@@ -61,7 +65,7 @@
      */
 
     private static final String TAG = "WifiDiags";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /** log level flags; keep these consistent with wifi_logger.h */
 
@@ -91,6 +95,10 @@
     public static final int REPORT_REASON_WIFINATIVE_FAILURE        = 8;
     public static final int REPORT_REASON_REACHABILITY_LOST         = 9;
     public static final int REPORT_REASON_FATAL_FW_ALERT            = 10;
+    public static final int REPORT_REASON_NUD_FAILURE               = 11;
+
+    /** Data stall offset */
+    private static final int  DATA_STALL_OFFSET_REASON_CODE         = 256;
 
     /** number of bug reports to hold */
     public static final int MAX_BUG_REPORTS                         = 4;
@@ -226,6 +234,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 +248,6 @@
             // the log handler is in an indeterminate state.
             mIsLoggingEventHandlerRegistered = false;
         }
-        if (mLogLevel != VERBOSE_NO_LOG) {
-            stopLoggingAllBuffers();
-            mRingBuffers = null;
-        }
     }
 
     @Override
@@ -471,9 +479,13 @@
     }
 
     synchronized void onWifiAlert(int errorCode, @NonNull byte[] buffer) {
-        captureAlertData(errorCode, buffer);
-        mWifiMetrics.logFirmwareAlert(errorCode);
-        mWifiInjector.getWifiScoreCard().noteFirmwareAlert(errorCode);
+	captureAlertData(errorCode, buffer);
+	mWifiMetrics.logFirmwareAlert(errorCode);
+	mWifiInjector.getWifiScoreCard().noteFirmwareAlert(errorCode);
+
+	Intent intent = new Intent(WifiManager.WIFI_ALERT);
+	intent.putExtra(WifiManager.EXTRA_WIFI_ALERT_REASON, errorCode);
+	mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /**
@@ -488,7 +500,7 @@
         final int ringBufferByteLimitLarge = mContext.getResources().getInteger(
                 R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb) * 1024;
         if (verboseEnabled) {
-            mLogLevel = VERBOSE_LOG_WITH_WAKEUP;
+            mLogLevel = VERBOSE_DETAILED_LOG_WITH_WAKEUP;
             mMaxRingBufferSizeBytes = ringBufferByteLimitLarge;
         } else {
             mLogLevel = VERBOSE_NORMAL_LOG;
@@ -636,6 +648,7 @@
 
     private BugReport captureBugreport(int errorCode, boolean captureFWDump) {
         BugReport report = new BugReport();
+        mLog.warn("CaptureBugReport %").c(errorCode).flush();
         report.errorCode = errorCode;
         report.systemTimeMs = System.currentTimeMillis();
         report.kernelTimeNanos = System.nanoTime();
diff --git a/service/java/com/android/server/wifi/WifiGbk.java b/service/java/com/android/server/wifi/WifiGbk.java
new file mode 100644
index 0000000..39ebec8
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiGbk.java
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import com.android.server.wifi.util.NativeUtil;
+
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiSsid;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * WifiGbk provides the valued addon for Gbk SSID support.
+ */
+public class WifiGbk {
+    private static final String TAG = "WifiGbk";
+
+    private static final boolean DBG = true;
+
+    // BSSID Regix
+    private static final String BSSID_REGIX = "(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
+
+    // Max SSID Length
+    public static final int MAX_SSID_LENGTH = 32;
+
+    // Max UTF-8 SSID length: GBK SSID 32 bytes equals to UTF SSID 48 bytes
+    public static final int MAX_SSID_UTF_LENGTH = 48;
+
+    // BSS cache of 'Non-ASCII SSID' (e.g. 'Chinese SSID').
+    private static final ArrayList<BssCache> mBssCacheList = new ArrayList<>();
+
+    // BSS round robin Random record
+    private static final HashMap<String, Integer> mBssRandom = new HashMap<>();
+
+    // Expire BSS after number of scans
+    private static final int SCAN_CACHE_EXPIRATION_COUNT = 2;
+
+    private static Object mLock = new Object();
+
+    /**
+     * Log wrappers
+     */
+    protected static void loge(String s) {
+        Log.e(TAG, s);
+    }
+
+    protected static void logi(String s) {
+        Log.i(TAG, s);
+    }
+
+    protected static void logd(String s) {
+        if (DBG) {
+            Log.d(TAG, s);
+        }
+    }
+
+    private static int getBssRandom(String SSID, int security) {
+        synchronized (mLock) {
+            String key = BssCache.bssToString(SSID, security);
+            Integer rb = mBssRandom.get(key);
+            if (rb == null) {
+                mBssRandom.put(key, Integer.valueOf(0));
+                return 0;
+            }
+
+            int rbInt = rb.intValue();
+            rbInt ++;
+            mBssRandom.put(key, Integer.valueOf(rbInt));
+
+            return rbInt;
+        }
+    }
+
+    /**
+     * Checker - ScanResult
+     */
+    private static boolean isValid(ScanResult result) {
+        if (result == null
+               || result.wifiSsid == null
+               || result.BSSID == null) {
+            logi("Invalid ScanResult - BSSID=" + result.BSSID + " SSID=" + result.SSID);
+            return false;
+        }
+        if (result.wifiSsid.isHidden()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checker - BssCache
+     */
+    private static boolean isValid(BssCache bss) {
+        if (bss == null
+               || bss.SSID == null
+               || bss.BSSID == null) {
+            logi("Invalid BssCache - BSSID=" + bss.BSSID + " SSID=" + bss.SSID);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get Bss Cache - BSSID and real ssid
+     */
+    private static BssCache getBssCache(String BSSID, byte[] ssidBytes) {
+        for (BssCache bss : mBssCacheList) {
+            if (bss.matches(BSSID, ssidBytes)) {
+                return bss;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get Bss Cache - BSSID and readable UTF SSID
+     */
+    private static BssCache getBssCache(String BSSID, String SSID) {
+        for (BssCache bss : mBssCacheList) {
+            if (bss.matches(BSSID, SSID)) {
+                return bss;
+            }
+        }
+        return null;
+    }
+
+    public static boolean isMixedGbkUtf(WifiConfiguration config) {
+        int gbkCount = 0;
+        int utfCount = 0;
+
+        synchronized (mLock) {
+            String SSID = config.SSID;
+            int security = BssCache.getSecurity(config);
+
+            for (BssCache bss : mBssCacheList) {
+                if (bss.matches(SSID, security)) {
+                    if (bss.isGbk) {
+                        gbkCount ++;
+                    } else {
+                        utfCount ++;
+                    }
+                }
+            }
+        }
+
+        return (gbkCount != 0 && utfCount != 0);
+    }
+
+    /**
+     * Get preferred Bss Cache - readable UTF SSID and security
+     */
+    private static BssCache getPreferredBssCache(String SSID, int security) {
+        int gbkCount = 0;
+        int utfCount = 0;
+        BssCache gbkBss = null;
+        BssCache utfBss = null;
+
+        // Detect the GBK and UTF Ap counters in air.
+        for (BssCache bss : mBssCacheList) {
+            if (bss.matches(SSID, security)) {
+                if (bss.isGbk) {
+                    gbkCount ++;
+                    // gbkBss which has best RSSI
+                    if (gbkBss != null) {
+                        if (gbkBss.level > bss.level) {
+                            gbkBss = bss;
+                        }
+                    } else {
+                        gbkBss = bss;
+                    }
+                } else {
+                    utfCount ++;
+                    // utfBss which has best RSSI
+                    if (utfBss != null) {
+                        if (utfBss.level > bss.level) {
+                            utfBss = bss;
+                        }
+                    } else {
+                        utfBss = bss;
+                    }
+                }
+            }
+        }
+
+        if (gbkCount != 0 && utfCount == 0) {
+            logd("getPreferredBssCache - ssid=" + SSID
+                 + " security=" + BssCache.securityToString(security)
+                 + " gbk=" + gbkCount
+                 + " utf=" + utfCount);
+            return gbkBss;
+        } else if (gbkCount != 0 && utfCount != 0) {
+            int rand = getBssRandom(SSID, security);
+            logd("getPreferredBssCache - ssid=" + SSID
+                 + " security=" + BssCache.securityToString(security)
+                 + " gbk=" + gbkCount
+                 + " utf=" + utfCount
+                 + " rand=" + rand);
+            // Round robin between UTF and GBK.
+            if (rand % 2 == 0) {
+                return gbkBss;
+            }
+        }
+        return utfBss;
+    }
+
+    /**
+     * Add or Update scan cache
+     */
+    private static boolean addOrUpdateBssCache(ScanResult result) {
+        synchronized (mLock) {
+            byte[] ssidBytes = result.wifiSsid.getOctets();
+            BssCache bss = getBssCache(result.BSSID, ssidBytes);
+            if (bss == null) {
+                bss = new BssCache(result);
+                if (isValid(bss)) {
+                    mBssCacheList.add(bss);
+                    logd("adding bss - " + bss);
+                }
+            } else {
+                bss.update(result);
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Age out bss cache, which shall be called when receive scan result.
+     */
+    public static void ageBssCache() {
+        synchronized (mLock) {
+            Iterator<BssCache> it = mBssCacheList.iterator();
+            while (it.hasNext()) {
+                BssCache bss = it.next();
+                bss.expire_count --;
+                if (bss.expire_count <= 0) {
+                    it.remove();
+                    logd("removing bss - " + bss);
+                }
+            }
+        }
+        return;
+    }
+
+    /**
+     * Clear Bss Cache
+     */
+    public static void clearBssCache() {
+        synchronized (mLock) {
+            mBssCacheList.clear();
+            mBssRandom.clear();
+        }
+        return;
+    }
+
+
+    /**
+     * Process Scan results whose SSID is non-ASCII.
+     * Save it to BssCache, with conversion from gbkBytes to readable UTF String
+     */
+    public static boolean processScanResult(ScanResult result) {
+        if (!isValid(result)) {
+            return false;
+        }
+
+        byte[] ssidBytes = result.wifiSsid.getOctets();
+        if (isAllAscii(ssidBytes)) {
+            return false;
+        }
+        return addOrUpdateBssCache(result);
+    }
+
+
+    /**
+     * If bssid set in WifiConfiguration, match the bssid and get real SSID.
+     * else match the ssid and security, and get preferred SSID.
+     */
+    public static String getRealSsid(WifiConfiguration config) {
+        String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID();
+        boolean setbssid = (bssid != null && bssid.matches(BSSID_REGIX));
+        BssCache bss = null;
+
+        synchronized (mLock) {
+            if (setbssid) {
+                bss = getBssCache(bssid, config.SSID);
+            } else {
+                bss = getPreferredBssCache(config.SSID, BssCache.getSecurity(config));
+            }
+
+            if (bss != null) {
+                logi("getRealSsid - BSSID=" + bssid + " - " + bss);
+                if (bss.isGbk) {
+                    String SSID2 = NativeUtil.hexStringFromByteArray(bss.ssidBytes);
+                    return SSID2;
+                }
+            }
+        }
+
+        return config.SSID;
+    }
+
+
+    /**
+     * Get random UTF or GBK bytes for SSID.
+     * throws IllegalArgumentException e
+     */
+    public static byte[] getRandUtfOrGbkBytes(String SSID)
+                throws IllegalArgumentException {
+        byte [] utfBytes;
+        byte [] gbkBytes;
+        boolean utfSsidValid = false;
+        boolean gbkSsidValid = false;
+
+        // utfSsid
+        utfBytes = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SSID));
+        if (utfBytes == null || (utfBytes.length > MAX_SSID_UTF_LENGTH)) {
+            // Important! check if ssidBytes exceed max length
+            throw new IllegalArgumentException("Exceed max length " +
+                    MAX_SSID_UTF_LENGTH +  ", ssid=" + SSID);
+        }
+        if (utfBytes != null && (utfBytes.length <= MAX_SSID_LENGTH)) {
+            utfSsidValid = true;
+        }
+
+        // gbkSsid
+        gbkBytes = isAllAscii(utfBytes) ? null : getSsidBytes(SSID, "GBK");
+        if (gbkBytes != null && gbkBytes.length <= MAX_SSID_LENGTH) {
+            gbkSsidValid = true;
+        }
+
+        if ((utfSsidValid == false) && (gbkSsidValid == true)) {
+            return gbkBytes;
+        } else if ((utfSsidValid == true) && (gbkSsidValid == false)){
+            return utfBytes;
+        } else if ((utfSsidValid == true) && (gbkSsidValid == true)) {
+            // random pick
+            int rand = getBssRandom(SSID, BssCache.SECURITY_NONE);
+            logd("getRandUtfOrGbkBytes - ssid=" + SSID + " rand=" + rand);
+            return (rand % 2 == 0) ? gbkBytes : utfBytes;
+        }
+
+        throw new IllegalArgumentException("No valid utfBytes or " +
+                "gbkBytes for ssid=" + SSID);
+    }
+
+
+    /**
+     * For Utf ssidBytes, it equals to WifiSsid.createFromByteArray().
+     * For Gbk ssidBytes, it will convert to utfBytes, then create WifiSsid.
+     */
+    public static WifiSsid createWifiSsidFromByteArray(byte[] ssidBytes) {
+        if (isGbk(ssidBytes)) {
+            byte[] utfBytes = toUtf(ssidBytes);
+            if (utfBytes != null) {
+                return WifiSsid.createFromByteArray(utfBytes);
+            }
+        }
+        return WifiSsid.createFromByteArray(ssidBytes);
+    }
+
+    /**
+     * Helper method - check ssidBytes if all Ascii.
+     */
+    public static boolean isAllAscii(byte[] ssidBytes) {
+        if (ssidBytes == null) {
+            return false;
+        }
+        int length = ssidBytes.length;
+        for (int i = 0; i < length; i ++) {
+            if (ssidBytes[i] < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Helper method - check ssidBytes if GBK.
+     * @return true only it matches GBK rule but not match UTF rule.
+     */
+    public static boolean isGbk(byte[] ssidBytes) {
+        // Return false if matches UTF rule.
+        String ssid = encodeSsid(ssidBytes, "UTF-8");
+        if (ssid != null) {
+            return false;
+        }
+
+        // Return false if not matches Gbk rule
+        ssid = encodeSsid(ssidBytes, "GBK");
+        if (ssid == null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Helper method - GbkBytes to utfBytes
+     */
+    public static byte[] toUtf(byte[] gbkBytes) {
+        String ssid = encodeSsid(gbkBytes, "GBK");
+        if (ssid == null) {
+            return null;
+        }
+        return getSsidBytes(ssid, "UTF-8");
+    }
+
+    /**
+     * Helper method - utfBytes to GbkBytes
+     */
+    public static byte[] toGbk(byte[] utfBytes) {
+        String ssid = encodeSsid(utfBytes, "UTF-8");
+        if (ssid == null) {
+            return null;
+        }
+        return getSsidBytes(ssid, "GBK");
+    }
+
+    /**
+     * Helper method - get ssid bytes from Quoted String.
+     */
+    public static byte[] getSsidBytes(String ssid, String charsetName) {
+        if (ssid == null) {
+            return null;
+        }
+
+        String bareSsid = NativeUtil.removeEnclosingQuotes(ssid);
+        byte ssidBytes[] = null;
+        try {
+            ssidBytes = bareSsid.getBytes(charsetName);
+        } catch (UnsupportedEncodingException cce) {
+           // Unsupported
+        }
+
+        int maxlen = "UTF-8".equals(charsetName) ?
+                MAX_SSID_UTF_LENGTH : MAX_SSID_LENGTH;
+        if (ssidBytes.length > maxlen) {
+            loge("getSsidBytes - converted SSID exceed max length " +
+                    maxlen + ", ssid=" + ssid);
+            ssidBytes = null;
+        }
+        return ssidBytes;
+    }
+
+    /**
+     * Helper method - get Quoted String from ssid bytes based on Charset.
+     */
+    public static String encodeSsid(byte[] ssidBytes, String name) {
+        String ssid = null;
+        try {
+            Charset charset = Charset.forName(name);
+            CharsetDecoder decoder = charset.newDecoder();
+            CharBuffer decoded = decoder.decode(ByteBuffer.wrap(ssidBytes));
+            ssid = "\"" + decoded.toString() + "\"";
+        } catch (UnsupportedCharsetException cce) {
+        } catch (CharacterCodingException cce) {
+        }
+
+        int maxlen = "UTF-8".equals(name) ?
+                MAX_SSID_UTF_LENGTH : MAX_SSID_LENGTH;
+        if (ssid != null && ssid.length() > (maxlen + 2)) {
+            loge("encodeSsid - converted SSID exceed max length " +
+                    maxlen +  ", ssid=" + ssid);
+            ssid = null;
+        }
+
+        return ssid;
+    }
+
+    /**
+     * BssCache reprents Bss with Chinese SSIDs, including UTF-8 and GBK.
+     */
+    private static class BssCache {
+        // Real SSID in ocets.
+        public byte[] ssidBytes;
+
+        // Real SSID is Gbk?
+        boolean isGbk;
+
+        // Readable SSID for framework, UTF encoded.
+        public String SSID;
+
+        // BSSID
+        public String BSSID;
+
+        // Security
+        public int security;
+
+        public static final int SECURITY_NONE = 0;
+        public static final int SECURITY_WEP = 1;
+        public static final int SECURITY_PSK = 2;
+        public static final int SECURITY_EAP = 3;
+
+        // RSSI
+        public int level;
+
+        // Freqency
+        public int frequency;
+
+        // Expire count
+        public int expire_count;
+
+        public BssCache() {}
+
+        public BssCache(ScanResult result) {
+            this.ssidBytes = result.wifiSsid.getOctets();
+            this.isGbk = isGbk(ssidBytes);
+            // Add Quotes to result.SSID as it is not quoted.
+            this.SSID = NativeUtil.addEnclosingQuotes(result.SSID);
+            this.BSSID = result.BSSID;
+            this.security = BssCache.getSecurity(result);
+            this.level = result.level;
+            this.frequency = result.frequency;
+            this.expire_count = SCAN_CACHE_EXPIRATION_COUNT;
+
+            if (isGbk) {
+                // Override BSSCache's SSID
+                String ssid = encodeSsid(ssidBytes, "GBK");
+                this.SSID = ssid;
+
+                // Override ScanResult's SSID and wifiSsid
+                replaceSSIDinScanResult(result);
+            }
+        }
+
+        public void update(ScanResult result) {
+            // TODO: remove this protect?
+            byte[] ssidBytes = result.wifiSsid.getOctets();
+            if (!this.matches(result.BSSID, ssidBytes)) {
+                return;
+            }
+
+            this.security = BssCache.getSecurity(result);
+            this.level = result.level;
+            this.frequency = result.frequency;
+            this.expire_count = SCAN_CACHE_EXPIRATION_COUNT;
+
+            if (this.isGbk) {
+                // Override ScanResult's SSID and wifiSsid
+                replaceSSIDinScanResult(result);
+            }
+        }
+
+        private boolean replaceSSIDinScanResult(ScanResult result) {
+            byte[] utfBytes = getSsidBytes(this.SSID, "UTF-8");
+            if (this.SSID == null || utfBytes == null) {
+                loge("replaceSSIDinScanResult fail - result=" + result);
+                return false;
+            } else {
+                result.SSID = NativeUtil.removeEnclosingQuotes(this.SSID);
+                result.wifiSsid = WifiSsid.createFromByteArray(utfBytes);
+            }
+            return true;
+        }
+
+        public boolean matches(String BSSID, byte[] ssidBytes) {
+            if (!this.BSSID.equals(BSSID)) {
+                return false;
+            }
+            return Arrays.equals(this.ssidBytes, ssidBytes);
+        }
+
+        public boolean matches(String BSSID, String SSID) {
+            if (!this.BSSID.equals(BSSID)) {
+                return false;
+            }
+            return this.SSID.equals(SSID);
+        }
+
+        public boolean matches(String SSID, int security) {
+            if (!this.SSID.equals(SSID)) {
+                return false;
+            }
+            return (this.security == security);
+        }
+
+        public static int getSecurity(ScanResult result) {
+            if (result.capabilities.contains("WEP")) {
+                return SECURITY_WEP;
+            } else if (result.capabilities.contains("PSK")) {
+                return SECURITY_PSK;
+            } else if (result.capabilities.contains("EAP")) {
+                return SECURITY_EAP;
+            }
+            return SECURITY_NONE;
+        }
+
+        public static int getSecurity(WifiConfiguration config) {
+            if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+                return SECURITY_PSK;
+            }
+            if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
+                    config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+                return SECURITY_EAP;
+            }
+            return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
+        }
+
+        public static String securityToString(int security) {
+            switch(security) {
+                case SECURITY_NONE:
+                    return "NONE";
+                case SECURITY_WEP:
+                    return "WEP";
+                case SECURITY_PSK:
+                    return "PSK";
+                case SECURITY_EAP:
+                    return "EAP";
+                default:
+                    return "?";
+            }
+        }
+
+        public static String bssToString(String SSID, int security) {
+            return SSID + securityToString(security);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder().append("Bss(")
+                .append(SSID);
+
+            if (BSSID != null) {
+                builder.append(":").append(BSSID);
+            }
+            builder.append(", isGbk=").append(isGbk);
+            builder.append(", security=").append(securityToString(security));
+            builder.append(", level=").append(level);
+            builder.append(", frequency=").append(frequency);
+
+            return builder.append(')').toString();
+        }
+    }
+}
+
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 385b2dc..e9e3c87 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -122,6 +122,7 @@
     private final WifiConfigStore mWifiConfigStore;
     private final WifiKeyStore mWifiKeyStore;
     private final WifiConfigManager mWifiConfigManager;
+    private WifiConfigManager mQtiWifiConfigManager = null;
     private final WifiConnectivityHelper mWifiConnectivityHelper;
     private final LocalLog mConnectivityLocalLog;
     private final WifiNetworkSelector mWifiNetworkSelector;
@@ -192,6 +193,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 +286,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,
@@ -305,7 +306,7 @@
         mPasspointManager = new PasspointManager(mContext, this,
                 wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
                 mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager,
-                mWifiPermissionsUtil);
+                mMacAddressUtil, mWifiPermissionsUtil);
         PasspointNetworkNominateHelper nominateHelper =
                 new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager,
                         mConnectivityLocalLog);
@@ -369,6 +370,8 @@
                 new WakeupEvaluator(mScoringParams), wakeupOnboarding, mWifiConfigManager,
                 mWifiConfigStore, mWifiNetworkSuggestionsManager, mWifiMetrics.getWakeupMetrics(),
                 this, mFrameworkFacade, mClock);
+        if (mClientModeImpl != null)
+            mClientModeImpl.setWifiDiagnostics(mWifiDiagnostics);
         mLockManager = new WifiLockManager(mContext, mBatteryStats,
                 mClientModeImpl, mFrameworkFacade, wifiHandler, mWifiNative, mClock, mWifiMetrics);
         mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock);
@@ -399,11 +402,13 @@
         return sWifiInjector;
     }
 
+    private int mVerboseLoggingEnabled = 0;
     /**
      * Enable verbose logging in Injector objects. Called from the WifiServiceImpl (based on
      * binder call).
      */
     public void enableVerboseLogging(int verbose) {
+        mVerboseLoggingEnabled = verbose;
         mWifiLastResortWatchdog.enableVerboseLogging(verbose);
         mWifiBackupRestore.enableVerboseLogging(verbose);
         mHalDeviceManager.enableVerboseLogging(verbose);
@@ -413,6 +418,7 @@
         LogcatLog.enableVerboseLogging(verbose);
         mDppManager.enableVerboseLogging(verbose);
         mWifiCarrierInfoManager.enableVerboseLogging(verbose);
+        mActiveModeWarden.enableVerboseLogging(verbose);
     }
 
     public UserManager getUserManager() {
@@ -616,7 +622,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(),
@@ -848,6 +855,114 @@
         return mDeviceConfigFacade;
     }
 
+    /**
+     * Create QtiWifiConfigManager
+     */
+    public WifiConfigManager makeOrGetQtiWifiConfigManager() {
+        if(mQtiWifiConfigManager == null)
+        {
+            Handler wifiHandler = new Handler(mWifiHandlerThread.getLooper()); 
+            WifiConfigStore mQtiWifiConfigStore = new WifiConfigStore(mContext, wifiHandler, mClock, mWifiMetrics,
+                mFrameworkFacade.isNiapModeOn(mContext), WifiManager.STA_SECONDARY);
+            mQtiWifiConfigManager = new WifiConfigManager(mContext, mClock,
+                mUserManager, mWifiCarrierInfoManager,
+                mWifiKeyStore, mQtiWifiConfigStore, mWifiPermissionsUtil,
+                mWifiPermissionsWrapper, this,
+                new NetworkListSharedStoreData(mContext),
+                new NetworkListUserStoreData(mContext),
+                new RandomizedMacStoreData(), mFrameworkFacade, wifiHandler, mDeviceConfigFacade,
+                mWifiScoreCard, mLruConnectionTracker);
+            mQtiWifiConfigManager.loadFromStore();
+        }
+        return mQtiWifiConfigManager;
+    }
+
+
+    /**
+     * Create a QtiClientModeManager
+     *
+     * @param id interface id for  QtiClientModeManager
+     * @param listener listener for QtiClientModeManager state changes
+     * @return a new instance of QtiClientModeManager
+     */
+    public QtiClientModeManager makeQtiClientModeManager(QtiClientModeManager.Listener listener) {
+        return new QtiClientModeManager(mContext, mWifiHandlerThread.getLooper(), mClock,
+                mWifiNative, listener, this,  mSarManager, mWakeupController,
+                WifiManager.STA_SECONDARY, makeOrGetQtiWifiConfigManager());
+    }
+
+    /**
+     * Construct a new instance of QtiClientModeImpl to manage addtional stations.
+     *
+     * Create and return a new QtiClientModeImpl.
+     * @param identity staId.
+     * @param listener listener for QtiClientModeManager state changes
+     */
+    public QtiClientModeImpl makeQtiClientModeImpl(QtiClientModeManager.Listener listener, WifiConfigManager qtiWifiConfigManager ) {
+        Handler wifiHandler = new Handler(mWifiHandlerThread.getLooper()); 
+        SupplicantStateTracker supplicantStateTracker = new SupplicantStateTracker(
+                mContext, qtiWifiConfigManager, mBatteryStats, wifiHandler);
+        return new QtiClientModeImpl(mContext, mFrameworkFacade, mWifiHandlerThread.getLooper(),
+                       this, mWifiNative,new WrongPasswordNotifier(mContext, mFrameworkFacade),
+                       mWifiTrafficPoller, mLinkProbeManager, WifiManager.STA_SECONDARY, mBatteryStats,
+                       supplicantStateTracker, mMboOceController, mWifiCarrierInfoManager,
+                       new EapFailureNotifier(mContext, mFrameworkFacade, mWifiCarrierInfoManager),
+                       new SimRequiredNotifier(mContext, mFrameworkFacade), 
+                       listener, qtiWifiConfigManager, mDeviceConfigFacade);
+    }
+
+    /**
+     * Construct a new instance of QtiWifiConnectivityManager and its dependencies.
+     *
+     * Create and return a new QtiWifiConnectivityManager.
+     * @param identity staId.
+     * @param qtiClientModeImpl Instance of client mode impl.
+     */
+    public QtiWifiConnectivityManager makeQtiWifiConnectivityManager(QtiClientModeImpl qtiClientModeImpl, WifiConfigManager qtiWifiConfigManager) {
+        WifiConnectivityHelper mQtiWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative);
+
+        ScoringParams scoringParams = new ScoringParams(mContext);
+        WifiNetworkSelector wifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiScoreCard, scoringParams,
+                qtiWifiConfigManager, mClock, mConnectivityLocalLog, mWifiMetrics, mWifiNative,
+                mThroughputPredictor);
+        CompatibilityScorer compatibilityScorer = new CompatibilityScorer(scoringParams);
+        wifiNetworkSelector.registerCandidateScorer(compatibilityScorer);
+        ScoreCardBasedScorer scoreCardBasedScorer = new ScoreCardBasedScorer(scoringParams);
+        wifiNetworkSelector.registerCandidateScorer(scoreCardBasedScorer);
+        BubbleFunScorer bubbleFunScorer = new BubbleFunScorer(scoringParams);
+        wifiNetworkSelector.registerCandidateScorer(bubbleFunScorer);
+        ThroughputScorer throughputScorer = new ThroughputScorer(scoringParams);
+        wifiNetworkSelector.registerCandidateScorer(throughputScorer);
+        PasspointNetworkNominateHelper nominateHelper =
+                new PasspointNetworkNominateHelper(mPasspointManager, qtiWifiConfigManager,
+                        mConnectivityLocalLog);
+        SavedNetworkNominator savedNetworkNominator = new SavedNetworkNominator(
+                qtiWifiConfigManager, nominateHelper, mConnectivityLocalLog, mWifiCarrierInfoManager,
+                mWifiPermissionsUtil, mWifiNetworkSuggestionsManager);
+        wifiNetworkSelector.registerNetworkNominator(savedNetworkNominator);
+
+        Handler wifiHandler = new Handler(mWifiHandlerThread.getLooper());
+        return new QtiWifiConnectivityManager(mContext, scoringParams,
+                qtiClientModeImpl, this, qtiWifiConfigManager, wifiNetworkSelector,
+                mQtiWifiConnectivityHelper, wifiHandler, mClock, mConnectivityLocalLog, WifiManager.STA_SECONDARY);
+    }
+
+    public int getVerboseLogging() {
+        return mVerboseLoggingEnabled;
+    }
+
+    /**
+     * Construct a new instance of AutoConnectNewNetworkResultNotifier .
+     * @return the created instance
+     */
+    public AutoConnectNewNetworkResultNotifier makeAutoConnectNewNetworkResultNotifier() {
+        return new AutoConnectNewNetworkResultNotifier(mContext, mFrameworkFacade);
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
     @NonNull
     public WifiKeyStore getWifiKeyStore() {
         return mWifiKeyStore;
diff --git a/service/java/com/android/server/wifi/WifiKeyStore.java b/service/java/com/android/server/wifi/WifiKeyStore.java
index 08a101f..a914462 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;
@@ -277,52 +278,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/WifiLockManager.java b/service/java/com/android/server/wifi/WifiLockManager.java
index 7cbeea0..e4f39a9 100644
--- a/service/java/com/android/server/wifi/WifiLockManager.java
+++ b/service/java/com/android/server/wifi/WifiLockManager.java
@@ -374,7 +374,7 @@
         updateOpMode();
     }
 
-    private void setBlameHiPerfLocks(boolean shouldBlame) {
+    private synchronized void setBlameHiPerfLocks(boolean shouldBlame) {
         for (WifiLock lock : mWifiLocks) {
             if (lock.mMode == WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
                 setBlameHiPerfWs(lock.getWorkSource(), shouldBlame);
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index a7544e0..75d53fc 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;
@@ -74,6 +75,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;
@@ -92,6 +94,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;
@@ -113,6 +116,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;
@@ -232,11 +236,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,
@@ -753,6 +759,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
@@ -763,13 +851,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) {
@@ -777,6 +863,8 @@
                     networkInfo.isEphemeral = config.isEphemeral();
                     networkInfo.isPasspoint = config.isPasspoint();
                     mUserActionEvent.targetNetworkInfo = networkInfo;
+                    mUserActionEvent.networkDisableReason = convertToNetworkDisableReason(
+                            config, mBssidBlocklistMonitor.getFailureReasonsForSsid(config.SSID));
                 }
             }
         }
@@ -824,6 +912,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);
@@ -832,6 +923,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();
         }
 
@@ -1459,7 +1571,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;
@@ -1607,6 +1719,7 @@
                 if (!result) {
                     mScanResultRssiTimestampMillis = -1;
                 }
+                mWifiStatusBuilder.setConnected(result);
             }
         }
     }
@@ -2084,6 +2197,8 @@
         mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps();
         incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq);
         incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq);
+        mWifiStatusBuilder.setRssi(mLastPollRssi);
+        mWifiStatusBuilder.setNetworkId(wifiInfo.getNetworkId());
     }
 
     /**
@@ -2259,6 +2374,8 @@
                     mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000);
                 }
             }
+            mWifiStatusBuilder.setEstimatedTxKbps(txThroughputKbps);
+            mWifiStatusBuilder.setEstimatedRxKbps(rxThroughputKbps);
         }
     }
 
@@ -4646,6 +4763,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();
+            }
         }
     }
 
@@ -4750,6 +4871,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:
@@ -4787,6 +4909,7 @@
         if (mWifiDataStall != null) {
             staEvent.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable();
         }
+        staEvent.isAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabled;
         mSupplicantStateChangeBitmask = 0;
         mLastPollRssi = -127;
         mLastPollFreq = -1;
@@ -5003,6 +5126,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));
@@ -5222,6 +5346,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<>();
@@ -6155,6 +6288,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);
+            }
         }
     }
 
@@ -6585,4 +6725,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..c6de003 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -20,11 +20,13 @@
 import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiSsid;
+import android.net.wifi.WifiDppConfig.DppResult;
 import android.os.Handler;
 import android.os.Message;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
+import static android.net.wifi.WifiScanner.ON_PARTIAL_SCAN_RESULTS;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Protocol;
@@ -100,8 +102,8 @@
     /* 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;
+    /* Take some gap, start DPP event from 101*/
+    public static final int DPP_EVENT                            = BASE + 101;
 
     /* WPS config errrors */
     private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
@@ -270,9 +272,11 @@
             for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) {
                 if (isMonitoring(entry.getKey())) {
                     Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what);
-                    for (Handler handler : ifaceWhatHandlers) {
-                        if (handler != null) {
-                            sendMessage(handler, Message.obtain(message));
+                    if (ifaceWhatHandlers != null) {
+                        for (Handler handler : ifaceWhatHandlers) {
+                            if (handler != null) {
+                                sendMessage(handler, Message.obtain(message));
+                            }
                         }
                     }
                 }
@@ -431,6 +435,14 @@
     }
 
     /**
+     * Broadcast partial scan result event to all the handlers registered for this event.
+     * @param iface Name of iface on which this occurred.
+     */
+    public void broadcastPartialScanResultEvent(String iface) {
+        sendMessage(iface, SCAN_RESULTS_EVENT, ON_PARTIAL_SCAN_RESULTS);
+    }
+
+    /**
      * Broadcast pno scan result event to all the handlers registered for this event.
      * @param iface Name of iface on which this occurred.
      */
@@ -500,21 +512,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);
     }
 
     /**
@@ -574,4 +577,15 @@
     public void broadcastBssTmHandlingDoneEvent(String iface, BtmFrameData btmFrmData) {
         sendMessage(iface, MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
     }
+
+    /**
+     * Broadcast the DPP events to all the handlers registered for this event.
+     *
+     * @param iface Name of iface on which this occurred.
+     * @param dppEventType Name of DPP event as defined in DppResults.
+     * @param result DppResult object.
+     */
+    public void broadcastDppEvent(String iface, int dppEventType, DppResult result) {
+        sendMessage(iface, DPP_EVENT, dppEventType, 0, result);
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index cf362d6..ea27d19 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -34,7 +34,9 @@
 import android.net.wifi.nl80211.RadioChainInfo;
 import android.net.wifi.nl80211.WifiNl80211Manager;
 import android.os.Handler;
+import android.net.wifi.WifiDppConfig;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -47,6 +49,7 @@
 import com.android.server.wifi.util.NativeUtil;
 import com.android.server.wifi.util.NetdWrapper;
 import com.android.server.wifi.util.NetdWrapper.NetdEventObserver;
+import com.android.wifi.resources.R;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -67,6 +70,8 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.BitSet;
+import android.os.Message;
 
 /**
  * Native calls for bring up/shut down of the supplicant daemon and for
@@ -89,6 +94,10 @@
     private final WifiInjector mWifiInjector;
     private NetdWrapper mNetdWrapper;
     private boolean mVerboseLoggingEnabled = false;
+    /* Trigger periodic partial scan results*/
+    private static final int PERIODIC_PARTIAL_SCAN_RESULT_EVENT = 1;
+    private static String mIfaceNameforPartialScanResult;
+    private boolean mAllowConnectionOnPartialScanResults = false;
 
     public WifiNative(WifiVendorHal vendorHal,
                       SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal,
@@ -106,6 +115,9 @@
         mHandler = handler;
         mRandom = random;
         mWifiInjector = wifiInjector;
+        qtiConnectedbands = new BitSet();
+        qtiConnectedbands.set(ConnectedBand.BAND_NONE);
+        mIfaceBands = new HashMap<>();
     }
 
     /**
@@ -117,6 +129,38 @@
         mSupplicantStaIfaceHal.enableVerboseLogging(mVerboseLoggingEnabled);
         mHostapdHal.enableVerboseLogging(mVerboseLoggingEnabled);
         mWifiVendorHal.enableVerboseLogging(mVerboseLoggingEnabled);
+        mHostapdHal.enableVerboseLogging(mVerboseLoggingEnabled);
+    }
+
+    public void enableSoftApOcvFeature(boolean enable) {
+        mHostapdHal.enableSoftApOcvFeature(enable);
+    }
+
+    public void enableSoftApBeaconProtFeature(boolean enable) {
+        mHostapdHal.enableSoftApBeaconProtFeature(enable);
+    }
+
+    public void allowConnectOnPartialScanResults(boolean enable) {
+        mAllowConnectionOnPartialScanResults = enable;
+    }
+    public static class WifiGenerationStatus {
+
+        public int generation;
+        public boolean vhtMax8SpatialStreamsSupport;
+        public boolean twtSupport;
+
+        public WifiGenerationStatus() {
+            generation = -1;
+            vhtMax8SpatialStreamsSupport = false;
+            twtSupport = false;
+        }
+
+        public WifiGenerationStatus(int generation, boolean vhtMax8SpatialStreamsSupport, boolean twtSupport) {
+            this.generation = generation;
+            this.vhtMax8SpatialStreamsSupport = vhtMax8SpatialStreamsSupport;
+            this.twtSupport = twtSupport;
+        }
+
     }
 
     /**
@@ -138,8 +182,11 @@
         public static final int IFACE_TYPE_AP = 0;
         public static final int IFACE_TYPE_STA_FOR_CONNECTIVITY = 1;
         public static final int IFACE_TYPE_STA_FOR_SCAN = 2;
+        public static final int IFACE_TYPE_FST = 3;
+        public static final int IFACE_TYPE_BRIDGE = 4;
 
-        @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN})
+       @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN, IFACE_TYPE_FST,
+                IFACE_TYPE_BRIDGE})
         @Retention(RetentionPolicy.SOURCE)
         public @interface IfaceType{}
 
@@ -178,6 +225,12 @@
                 case IFACE_TYPE_AP:
                     typeString = "AP";
                     break;
+                case IFACE_TYPE_FST:
+                    typeString = "FST";
+                    break;
+                case IFACE_TYPE_BRIDGE:
+                    typeString = "BRIDGE";
+                    break;
                 default:
                     typeString = "<UNKNOWN>";
                     break;
@@ -325,6 +378,17 @@
             }
             return removedIface;
         }
+
+        /** Gets all ifaces of the given type. */
+        private List<Iface> getAllfaceOfType(@Iface.IfaceType int type) {
+            List<Iface> mReqIfaces = new ArrayList<>();
+            for (Iface iface : mIfaces.values()) {
+                if (iface.type == type) {
+                    mReqIfaces.add(iface);
+                }
+            }
+            return mReqIfaces;
+        }
     }
 
     private class NormalScanEventCallback implements WifiNl80211Manager.ScanEventCallback {
@@ -337,12 +401,14 @@
         @Override
         public void onScanResultReady() {
             Log.d(TAG, "Scan result ready event");
+            mPartialScanResultsHandler.removeMessages(PERIODIC_PARTIAL_SCAN_RESULT_EVENT);
             mWifiMonitor.broadcastScanResultEvent(mIfaceName);
         }
 
         @Override
         public void onScanFailed() {
             Log.d(TAG, "Scan failed event");
+            mPartialScanResultsHandler.removeMessages(PERIODIC_PARTIAL_SCAN_RESULT_EVENT);
             mWifiMonitor.broadcastScanFailedEvent(mIfaceName);
         }
     }
@@ -530,6 +596,7 @@
             }
             stopSupplicantIfNecessary();
             stopHalAndWificondIfNecessary();
+            removeFstInterface();
         }
     }
 
@@ -544,6 +611,7 @@
                 Log.e(TAG, "Failed to teardown iface in wificond on " + iface);
             }
             stopHalAndWificondIfNecessary();
+            removeFstInterface();
         }
     }
 
@@ -561,6 +629,17 @@
             }
             stopHostapdIfNecessary();
             stopHalAndWificondIfNecessary();
+            removeFstInterface();
+        }
+    }
+
+    /** Helper method invoked to teardown softAp iface and perform necessary cleanup */
+    private void onBridgeInterfaceDestroyed(@NonNull Iface iface) {
+        synchronized (mLock) {
+            if (!unregisterNetworkObserver(iface.networkObserver)) {
+                Log.e(TAG, "Failed to unregister network observer on " + iface);
+            }
+            stopHalAndWificondIfNecessary();
         }
     }
 
@@ -573,6 +652,8 @@
                 onClientInterfaceForScanDestroyed(iface);
             } else if (iface.type == Iface.IFACE_TYPE_AP) {
                 onSoftApInterfaceDestroyed(iface);
+            } else if (iface.type == Iface.IFACE_TYPE_BRIDGE) {
+                onBridgeInterfaceDestroyed(iface);
             }
             // Invoke the external callback.
             iface.externalListener.onDestroyed(iface.name);
@@ -613,14 +694,12 @@
      * daemon's death.
      */
     private void onNativeDaemonDeath() {
-        synchronized (mLock) {
             for (StatusListener listener : mStatusListeners) {
                 listener.onStatusChanged(false);
             }
             for (StatusListener listener : mStatusListeners) {
                 listener.onStatusChanged(true);
             }
-        }
     }
 
     /**
@@ -629,11 +708,9 @@
     private class VendorHalDeathHandlerInternal implements VendorHalDeathEventHandler {
         @Override
         public void onDeath() {
-            synchronized (mLock) {
                 Log.i(TAG, "Vendor HAL died. Cleaning up internal state.");
                 onNativeDaemonDeath();
                 mWifiMetrics.incrementNumHalCrashes();
-            }
         }
     }
 
@@ -657,11 +734,9 @@
     private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler {
         @Override
         public void onDeath() {
-            synchronized (mLock) {
                 Log.i(TAG, "wpa_supplicant died. Cleaning up internal state.");
                 onNativeDaemonDeath();
                 mWifiMetrics.incrementNumSupplicantCrashes();
-            }
         }
     }
 
@@ -671,11 +746,9 @@
     private class HostapdDeathHandlerInternal implements HostapdDeathEventHandler {
         @Override
         public void onDeath() {
-            synchronized (mLock) {
                 Log.i(TAG, "hostapd died. Cleaning up internal state.");
                 onNativeDaemonDeath();
                 mWifiMetrics.incrementNumHostapdCrashes();
-            }
         }
     }
 
@@ -698,7 +771,8 @@
                 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY
                         || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) {
                     mWifiMetrics.incrementNumClientInterfaceDown();
-                } else if (iface.type == Iface.IFACE_TYPE_AP) {
+                } else if (iface.type == Iface.IFACE_TYPE_AP
+                        || iface.type == Iface.IFACE_TYPE_BRIDGE) {
                     mWifiMetrics.incrementNumSoftApInterfaceDown();
                 }
             }
@@ -861,6 +935,7 @@
      */
     private boolean removeStaIface(@NonNull Iface iface) {
         synchronized (mLock) {
+
             if (mWifiVendorHal.isVendorHalSupported()) {
                 return mWifiVendorHal.removeStaIface(iface.name);
             } else {
@@ -900,6 +975,7 @@
             mWifiVendorHal.registerRadioModeChangeHandler(
                     new VendorHalRadioModeChangeHandlerInternal());
             mNetdWrapper = mWifiInjector.makeNetdWrapper();
+            mHostapdHal.terminateIfRunning();
             return true;
         }
     }
@@ -1011,6 +1087,77 @@
         }
     }
 
+    private boolean setupFstInterface(@NonNull Iface iface)
+    {
+        int fstEnabled = SystemProperties.getInt("persist.vendor.fst.rate.upgrade.en", 0);
+        Log.d(TAG, "fst " + ((fstEnabled == 1) ? "enabled" : "disabled"));
+        if (fstEnabled != 1) {
+            Log.d(TAG, "FST disabled, not creating FST interface");
+            return true;
+        }
+        boolean hasOther = mIfaceMgr.hasAnyIfaceOfType(iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY ?
+                                                       Iface.IFACE_TYPE_AP : Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY);
+        if (hasOther) {
+            Log.e(TAG, "FST not supported in STA/SAP concurrency");
+            return false;
+        }
+        Iface fstIface = mIfaceMgr.findAnyIfaceOfType(iface.IFACE_TYPE_FST);
+        if (fstIface != null) {
+            Log.e(TAG, "FST interface already added");
+            return false;
+        }
+
+        fstIface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_FST);
+        if (fstIface == null) {
+            Log.e(TAG, "Failed to allocate FST interface");
+            return false;
+        }
+        // TODO(b/145993198): TetheringConfiguration.getFstInterfaceName() replaced with "bond0"
+        fstIface.name = "bond0";
+        fstIface.externalListener = iface.externalListener;
+        iface.externalListener = new InterfaceCallback() {
+            public void onDestroyed(String ifaceName) {
+                /* nothing */
+            }
+            public void onDown(String ifaceName) {
+                /* nothing */
+            }
+            public void onUp(String ifaceName) {
+                /* nothing */
+            }
+        };
+        iface.networkObserver = new NetworkObserverInternal(iface.id);
+        if (!registerNetworkObserver(iface.networkObserver)) {
+            Log.e(TAG, "Failed to register network observer on " + fstIface);
+            iface.externalListener = fstIface.externalListener;
+            teardownInterface(fstIface.name);
+            return false;
+        }
+        return true;
+    }
+
+    private void removeFstInterface() {
+        Iface iface = mIfaceMgr.findAnyIfaceOfType(Iface.IFACE_TYPE_FST);
+        if (iface == null) {
+            return;
+        }
+        mIfaceMgr.removeIface(iface.id);
+        // the FST bonding interface is never destroyed
+        // make sure it is just brought down
+        mNetdWrapper.setInterfaceDown(iface.name);
+        mNetdWrapper.clearInterfaceAddresses(iface.name);
+    }
+
+    public String getFstDataInterfaceName() {
+        synchronized(mLock) {
+            Iface iface = mIfaceMgr.findAnyIfaceOfType(Iface.IFACE_TYPE_FST);
+            if (iface != null) {
+                return iface.name;
+            }
+            return null;
+        }
+    }
+
     /**
      * Setup an interface for client mode (for connectivity) operations.
      *
@@ -1046,6 +1193,12 @@
                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
                 return null;
             }
+            if (!setupFstInterface(iface)) {
+                Log.e(TAG, "Failed to setup fst interface from: " + iface);
+                teardownInterface(iface.name);
+                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
+                return null;
+            }
             if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,
                     new NormalScanEventCallback(iface.name),
                     new PnoScanEventCallback(iface.name))) {
@@ -1167,6 +1320,12 @@
                 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
                 return null;
             }
+            if (!setupFstInterface(iface)) {
+                Log.e(TAG, "Failed to setup fst interface from: " + iface);
+                teardownInterface(iface.name);
+                mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond();
+                return null;
+            }
             if (!mWifiCondManager.setupInterfaceForSoftApMode(iface.name)) {
                 Log.e(TAG, "Failed to setup iface in wificond on " + iface);
                 teardownInterface(iface.name);
@@ -1189,6 +1348,59 @@
         }
     }
 
+    /* Set interface UP. */
+    public boolean setInterfaceUp(String ifname) {
+        if (TextUtils.isEmpty(ifname))
+            return false;
+
+        mNetdWrapper.setInterfaceUp(ifname);
+
+        return isInterfaceUp(ifname);
+    }
+
+    /**
+     * Setup an interface for Bridge mode operations.
+     *
+     * This method configures an interface in Bridge mode. This is used only to register
+     * for interface callbacks (up/down/enable/disabled)
+     *
+     * @param interfaceCallback Associated callback for notifying status changes for the iface.
+     * @return Returns the name of the allocated interface, will be null on failure.
+     */
+    public String setupInterfaceForBridgeMode(@NonNull InterfaceCallback interfaceCallback) {
+        synchronized (mLock) {
+            if (!startHal()) {
+                Log.e(TAG, "Failed to start Hal");
+                mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
+                return null;
+            }
+            Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_BRIDGE);
+            if (iface == null) {
+                Log.e(TAG, "Failed to allocate new bridge iface");
+                return null;
+            }
+            iface.externalListener = interfaceCallback;
+            iface.name = WifiInjector.getInstance().getWifiApConfigStore().getBridgeInterface();
+            if (TextUtils.isEmpty(iface.name)) {
+                Log.e(TAG, "Failed to create Bridge iface in wifinative");
+                mIfaceMgr.removeIface(iface.id);
+                mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
+                return null;
+            }
+            iface.networkObserver = new NetworkObserverInternal(iface.id);
+            if (!registerNetworkObserver(iface.networkObserver)) {
+                Log.e(TAG, "Failed to register network observer on " + iface);
+                teardownInterface(iface.name);
+                return null;
+            }
+            // Just to avoid any race conditions with interface state change callbacks,
+            // update the interface state before we exit.
+            onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
+            Log.i(TAG, "Successfully setup bridge " + iface);
+            return iface.name;
+        }
+    }
+
     /**
      * Switches an existing Client mode interface from connectivity
      * {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY} to scan mode
@@ -1298,6 +1510,7 @@
     public void teardownInterface(@NonNull String ifaceName) {
         synchronized (mLock) {
             final Iface iface = mIfaceMgr.getIface(ifaceName);
+            mPartialScanResultsHandler.removeMessages(PERIODIC_PARTIAL_SCAN_RESULT_EVENT);
             if (iface == null) {
                 Log.e(TAG, "Trying to teardown an invalid iface=" + ifaceName);
                 return;
@@ -1315,6 +1528,9 @@
                     Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName);
                     return;
                 }
+            } else if (iface.type == Iface.IFACE_TYPE_BRIDGE) {
+                 mIfaceMgr.removeIface(iface.id);
+                 onInterfaceDestroyed(iface);
             }
             Log.i(TAG, "Successfully initiated teardown for iface=" + ifaceName);
         }
@@ -1437,18 +1653,56 @@
     public boolean scan(
             @NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, Set<Integer> freqs,
             List<String> hiddenNetworkSSIDs) {
+        Log.d(TAG, "Scan trigered from WifiNative");
         List<byte[]> hiddenNetworkSsidsArrays = new ArrayList<>();
         for (String hiddenNetworkSsid : hiddenNetworkSSIDs) {
             try {
-                hiddenNetworkSsidsArrays.add(
-                        NativeUtil.byteArrayFromArrayList(
-                                NativeUtil.decodeSsid(hiddenNetworkSsid)));
+                byte[] hiddenSsidBytes = WifiGbk.getRandUtfOrGbkBytes(hiddenNetworkSsid);
+                if (hiddenSsidBytes.length > WifiGbk.MAX_SSID_LENGTH) {
+                    Log.e(TAG, "SSID is too long after conversion, skipping this ssid! SSID =" +
+                               hiddenNetworkSsid + " , SSID size = " + hiddenSsidBytes.length);
+                    continue;
+                }
+                hiddenNetworkSsidsArrays.add(hiddenSsidBytes);
             } catch (IllegalArgumentException e) {
                 Log.e(TAG, "Illegal argument " + hiddenNetworkSsid, e);
                 continue;
             }
         }
-        return mWifiCondManager.startScan(ifaceName, scanType, freqs, hiddenNetworkSsidsArrays);
+        mIfaceNameforPartialScanResult = ifaceName;
+        boolean scanRequested = mWifiCondManager.startScan(ifaceName, scanType, freqs,
+                                hiddenNetworkSsidsArrays);
+        if (scanRequested &&
+            ((mWifiInjector.getClientModeImpl().isDisconnected()) ||
+             mAllowConnectionOnPartialScanResults)) {
+              schedulePeriodicPartialScanResult();
+        }
+        return scanRequested;
+    }
+
+    Handler mPartialScanResultsHandler = new Handler() {
+       @Override
+       public void handleMessage(Message msg) {
+           switch (msg.what) {
+           case PERIODIC_PARTIAL_SCAN_RESULT_EVENT:
+               Log.d(TAG,"Broadcast partial scan results event");
+               mWifiMonitor.broadcastPartialScanResultEvent(mIfaceNameforPartialScanResult);
+               schedulePeriodicPartialScanResult();
+               break;
+           default:
+               break;
+           }
+       }
+    };
+
+    private void schedulePeriodicPartialScanResult() {
+        Message msg = mPartialScanResultsHandler.obtainMessage(PERIODIC_PARTIAL_SCAN_RESULT_EVENT);
+        int wifiPartialScanResultsFetchingPeriod = mWifiInjector.getContext().getResources().getInteger(
+                                                   R.integer.config_wifi_partial_scan_results_fetching_period_ms);
+        if (wifiPartialScanResultsFetchingPeriod == 0)
+            return;
+        mPartialScanResultsHandler.sendMessageDelayed(msg,
+            wifiPartialScanResultsFetchingPeriod);
     }
 
     /**
@@ -1487,6 +1741,7 @@
                     InformationElementUtil.parseInformationElements(result.getInformationElements());
             InformationElementUtil.Capabilities capabilities =
                     new InformationElementUtil.Capabilities();
+
             capabilities.from(ies, result.getCapabilities(), isEnhancedOpenSupported());
             String flags = capabilities.generateCapabilitiesString();
             NetworkDetail networkDetail;
@@ -1752,11 +2007,30 @@
             Log.e(TAG, "Failed to register ap listener");
             return false;
         }
-        if (!mHostapdHal.addAccessPoint(ifaceName, config, listener::onFailure)) {
+
+        if (mHostapdHal.isVendorHostapdHal()) {
+            if (!mHostapdHal.addVendorAccessPoint(ifaceName, config, listener)) {
+                Log.e(TAG, "Failed to add Vendor acccess point");
+                mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
+                return false;
+            }
+        } else if (!mHostapdHal.addAccessPoint(ifaceName, config, listener::onFailure)) {
             Log.e(TAG, "Failed to add acccess point");
             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
             return false;
         }
+
+        int wifiStandard = getDeviceWifiStandard(ifaceName);
+
+        if (config.getBand() == SoftApConfiguration.BAND_2GHZ &&
+                wifiStandard == ScanResult.WIFI_STANDARD_11AC) {
+            Log.i(TAG, ifaceName + ": Do not consider vendor extensions of VHT on 2.4 GHz as 11AC");
+            wifiStandard = ScanResult.WIFI_STANDARD_11N;
+        }
+
+        Log.i(TAG, ifaceName + ": SoftAp Wifi Standard: " + wifiStandard);
+        mWifiInjector.getWifiApConfigStore().setWifiStandard(wifiStandard);
+
         return true;
     }
 
@@ -1995,6 +2269,27 @@
     }
 
     /**
+     * Get capabilities from driver
+     *
+     * @param ifaceName Name of the interface.
+     * @param capaType which driver capability to get, ex. key_mgmt
+     * @return String of capabilities fetched from driver.
+     */
+     public String getCapabilities(@NonNull String ifaceName, String capaType) {
+         return mSupplicantStaIfaceHal.getCapabilities(ifaceName, capaType);
+    }
+
+    /**
+     * Get wifi generation status from supplicant
+     *
+     * @param ifaceName Name of the interface.
+     * @return WifiGenerationStatus Wifi generation status fetched from supplicant.
+     */
+     public WifiGenerationStatus getWifiGenerationStatus(@NonNull String ifaceName) {
+         return mSupplicantStaIfaceHal.getWifiGenerationStatus(ifaceName);
+    }
+
+    /**
      * Set country code.
      *
      * @param ifaceName Name of the interface.
@@ -2760,7 +3055,22 @@
                     android.net.wifi.nl80211.PnoNetwork nativeNetwork =
                             network.toNativePnoNetwork();
                     if (nativeNetwork != null) {
-                        pnoNetworks.add(nativeNetwork);
+                        if (nativeNetwork.getSsid().length <= WifiGbk.MAX_SSID_LENGTH) { //wifigbk++
+                            pnoNetworks.add(nativeNetwork);
+                        }
+                        //wifigbk++
+                        if (!WifiGbk.isAllAscii(nativeNetwork.getSsid())) {
+                            byte gbkBytes[] = WifiGbk.toGbk(nativeNetwork.getSsid());
+                            if (gbkBytes != null) {
+                                android.net.wifi.nl80211.PnoNetwork gbkNetwork =
+                                    network.toNativePnoNetwork();
+                                gbkNetwork.setSsid(gbkBytes);
+                                pnoNetworks.add(gbkNetwork);
+                                Log.i(TAG, "WifiGbk fixed - pnoScan add extra Gbk ssid for "
+                                      + nativeNetwork.getSsid());
+                            }
+                        }
+                        //wifigbk--
                     }
                 }
             }
@@ -2810,6 +3120,7 @@
     public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
     public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
     public static final int WIFI_SCAN_FAILED = 3;
+    public static final int WIFI_SCAN_PARTIAL_RESULTS_AVAILABLE = 4;
 
     /**
      * Starts a background scan.
@@ -2893,6 +3204,15 @@
     }
 
     /**
+     * Returns whether Dual STA is supported or not.
+     */
+    public boolean isDualStaSupported() {
+        synchronized (mLock) {
+            return mWifiVendorHal.isDualStaSupported();
+        }
+    }
+
+    /**
      * Get the supported features
      *
      * @param ifaceName Name of the interface.
@@ -3594,4 +3914,211 @@
             iface.phyCapabilities = capabilities;
         }
     }
+
+    /**
+     * Add the DPP bootstrap info obtained from QR code.
+     *
+     * @param ifaceName Name of the interface.
+     * @param channel Channel for communicating with the state machine
+     * @param uri:The URI obtained from the QR code.
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int dppAddBootstrapQrCode(@NonNull String ifaceName, String uri) {
+        return mSupplicantStaIfaceHal.dppAddBootstrapQrCode(ifaceName, uri);
+    }
+
+    /**
+     * Generate bootstrap URI based on the passed arguments
+     *
+     * @param ifaceName Name of the interface.
+     * @param config – bootstrap generate config
+     *
+     * @return: Handle to strored URI info else -1 on failure
+     */
+    public int dppBootstrapGenerate(@NonNull String ifaceName, WifiDppConfig config) {
+        return mSupplicantStaIfaceHal.dppBootstrapGenerate(ifaceName, config);
+    }
+
+    /**
+     * Get bootstrap URI based on bootstrap ID
+     *
+     * @param ifaceName Name of the interface.
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: URI string else -1 on failure
+     */
+    public String dppGetUri(@NonNull String ifaceName, int bootstrap_id) {
+        return mSupplicantStaIfaceHal.dppGetUri(ifaceName, bootstrap_id);
+    }
+
+    /**
+     * Remove bootstrap URI based on bootstrap ID.
+     *
+     * @param ifaceName Name of the interface.
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: 0 – Success or -1 on failure
+     */
+    public int dppBootstrapRemove(@NonNull String ifaceName, int bootstrap_id) {
+        return mSupplicantStaIfaceHal.dppBootstrapRemove(ifaceName, bootstrap_id);
+    }
+
+    /**
+     * start listen on the channel specified waiting to receive
+     * the DPP Authentication request.
+     *
+     * @param ifaceName Name of the interface.
+     * @param frequency: DPP listen frequency
+     * @param dpp_role: Configurator/Enrollee role
+     * @param qr_mutual: Mutual authentication required
+     * @param netrole_ap: network role
+     *
+     * @return: Returns 0 if a DPP-listen work is successfully
+     *  queued and -1 on failure.
+     */
+    public int dppListen(@NonNull String ifaceName, String frequency, int dpp_role,
+                         boolean qr_mutual, boolean netrole_ap) {
+        return mSupplicantStaIfaceHal.dppListen(ifaceName, frequency, dpp_role, qr_mutual, netrole_ap);
+    }
+
+    /**
+     * stop ongoing dpp listen.
+     *
+     * @param ifaceName Name of the interface.
+     */
+    public boolean dppStopListen(@NonNull String ifaceName) {
+        return mSupplicantStaIfaceHal.dppStopListen(ifaceName);
+    }
+
+    /**
+     * Adds the DPP configurator
+     *
+     * @param ifaceName Name of the interface.
+     * @param curve curve used for dpp encryption
+     * @param key private key
+     * @param expiry timeout in seconds
+     *
+     * @return: Identifier of the added configurator or -1 on failure
+     */
+    public int dppConfiguratorAdd(@NonNull String ifaceName, String curve, String key, int expiry) {
+        return mSupplicantStaIfaceHal.dppConfiguratorAdd(ifaceName, curve, key, expiry);
+    }
+
+    /**
+     * Remove the added configurator through dppConfiguratorAdd.
+     *
+     * @param ifaceName Name of the interface.
+     * @param config_id: DPP Configurator ID
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    public int dppConfiguratorRemove(@NonNull String ifaceName, int config_id) {
+        return mSupplicantStaIfaceHal.dppConfiguratorRemove(ifaceName, config_id);
+    }
+
+    /**
+     * Start DPP authentication and provisioning with the specified peer
+     *
+     * @param ifaceName Name of the interface.
+     * @param config – dpp auth init config
+     *
+     * @return: 0 if DPP Authentication request was transmitted and -1 on failure
+     */
+    public int  dppStartAuth(@NonNull String ifaceName, WifiDppConfig config) {
+        return mSupplicantStaIfaceHal.dppStartAuth(ifaceName, config);
+    }
+
+    /**
+     * Retrieve Private key to be used for configurator
+     *
+     * @param ifaceName Name of the interface.
+     * @param id: id of configurator object
+     *
+     * @return: Key string else -1 on failure
+     */
+    public String dppConfiguratorGetKey(@NonNull String ifaceName, int id) {
+        return mSupplicantStaIfaceHal.dppConfiguratorGetKey(ifaceName, id);
+    }
+
+    public int getDeviceWifiStandard(@NonNull String ifaceName) {
+        DeviceWiphyCapabilities deviceCapabilities = getDeviceWiphyCapabilities(ifaceName);
+
+        if (deviceCapabilities == null)
+            return ScanResult.WIFI_STANDARD_LEGACY;
+        if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)
+                && mHostapdHal.is11axSupportEnabled())
+            return ScanResult.WIFI_STANDARD_11AX;
+        if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC)
+                && mHostapdHal.is11acSupportEnabled())
+            return ScanResult.WIFI_STANDARD_11AC;
+        if (deviceCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N))
+            return ScanResult.WIFI_STANDARD_11N;
+
+        return ScanResult.WIFI_STANDARD_LEGACY;
+    }
+
+    /**
+     * Run driver command
+     *
+     * @param ifaceName String representing iface name
+     * @param command to pass to driver
+     * returns String of command reply.
+     */
+    String doDriverCmd(String ifaceName, String command)
+    {
+        return mSupplicantStaIfaceHal.doDriverCmd(ifaceName, command);
+    }
+
+    public BitSet qtiConnectedbands;
+    private HashMap<Integer, Integer> mIfaceBands;
+
+    public static class ConnectedBand {
+        private ConnectedBand() {}
+
+        /* no band is in connected state */
+        public static final int BAND_NONE = 0;
+
+        /* one of band is connected in 2.4 GHz */
+        public static final int BAND_2G = 1;
+
+        /* one of band is connected in 5 GHz or 6 GHz */
+        public static final int BAND_5G = 2;
+    }
+
+    public void qtiUpdateConnectedBand(int wifiId, int band) {
+        if (band < 0 || band > ConnectedBand.BAND_5G) {
+            Log.e(TAG, "Unknown band option: " + band);
+            return;
+        }
+
+        if (band != ConnectedBand.BAND_NONE)
+            mIfaceBands.put(wifiId, band);
+        else
+            mIfaceBands.remove(wifiId);
+
+        synchronized (mLock) {
+            qtiConnectedbands.clear();
+            for (int b : mIfaceBands.values()) {
+                qtiConnectedbands.set(b);
+            }
+            if (qtiConnectedbands.isEmpty())
+                qtiConnectedbands.set(ConnectedBand.BAND_NONE);
+
+            if (mVerboseLoggingEnabled)
+                Log.d(TAG, "ConnectedBand bitset="+qtiConnectedbands);
+        }
+    }
+
+    /** updates linked networks of the |networkId| in supplicant if it's the current network,
+     * if the current configured network matches |networkId|.
+     *
+     * @param ifaceName Name of the interface.
+     * @param networkId network id of the network to be updated from supplicant.
+     * @param linkedNetworks linked networks to be configured in supplicant.
+     */
+    public boolean updateLinkedNetworks(@NonNull String ifaceName, int networkId,
+                    HashMap<String, WifiConfiguration> linkedNetworks) {
+        return mSupplicantStaIfaceHal.updateLinkedNetworks(ifaceName, networkId, linkedNetworks);
+    }
 }
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..a122dc3 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() + " :");
@@ -808,13 +821,19 @@
                         WifiCandidates.Key key = wifiCandidates.keyFromScanDetailAndConfig(
                                 scanDetail, config);
                         if (key != null) {
+                            double lastSelectionWeight;
                             boolean metered = isEverMetered(config, wifiInfo, scanDetail);
                             // TODO(b/151981920) Saved passpoint candidates are marked ephemeral
+                            if (currentNetwork != null && config.isAutoConnectionEnabled) {
+                                lastSelectionWeight = calculateLastSelectionWeight(currentNetwork.networkId);
+                            } else {
+                                lastSelectionWeight = calculateLastSelectionWeight(config.networkId);
+                            }
                             boolean added = wifiCandidates.add(key, config,
                                     registeredNominator.getId(),
                                     scanDetail.getScanResult().level,
                                     scanDetail.getScanResult().frequency,
-                                    calculateLastSelectionWeight(config.networkId),
+                                    lastSelectionWeight,
                                     metered,
                                     isFromCarrierOrPrivilegedApp(config),
                                     predictThroughput(scanDetail));
@@ -1074,6 +1093,11 @@
             // From ScoredNetworkNominator
             return true;
         }
+        if (config.isEphemeral()
+                && config.isAutoConnectionEnabled) {
+            // From Auto connection WNS
+            return true;
+        }
         return false;
     }
 
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/WifiSecShellCmd.java b/service/java/com/android/server/wifi/WifiSecShellCmd.java
new file mode 100644
index 0000000..58f4323
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiSecShellCmd.java
@@ -0,0 +1,155 @@
+
+package com.android.server.wifi;
+
+import android.net.wifi.WifiManager;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+
+import java.io.PrintWriter;
+import java.util.List;
+import com.android.internal.util.AsyncChannel;
+import android.text.TextUtils;
+import android.os.Process;
+import android.os.Message;
+import android.content.Context;
+
+import android.net.NetworkRequest;
+import static android.net.wifi.WifiManager.STA_PRIMARY;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
+import android.net.NetworkCapabilities;
+/**
+ * Runs shell command for secondary station.
+ *
+ * To run 'adb shell cmd wifi sec [args]'
+ *
+ * API of this class is invoked by WifiShellCommand.
+ */
+public class WifiSecShellCmd {
+
+    private final ConnectivityManager mConnectivityManager;
+    private final WifiInjector mWifiInjector;
+    private final ActiveModeWarden mActiveModeWarden;
+    private final Context mContext;
+    private final int mStaId;
+    private WifiManager mWifiManager;
+
+    WifiSecShellCmd(WifiInjector injector) {
+        mWifiInjector = injector;
+        mActiveModeWarden = injector.getActiveModeWarden();
+        mContext = injector.getContext();
+        mStaId = STA_SECONDARY;
+        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+        mWifiManager = null;
+    }
+
+    private WifiManager getManager() {
+        if (mWifiManager == null)
+            mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        return mWifiManager;
+    }
+
+/* Lets do it through WifiManager */
+
+    public void enable() {
+       mConnectivityManager.requestNetwork(new NetworkRequest.Builder()
+                            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                            .addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)
+                            .build(),
+                  new ConnectivityManager.NetworkCallback());
+       getManager().setWifiEnabled(mStaId, true);
+    }
+
+    public void disable() {
+        getManager().setWifiEnabled(mStaId, false);
+    }
+
+    public int addNetwork(String ssid, String password) {
+        return getManager().addNetwork(createLocalConfig(ssid, password));
+    }
+
+    public int updateNetwork(String ssid, String password) {
+        return getManager().updateNetwork(createLocalConfig(ssid, password));
+    }
+
+    public void saveNetwork(String ssid, String password) {
+        getManager().save(createLocalConfig(ssid, password), null);
+    }
+
+    public boolean removeNetwork(int netId) {
+        return getManager().removeNetwork(netId);
+    }
+
+
+    public void forgetNetwork(int netId) {
+        getManager().forget(netId, null);
+    }
+
+    public void connectNetwork(String ssid, String password) {
+        getManager().connect(createLocalConfig(ssid, password), null);
+    }
+
+    public void connectNetwork(int netId) {
+        getManager().connect(netId, null);
+    }
+
+    public boolean enableNetwork(int netId) {
+        return getManager().enableNetwork(netId, false /*disable others*/);
+    }
+
+    public void disableNetwork(int netId) {
+        getManager().disable(netId, null);
+    }
+
+    public boolean disconnect() {
+        return getManager().disconnect(mStaId);
+    }
+
+    public void listNetwork(PrintWriter pw) {
+        List<WifiConfiguration> configs = null;
+
+        configs = getManager().getConfiguredNetworks(mStaId);
+        if (configs != null)
+            pw.println("Total configurations: " + configs.size());
+
+        for (WifiConfiguration config : configs) {
+            pw.println(" [" + getStaIdString(config) + "] netId: " + config.networkId
+                       + " SSID: " + config.SSID + " configkey: " + config.getKey());
+        }
+    }
+
+    public void status(PrintWriter pw) {
+        pw.println("WifiInfo=" + getManager().getConnectionInfo(mStaId));
+    }
+
+    // Utility API
+
+    private WifiConfiguration createLocalConfig(String ssid, String password) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.staId = mStaId;
+        config.SSID = "\"" + ssid + "\"";
+
+        // WPA2-PSK or OPEN network
+        if (TextUtils.isEmpty(password)) {
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        } else {
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+            config.preSharedKey = "\"" + password + "\"";
+        }
+        return config;
+    }
+
+    private String getStaIdString(WifiConfiguration config) {
+        if (config == null)
+            return "config is null";
+
+        switch (config.staId) {
+            case STA_PRIMARY:
+                return "PRIMARY";
+            case STA_SECONDARY:
+                return "SECONDARY";
+            default:
+                return "UNKNOWN";
+        }
+    }
+}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index bb72876..4545d52 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -26,9 +26,16 @@
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+import static android.net.wifi.WifiManager.STA_PRIMARY;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 
+import static com.android.server.wifi.WifiSettingsConfigStore.SOFTAP_BEACON_PROTECTION_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.SOFTAP_OCV_ENABLED;
 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED;
-
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_COVERAGE_EXTEND_FEATURE_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WHITELIST_ROAMING_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED;
+import static com.android.server.wifi.WifiSettingsConfigStore.HW_SUPPORTED_FEATURES;
 import android.annotation.CheckResult;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,6 +57,8 @@
 import android.net.Network;
 import android.net.NetworkStack;
 import android.net.Uri;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
 import android.net.ip.IpClientUtil;
 import android.net.wifi.IActionListener;
 import android.net.wifi.IDppCallback;
@@ -80,6 +89,9 @@
 import android.net.wifi.hotspot2.IProvisioningCallback;
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.WifiDppConfig;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.IWifiNotificationCallback;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
@@ -178,6 +190,8 @@
     private final WifiTrafficPoller mWifiTrafficPoller;
     /** Tracks the persisted states for wi-fi & airplane mode */
     private final WifiSettingsStore mSettingsStore;
+
+    private boolean mIsControllerStarted = false;
     /** Logs connection events and some general router and scan stats */
     private final WifiMetrics mWifiMetrics;
 
@@ -204,6 +218,16 @@
 
     private final WifiPermissionsUtil mWifiPermissionsUtil;
 
+    private final ExternalCallbackTracker<IWifiNotificationCallback> mRegisteredWifiCallbacks;
+
+    // QtiClientMode states
+    private final HashMap<Integer, Integer> mQtiWifiRssi;
+    private final HashMap<Integer, Integer> mQtiWifiNewState;
+    private final HashMap<Integer, LinkProperties> mQtiWifiLinkProperties;
+    private final HashMap<Integer, NetworkInfo> mQtiWifiNetworkInfo;
+
+    private int mQCSoftApNumClients = 0;
+
     private final TetheredSoftApTracker mTetheredSoftApTracker;
 
     private final LohsSoftApTracker mLohsSoftApTracker;
@@ -292,6 +316,41 @@
     private final MemoryStoreImpl mMemoryStoreImpl;
     private final WifiScoreCard mWifiScoreCard;
 
+    private void restartSoftApIfNeeded() {
+        if (getWifiApEnabledState() == WifiManager.WIFI_AP_STATE_DISABLED) {
+            Log.d(TAG ,"Repeater mode: not restarting SoftAP as Hotspot is disabled.");
+            return;
+        }
+
+        Log.d(TAG ,"Repeater mode: Stop SoftAP.");
+        mRestartWifiApIfRequired = true;
+        stopSoftAp();
+    }
+
+    private boolean mRestartWifiApIfRequired = false;
+    private boolean mSoftApExtendingWifi = false;
+    private final IntentFilter mQcIntentFilter;
+    private final BroadcastReceiver mQcReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
+                SupplicantState state = (SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
+                if (isCurrentStaShareThisAp() && state == SupplicantState.COMPLETED && !mSoftApExtendingWifi) {
+                    restartSoftApIfNeeded();
+                } else if (mSoftApExtendingWifi && state == SupplicantState.DISCONNECTED) {
+                    restartSoftApIfNeeded();
+                }
+            } else if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
+                 if (mSoftApExtendingWifi && state == WifiManager.WIFI_STATE_DISABLED) {
+                     restartSoftApIfNeeded();
+                 }
+            }
+        }
+    };
+
+
     public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) {
         mContext = context;
         mWifiInjector = wifiInjector;
@@ -304,6 +363,7 @@
         mCountryCode = mWifiInjector.getWifiCountryCode();
         mClientModeImpl = mWifiInjector.getClientModeImpl();
         mActiveModeWarden = mWifiInjector.getActiveModeWarden();
+        mClientModeImpl.setTrafficPoller(mWifiTrafficPoller);
         mScanRequestProxy = mWifiInjector.getScanRequestProxy();
         mSettingsStore = mWifiInjector.getWifiSettingsStore();
         mPowerManager = mContext.getSystemService(PowerManager.class);
@@ -321,6 +381,13 @@
         mTetheredSoftApTracker = new TetheredSoftApTracker();
         mActiveModeWarden.registerSoftApCallback(mTetheredSoftApTracker);
         mLohsSoftApTracker = new LohsSoftApTracker();
+        mQtiWifiRssi = new HashMap<>();
+        mQtiWifiNewState = new HashMap<>();
+        mQtiWifiLinkProperties = new HashMap<>();
+        mQtiWifiNetworkInfo = new HashMap<>();
+        mRegisteredWifiCallbacks =
+                new ExternalCallbackTracker<IWifiNotificationCallback>(mClientModeImplHandler);
+        mWifiInjector.getActiveModeWarden().registerQtiClientModeCallback(new WifiNotificationCallbackImpl());
         mActiveModeWarden.registerLohsCallback(mLohsSoftApTracker);
         mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager();
         mDppManager = mWifiInjector.getDppManager();
@@ -330,6 +397,9 @@
         mWifiScoreCard = mWifiInjector.getWifiScoreCard();
         mMemoryStoreImpl = new MemoryStoreImpl(mContext, mWifiInjector,
                 mWifiScoreCard,  mWifiInjector.getWifiHealthMonitor());
+        mQcIntentFilter = new IntentFilter("android.net.wifi.supplicant.STATE_CHANGE");
+        mQcIntentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
+        mContext.registerReceiver(mQcReceiver, mQcIntentFilter);
     }
 
     /**
@@ -347,6 +417,10 @@
             }
             // config store is read, check if verbose logging is enabled.
             enableVerboseLoggingInternal(getVerboseLoggingLevel());
+            enableSoftApOcvFeatureInternal(mContext.getResources().getBoolean(
+                    R.bool.config_vendor_softap_ocv_supported));
+            enableSoftApBeaconProtFeatureInternal(mContext.getResources().getBoolean(
+                    R.bool.config_vendor_softap_beacon_protection_supported));
             // Check if wi-fi needs to be enabled
             boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
             Log.i(TAG,
@@ -420,6 +494,7 @@
             mClientModeImpl.initialize();
             mActiveModeWarden.start();
             registerForCarrierConfigChange();
+            mIsControllerStarted = true;
         });
     }
 
@@ -761,12 +836,13 @@
 
     /**
      * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
+     * @param  staId Wifi interface to enable/disable.
      * @param enable {@code true} to enable, {@code false} to disable.
      * @return {@code true} if the enable/disable operation was
      *         started or is already in the queue.
      */
     @Override
-    public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
+    public synchronized boolean setWifiEnabled2(String packageName, int staId,boolean enable) {
         if (enforceChangePermission(packageName) != MODE_ALLOWED) {
             return false;
         }
@@ -795,7 +871,7 @@
                 .c(Binder.getCallingUid()).c(enable).flush();
         long ident = Binder.clearCallingIdentity();
         try {
-            if (!mSettingsStore.handleWifiToggled(enable)) {
+            if (staId == STA_PRIMARY && !mSettingsStore.handleWifiToggled(enable)) {
                 // Nothing to do if wifi cannot be toggled
                 return true;
             }
@@ -803,14 +879,35 @@
             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());
+            }
         }
+
+        if (!mIsControllerStarted) {
+            Log.e(TAG,"WifiController is not yet started, abort setWifiEnabled");
+            return false;
+        }
+
         mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
-        mActiveModeWarden.wifiToggled();
+		if(staId == STA_PRIMARY)
+            mActiveModeWarden.wifiToggled();
+		else if(staId == STA_SECONDARY && (getNumConcurrentStaSupported() > 1) && (getWifiEnabledState() == WifiManager.WIFI_STATE_ENABLED))
+			mActiveModeWarden.qtiWifiToggled(staId, enable);
+        else
+            Log.e(TAG,"setWifiEnabled not allowed for Id: " + staId);
         return true;
     }
 
+    @Override
+    public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
+        return setWifiEnabled2(packageName, STA_PRIMARY, enable);
+    }
+
     /**
      * see {@link WifiManager#getWifiState()}
      * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
@@ -930,6 +1027,15 @@
             }
         }
 
+        if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_DUAL)
+                && !is5GhzBandSupportedInternal()
+                && (!is6GhzBandSupportedInternal()
+                       || !mContext.getResources().getBoolean(
+                               R.bool.config_wifiSoftap6ghzSupported))) {
+            mLog.err("Can not start softAp with Dual band, not supported.").flush();
+            return false;
+        }
+
         return true;
     }
 
@@ -977,9 +1083,25 @@
         mLog.trace("startSoftApInternal uid=% mode=%")
                 .c(uid).c(apConfig.getTargetMode()).flush();
 
+        SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
+
+        if (softApConfig == null && TextUtils.isEmpty(mCountryCode.getCountryCode())) {
+            Log.d(TAG, "Starting softap without country code. Fallback to 2G band!");
+            softApConfig = new SoftApConfiguration.Builder(mWifiApConfigStore.getApConfiguration())
+                .setBand(SoftApConfiguration.BAND_2GHZ).build();
+            mWifiApConfigStore.setApConfiguration(softApConfig);
+        }
+
+        setDualSapMode(softApConfig);
+
+        mSoftApExtendingWifi = (!mWifiApConfigStore.getDualSapStatus()) && isCurrentStaShareThisAp();
+        if (mSoftApExtendingWifi) {
+            startSoftApInRepeaterMode(apConfig.getTargetMode(), softApConfig);
+            return true;
+        }
+
         // null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent
         // AP config.
-        SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
         if (softApConfig != null
                 && (!WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged)
                     || !validateSoftApBand(softApConfig.getBand()))) {
@@ -1024,6 +1146,7 @@
     private void stopSoftApInternal(int mode) {
         mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();
 
+        mSoftApExtendingWifi = false;
         mActiveModeWarden.stopSoftAp(mode);
     }
 
@@ -1156,6 +1279,15 @@
                     iterator.remove();
                 }
             }
+
+            if ((getState() == WifiManager.WIFI_AP_STATE_DISABLED) && mRestartWifiApIfRequired) {
+                mWifiThreadRunner.post(() -> {
+                    Log.d(TAG ,"Repeater mode: Restart SoftAP.");
+                    mRestartWifiApIfRequired = false;
+                    startSoftAp(null);
+                });
+            }
+
         }
 
         /**
@@ -1879,8 +2011,13 @@
     @NonNull
     @Override
     public SoftApConfiguration getSoftApConfiguration() {
-        enforceNetworkSettingsPermission();
         int uid = Binder.getCallingUid();
+        if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)
+                && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
+            // random apps should not be allowed to read the user specified config
+            throw new SecurityException("App not allowed to read or update stored WiFi Ap config "
+                    + "(uid = " + uid + ")");
+        }
         if (mVerboseLoggingEnabled) {
             mLog.info("getSoftApConfiguration uid=%").c(uid).flush();
         }
@@ -1933,9 +2070,14 @@
     @Override
     public boolean setSoftApConfiguration(
             @NonNull SoftApConfiguration softApConfig, @NonNull String packageName) {
-        enforceNetworkSettingsPermission();
         int uid = Binder.getCallingUid();
         boolean privileged = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
+        if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)
+                && !privileged) {
+            // random apps should not be allowed to read the user specified config
+            throw new SecurityException("App not allowed to read or update stored WiFi Ap config "
+                    + "(uid = " + uid + ")");
+        }
         mLog.info("setSoftApConfiguration uid=%").c(uid).flush();
         if (softApConfig == null) return false;
         if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged)) {
@@ -1982,7 +2124,7 @@
      * see {@link android.net.wifi.WifiManager#disconnect()}
      */
     @Override
-    public boolean disconnect(String packageName) {
+    public boolean disconnect2(int staId, String packageName) {
         if (enforceChangePermission(packageName) != MODE_ALLOWED) {
             return false;
         }
@@ -1993,11 +2135,26 @@
             return false;
         }
         mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush();
-        mClientModeImpl.disconnectCommand();
+        if (staId == STA_PRIMARY) {
+            mClientModeImpl.disconnectCommand();
+        } else {
+            QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+            if (qtiClientModeImpl == null) return false;
+            qtiClientModeImpl.disconnectCommand();
+        }
         return true;
     }
 
     /**
+     * see {@link android.net.wifi.WifiManager#disconnect()}
+     * @hide
+     */
+    @Override
+    public boolean disconnect(String packageName) {
+        return disconnect2(STA_PRIMARY, packageName);
+    }
+
+    /**
      * see {@link android.net.wifi.WifiManager#reconnect()}
      */
     @Override
@@ -2122,7 +2279,7 @@
      * @return the list of configured networks
      */
     @Override
-    public ParceledListSlice<WifiConfiguration> getConfiguredNetworks(String packageName,
+    public ParceledListSlice<WifiConfiguration> getConfiguredNetworks2(int staId, String packageName,
             String featureId) {
         enforceAccessPermission();
         int callingUid = Binder.getCallingUid();
@@ -2162,9 +2319,21 @@
             targetConfigUid = callingUid; // expose only those configs created by the Carrier App
         }
         int finalTargetConfigUid = targetConfigUid;
-        List<WifiConfiguration> configs = mWifiThreadRunner.call(
+        List<WifiConfiguration> configs = null;
+        if (staId == STA_PRIMARY) {
+            configs = mWifiThreadRunner.call(
                 () -> mWifiConfigManager.getSavedNetworks(finalTargetConfigUid),
-                Collections.emptyList());
+                               Collections.emptyList());
+        } else if (staId == STA_SECONDARY) {
+            configs = mWifiThreadRunner.call(
+                            () -> mWifiInjector.makeOrGetQtiWifiConfigManager().getSavedNetworks(finalTargetConfigUid),
+                                       Collections.emptyList());
+        }
+        if (configs == null ) {
+            Log.e(TAG, "Configs is null");
+            return null;
+        }
+
         if (isTargetSdkLessThanQOrPrivileged) {
             return new ParceledListSlice<>(configs);
         }
@@ -2179,6 +2348,17 @@
     }
 
     /**
+     * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()}
+     *
+     * @param packageName String name of the calling package
+     * @return the list of configured networks
+     */
+    @Override
+    public ParceledListSlice<WifiConfiguration> getConfiguredNetworks(String packageName, String featureId) {
+        return getConfiguredNetworks2(STA_PRIMARY, packageName, featureId);
+    }
+
+    /**
      * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()}
      *
      * @param packageName String name of the calling package
@@ -2400,11 +2580,22 @@
 
         Log.i("addOrUpdateNetwork", " uid = " + Binder.getCallingUid()
                 + " SSID " + config.SSID
-                + " nid=" + config.networkId);
-        return mWifiThreadRunner.call(
-            () -> mWifiConfigManager.addOrUpdateNetwork(config, callingUid, packageName)
-                    .getNetworkId(),
-                WifiConfiguration.INVALID_NETWORK_ID);
+                + " nid=" + config.networkId
+                + " staId=" + Integer.toString(config.staId));
+        if (config.staId == STA_SECONDARY) {
+            return mWifiThreadRunner.call(
+                () -> mWifiInjector.makeOrGetQtiWifiConfigManager().addOrUpdateNetwork(config, callingUid, packageName)
+                        .getNetworkId(),
+                    WifiConfiguration.INVALID_NETWORK_ID);
+        } else if (config.staId == STA_PRIMARY) {
+            return mWifiThreadRunner.call(
+                () -> mWifiConfigManager.addOrUpdateNetwork(config, callingUid, packageName)
+                        .getNetworkId(),
+                    WifiConfiguration.INVALID_NETWORK_ID);
+        } else {
+			Log.e(TAG, "Invalid staId");
+			return -1;
+		}
     }
 
     public static void verifyCert(X509Certificate caCert)
@@ -2440,8 +2631,10 @@
         }
         int callingUid = Binder.getCallingUid();
         mLog.info("removeNetwork uid=%").c(callingUid).flush();
-        return mWifiThreadRunner.call(
-                () -> mWifiConfigManager.removeNetwork(netId, callingUid, packageName), false);
+        return (mWifiThreadRunner.call(
+                () -> mWifiConfigManager.removeNetwork(netId, callingUid, packageName), false) ||
+				mWifiThreadRunner.call(
+                () -> mWifiInjector.makeOrGetQtiWifiConfigManager().removeNetwork(netId, callingUid, packageName), false));
     }
 
     /**
@@ -2451,6 +2644,7 @@
      * @return
      */
     private boolean triggerConnectAndReturnStatus(int netId, int callingUid) {
+        int staId = getIdentityForNetwork(netId);
         final CountDownLatch countDownLatch = new CountDownLatch(1);
         final MutableBoolean success = new MutableBoolean(false);
         IActionListener.Stub connectListener = new IActionListener.Stub() {
@@ -2465,8 +2659,15 @@
                 countDownLatch.countDown();
             }
         };
-        mClientModeImpl.connect(null, netId, new Binder(), connectListener,
+        if(staId == STA_PRIMARY) {
+            mClientModeImpl.connect(null, netId, new Binder(), connectListener,
                 connectListener.hashCode(), callingUid);
+        } else if (staId == STA_SECONDARY) {
+            QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+            if(qtiClientModeImpl == null) return false;
+            qtiClientModeImpl.connect(null, netId, new Binder(), connectListener,
+                connectListener.hashCode(), callingUid);
+        }
         // now wait for response.
         try {
             countDownLatch.await(RUN_WITH_SCISSORS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
@@ -2504,9 +2705,10 @@
         if (disableOthers) {
             return triggerConnectAndReturnStatus(netId, callingUid);
         } else {
-            return mWifiThreadRunner.call(
-                    () -> mWifiConfigManager.enableNetwork(netId, false, callingUid, packageName),
-                    false);
+            return (mWifiThreadRunner.call(
+                        () -> mWifiConfigManager.enableNetwork(netId, false, callingUid, packageName), false) ||
+                    mWifiThreadRunner.call(
+                        () -> mWifiInjector.makeOrGetQtiWifiConfigManager().enableNetwork(netId, false, callingUid, packageName), false));
         }
     }
 
@@ -2529,8 +2731,11 @@
         }
         int callingUid = Binder.getCallingUid();
         mLog.info("disableNetwork uid=%").c(callingUid).flush();
-        return mWifiThreadRunner.call(
-                () -> mWifiConfigManager.disableNetwork(netId, callingUid, packageName), false);
+        int staId = getIdentityForNetwork(netId);
+        return (mWifiThreadRunner.call(
+                   () -> mWifiConfigManager.disableNetwork(netId, callingUid, packageName), false) ||
+                mWifiThreadRunner.call(
+                   () -> mWifiInjector.makeOrGetQtiWifiConfigManager().disableNetwork(netId, callingUid, packageName), false));
     }
 
     /**
@@ -2548,6 +2753,20 @@
     }
 
     /**
+     * See {@link android.net.wifi.WifiManager#allowConnectOnPartialScanResults(boolean)}
+     * @param
+     */
+    @Override
+    public void allowConnectOnPartialScanResults(boolean enable) {
+        enforceNetworkSettingsPermission();
+
+        int callingUid = Binder.getCallingUid();
+        mLog.info("allowConnectOnPartialScanResults=% uid=%").c(enable).c(callingUid).flush();
+
+        mWifiThreadRunner.post(() -> mClientModeImpl.allowConnectOnPartialScanResults(enable));
+    }
+
+    /**
      * See {@link android.net.wifi.WifiManager#allowAutojoin(int, boolean)}
      * @param netId the integer that identifies the network configuration
      * @param choice the user's choice to allow auto-join
@@ -2660,7 +2879,7 @@
      * @return the Wi-Fi information, contained in {@link WifiInfo}.
      */
     @Override
-    public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) {
+    public WifiInfo getConnectionInfo2(int staId, String callingPackage, String callingFeatureId) {
         enforceAccessPermission();
         int uid = Binder.getCallingUid();
         if (mVerboseLoggingEnabled) {
@@ -2668,7 +2887,16 @@
         }
         long ident = Binder.clearCallingIdentity();
         try {
-            WifiInfo result = mClientModeImpl.syncRequestConnectionInfo();
+            WifiInfo result;
+
+            if (staId == STA_PRIMARY) {
+                result = mClientModeImpl.syncRequestConnectionInfo();
+            } else {
+                QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+                if (qtiClientModeImpl == null) return null;
+                result = qtiClientModeImpl.syncRequestConnectionInfo();
+            }
+
             boolean hideDefaultMacAddress = true;
             boolean hideBssidSsidNetworkIdAndFqdn = true;
 
@@ -2708,6 +2936,15 @@
     }
 
     /**
+     * See {@link android.net.wifi.WifiManager#getConnectionInfo()}
+     * @hide
+     */
+    @Override
+    public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) {
+        return getConnectionInfo2(STA_PRIMARY, callingPackage, callingFeatureId);
+    }
+
+    /**
      * Return the results of the most recent access point scan, in the form of
      * a list of {@link ScanResult} objects.
      * @return the list of results
@@ -2891,6 +3128,10 @@
         mClientModeImpl.deauthenticateNetwork(mClientModeImplChannel, holdoff, ess);
     }
 
+    public String getCapabilities(String capaType) {
+        return mClientModeImpl.getCapabilities(capaType);
+    }
+
      /**
      * Get the country code
      * @return Get the best choice country code for wifi, regardless of if it was set or
@@ -3772,6 +4013,11 @@
                 false)) {
             supportedFeatureSet |= WifiManager.WIFI_FEATURE_AP_STA;
         }
+        if (mWifiThreadRunner.call(
+                () -> mActiveModeWarden.isDualStaSupported(),
+                false)) {
+            supportedFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA;
+        }
         return supportedFeatureSet;
     }
 
@@ -4042,6 +4288,268 @@
     }
 
     /**
+     * Add the DPP bootstrap info obtained from QR code.
+     *
+     * @param uri:The URI obtained from the QR code reader.
+     *
+     * @return: Handle to strored info else -1 on failure
+     * @hide
+     */
+    @Override
+    public int dppAddBootstrapQrCode(String uri) {
+        return mClientModeImpl.syncDppAddBootstrapQrCode(mClientModeImplChannel, uri);
+    }
+
+    /**
+     * Generate bootstrap URI based on the passed arguments
+     *
+     * @param config – bootstrap generate config
+     *
+     * @return: Handle to strored URI info else -1 on failure
+     */
+    @Override
+    public int dppBootstrapGenerate(WifiDppConfig config) {
+        return mClientModeImpl.syncDppBootstrapGenerate(mClientModeImplChannel, config);
+    }
+
+    /**
+     * Get bootstrap URI based on bootstrap ID
+     *
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: URI string else -1 on failure
+     */
+    @Override
+    public String dppGetUri(int bootstrap_id) {
+        return mClientModeImpl.syncDppGetUri(mClientModeImplChannel, bootstrap_id);
+    }
+
+    /**
+     * Remove bootstrap URI based on bootstrap ID.
+     *
+     * @param bootstrap_id: Stored bootstrap ID
+     *
+     * @return: 0 – Success or -1 on failure
+     */
+    @Override
+    public int dppBootstrapRemove(int bootstrap_id) {
+        return mClientModeImpl.syncDppBootstrapRemove(mClientModeImplChannel, bootstrap_id);
+    }
+
+    /**
+     * start listen on the channel specified waiting to receive
+     * the DPP Authentication request.
+     *
+     * @param frequency: DPP listen frequency
+     * @param dpp_role: Configurator/Enrollee role
+     * @param qr_mutual: Mutual authentication required
+     * @param netrole_ap: network role
+     *
+     * @return: Returns 0 if a DPP-listen work is successfully
+     *  queued and -1 on failure.
+     */
+    @Override
+    public int dppListen(String frequency, int dpp_role, boolean qr_mutual, boolean netrole_ap) {
+        return mClientModeImpl.syncDppListen(mClientModeImplChannel, frequency, dpp_role,
+                                               qr_mutual, netrole_ap);
+    }
+
+    /**
+     * stop ongoing dpp listen
+     */
+    @Override
+    public void dppStopListen() {
+        mClientModeImpl.dppStopListen(mClientModeImplChannel);
+    }
+
+    /**
+     * Adds the DPP configurator
+     *
+     * @param curve curve used for dpp encryption
+     * @param key private key
+     * @param expiry timeout in seconds
+     *
+     * @return: Identifier of the added configurator or -1 on failure
+     */
+    @Override
+    public int dppConfiguratorAdd(String curve, String key, int expiry) {
+        return mClientModeImpl.syncDppConfiguratorAdd(
+            mClientModeImplChannel, curve, key, expiry);
+    }
+
+    /**
+     * Remove the added configurator through dppConfiguratorAdd.
+     *
+     * @param config_id: DPP Configurator ID
+     *
+     * @return: Handle to strored info else -1 on failure
+     */
+    @Override
+    public int dppConfiguratorRemove(int config_id) {
+        return mClientModeImpl.syncDppConfiguratorRemove(mClientModeImplChannel, config_id);
+    }
+
+    /**
+     * Start DPP authentication and provisioning with the specified peer
+     *
+     * @param config – dpp auth init config
+     *
+     * @return: 0 if DPP Authentication request was transmitted and -1 on failure
+     */
+    @Override
+    public int  dppStartAuth(WifiDppConfig config) {
+        return mClientModeImpl.syncDppStartAuth(mClientModeImplChannel, config);
+    }
+
+    /**
+     * Retrieve Private key to be used for configurator
+     *
+     * @param id: id of configurator object
+     *
+     * @return: KEY string else -1 on failure
+     */
+    public String dppConfiguratorGetKey(int id) {
+        return mClientModeImpl.syncDppConfiguratorGetKey(mClientModeImplChannel, id);
+    }
+
+    private void setDualSapMode(SoftApConfiguration apConfig) {
+        if (apConfig == null)
+            apConfig = mWifiApConfigStore.getApConfiguration();
+
+        if (apConfig.getBand() == SoftApConfiguration.BAND_DUAL
+                || apConfig.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OWE) {
+            mLog.trace("setDualSapMode uid=%").c(Binder.getCallingUid()).flush();
+            mWifiApConfigStore.setDualSapStatus(true);
+        } else {
+            mWifiApConfigStore.setDualSapStatus(false);
+        }
+    }
+
+    /* API to check whether SoftAp extending current sta connected AP network*/
+    public boolean isExtendingWifi() {
+        return mSoftApExtendingWifi;
+    }
+
+    public boolean isCurrentStaShareThisAp() {
+        if(!isWifiCoverageExtendFeatureEnabled())
+            return false;
+
+        WifiConfiguration currentStaConfig = mClientModeImpl.getCurrentWifiConfiguration();
+
+        if (currentStaConfig != null && currentStaConfig.shareThisAp) {
+            int authType = currentStaConfig.getAuthType();
+
+            if (authType == WifiConfiguration.KeyMgmt.NONE || authType == WifiConfiguration.KeyMgmt.WPA_PSK)
+                return true;
+        }
+
+        return false;
+    }
+
+    private void startSoftApInRepeaterMode(int mode, SoftApConfiguration apConfig) {
+        WifiInfo wifiInfo = mClientModeImpl.getWifiInfo();
+        WifiConfigManager wifiConfigManager = mWifiInjector.getWifiConfigManager();
+        WifiConfiguration currentStaConfig = wifiConfigManager.getConfiguredNetworkWithPassword(wifiInfo.getNetworkId());
+        SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(
+            ApConfigUtil.fromWifiConfiguration(currentStaConfig));
+
+        // Remove double quotes in SSID and psk
+        softApConfigBuilder.setSsid(WifiInfo.removeDoubleQuotes(currentStaConfig.SSID));
+        if (currentStaConfig.getAuthType() == WifiConfiguration.KeyMgmt.WPA_PSK) {
+            softApConfigBuilder.setPassphrase(WifiInfo.removeDoubleQuotes(currentStaConfig.preSharedKey),
+                SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+        }
+
+        // Get band info from SoftAP configuration
+        if (apConfig == null)
+            softApConfigBuilder.setBand(mWifiApConfigStore.getApConfiguration().getBand());
+        else
+            softApConfigBuilder.setBand(apConfig.getBand());
+
+        SoftApConfiguration softApConfig = softApConfigBuilder.build();
+        Log.d(TAG,"Repeater mode config - " + softApConfig);
+        SoftApModeConfiguration softApModeConfig = new SoftApModeConfiguration(mode, softApConfig,
+                mTetheredSoftApTracker.getSoftApCapability());
+        mActiveModeWarden.startSoftAp(softApModeConfig);
+
+    }
+
+    public boolean isWifiCoverageExtendFeatureEnabled() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(WIFI_COVERAGE_EXTEND_FEATURE_ENABLED);
+    }
+
+    public void enableWifiCoverageExtendFeature(boolean enable) {
+        enforceAccessPermission();
+        enforceNetworkSettingsPermission();
+        mLog.info("enableWifiCoverageExtendFeature uid=% enable=%")
+                .c(Binder.getCallingUid())
+                .c(enable).flush();
+         mWifiInjector.getSettingsConfigStore().put(WIFI_COVERAGE_EXTEND_FEATURE_ENABLED, enable);
+    }
+
+    @Override
+    public boolean isSoftApOcvFeatureEnabled() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(SOFTAP_OCV_ENABLED);
+    }
+
+    @Override
+    public boolean isSoftApOcvFeatureSupported() {
+        enforceAccessPermission();
+        return mContext.getResources().getBoolean(
+                R.bool.config_vendor_softap_ocv_supported);
+    }
+
+    @Override
+    public void enableSoftApOcvFeature(boolean enable) {
+        enforceAccessPermission();
+        enforceNetworkSettingsPermission();
+        mLog.info("enableSoftApOcvFeature uid=% enable=%")
+                .c(Binder.getCallingUid())
+                .c(enable).flush();
+        enableSoftApOcvFeatureInternal(enable);
+    }
+
+    private void enableSoftApOcvFeatureInternal(boolean enable) {
+        mWifiInjector.getSettingsConfigStore().put(SOFTAP_OCV_ENABLED, enable);
+        mClientModeImpl.enableSoftApOcvFeature(enable);
+    }
+
+    @Override
+    public boolean isSoftApBeaconProtFeatureEnabled() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(SOFTAP_BEACON_PROTECTION_ENABLED);
+    }
+
+    @Override
+    public boolean isSoftApBeaconProtFeatureSupported() {
+        return mContext.getResources().getBoolean(
+                R.bool.config_vendor_softap_beacon_protection_supported);
+    }
+
+    @Override
+    public void enableSoftApBeaconProtFeature(boolean enable) {
+        enforceAccessPermission();
+        enforceNetworkSettingsPermission();
+        mLog.info("enableSoftApBeaconProtFeature uid=% enable=%")
+                .c(Binder.getCallingUid())
+                .c(enable).flush();
+        enableSoftApBeaconProtFeatureInternal(enable);
+    }
+
+    private void enableSoftApBeaconProtFeatureInternal(boolean enable) {
+        mWifiInjector.getSettingsConfigStore().put(SOFTAP_BEACON_PROTECTION_ENABLED, enable);
+        mClientModeImpl.enableSoftApBeaconProtFeature(enable);
+    }
+
+    @Override
+    public int isConcurrentBandSupported() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(HW_SUPPORTED_FEATURES);
+    }
+
+    /**
      * see {@link android.net.wifi.WifiManager#addOnWifiUsabilityStatsListener(Executor,
      * OnWifiUsabilityStatsListener)}
      *
@@ -4131,12 +4639,25 @@
             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);
+        int staId;
+        if(config != null) staId = config.staId;
+        else staId = getIdentityForNetwork(netId);
+        if(staId == STA_PRIMARY) {
+        } else {
+            QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+            if (qtiClientModeImpl != null)
+                qtiClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid);
         }
+        if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
+            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);
     }
-
     /**
      * see {@link android.net.wifi.WifiManager#save(WifiConfiguration,
      * WifiManager.ActionListener)}
@@ -4148,8 +4669,20 @@
             throw new SecurityException(TAG + ": Permission denied");
         }
         mLog.info("save uid=%").c(Binder.getCallingUid()).flush();
-        mClientModeImpl.save(
-                config, binder, callback, callbackIdentifier, Binder.getCallingUid());
+        if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
+            mWifiMetrics.logUserActionEvent(
+                    UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId);
+        }
+        int staId = config.staId;
+        if(staId == STA_PRIMARY) {
+            mClientModeImpl.save(
+                    config, binder, callback, callbackIdentifier, Binder.getCallingUid());
+        } else {
+            QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+            if (qtiClientModeImpl != null)
+                qtiClientModeImpl.save(
+                    config, binder, callback, callbackIdentifier, Binder.getCallingUid());
+        }
     }
 
     /**
@@ -4168,7 +4701,14 @@
             // the netId becomes invalid after the forget operation.
             mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_FORGET_WIFI, netId);
         }
-        mClientModeImpl.forget(netId, binder, callback, callbackIdentifier, uid);
+        int staId = getIdentityForNetwork(netId);
+        if(staId == STA_PRIMARY) {
+            mClientModeImpl.forget(netId, binder, callback, callbackIdentifier, uid);
+        } else {
+           QtiClientModeImpl qtiClientModeImpl = mActiveModeWarden.getQtiClientModeImpl(staId);
+           if (qtiClientModeImpl != null)
+               qtiClientModeImpl.forget(netId, binder, callback, callbackIdentifier, uid);
+        }
     }
 
     /**
@@ -4346,4 +4886,256 @@
         }
         return mWifiThreadRunner.call(()-> mWifiInjector.getWakeupController().isEnabled(), false);
     }
+
+    /*
+     * Gets SoftAP Wi-Fi Standard
+     * @return Wi-Fi standard if SoftAp enabled or -1.
+     */
+    @Override
+    public int getSoftApWifiStandard() {
+        enforceAccessPermission();
+        if (getWifiApEnabledState() == WifiManager.WIFI_AP_STATE_ENABLED) {
+            return mWifiApConfigStore.getWifiStandard();
+        } else {
+            return -1;
+        }
+    }
+
+    /*
+     * Check if the driver supports 11ax ready
+     * @return {true} if supported, {false} otherwise.
+     */
+    @Override
+    public boolean isVht8ssCapableDevice() {
+        enforceAccessPermission();
+        return mContext.getResources().getBoolean(R.bool.config_vendorWifi11axReadySupport);
+    }
+
+    @Override
+    public String doDriverCmd(String command)
+    {
+        return mClientModeImpl.doDriverCmd(mClientModeImplChannel, command);
+    }
+
+    private final class WifiNotificationCallbackImpl implements QtiClientModeManager.Listener {
+        @Override
+        public void onStateChanged(int staId, int newState) {
+            if (mVerboseLoggingEnabled)
+                Log.d(TAG, "[wifi" + staId + "] State changed from client mode. state = " + newState);
+
+            mQtiWifiNewState.put(staId, newState);
+
+            // Clear out the events for NetworkInfo/LinkLayer/RSSI on wifi disable
+            if (newState == WifiManager.WIFI_STATE_DISABLED) {
+                mQtiWifiRssi.remove(staId);
+                mQtiWifiLinkProperties.remove(staId);
+                mQtiWifiNetworkInfo.remove(staId);
+            }
+
+            Iterator<IWifiNotificationCallback> iterator =
+                    mRegisteredWifiCallbacks.getCallbacks(staId).iterator();
+            while (iterator.hasNext()) {
+                IWifiNotificationCallback callback = iterator.next();
+                try {
+                    callback.onStateChanged(newState);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "onStateChanged: remote exception -- " + e);
+                    iterator.remove();
+                }
+            }
+        }
+
+        @Override
+        public void onRssiChanged(int staId, int rssi) {
+            if (mVerboseLoggingEnabled)
+                Log.d(TAG, "[wifi" + staId + "] rssi changed from client mode. rssi = " + rssi);
+
+            mQtiWifiRssi.put(staId, rssi);
+
+            Iterator<IWifiNotificationCallback> iterator =
+                    mRegisteredWifiCallbacks.getCallbacks(staId).iterator();
+            while (iterator.hasNext()) {
+                IWifiNotificationCallback callback = iterator.next();
+                try {
+                    callback.onRssiChanged(rssi);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "onRssiChanged: remote exception -- " + e);
+                    iterator.remove();
+                }
+            }
+        }
+
+        @Override
+        public void onLinkConfigurationChanged(int staId, LinkProperties lp) {
+            if (mVerboseLoggingEnabled)
+                Log.d(TAG, "[wifi" + staId + "] link changed from client mode. lp = " + lp);
+
+            mQtiWifiLinkProperties.put(staId, lp);
+
+            Iterator<IWifiNotificationCallback> iterator =
+                    mRegisteredWifiCallbacks.getCallbacks(staId).iterator();
+            while (iterator.hasNext()) {
+                IWifiNotificationCallback callback = iterator.next();
+                try {
+                    callback.onLinkConfigurationChanged(lp);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "onLinkConfigurationChanged: remote exception -- " + e);
+                    iterator.remove();
+                }
+            }
+        }
+
+        @Override
+        public void onNetworkStateChanged(int staId, NetworkInfo netInfo) {
+            if (mVerboseLoggingEnabled)
+                Log.d(TAG, "[wifi" + staId + "] network state changed from client mode. netInfo = " + netInfo);
+
+            mQtiWifiNetworkInfo.put(staId, netInfo);
+
+            Iterator<IWifiNotificationCallback> iterator =
+                    mRegisteredWifiCallbacks.getCallbacks(staId).iterator();
+            while (iterator.hasNext()) {
+                IWifiNotificationCallback callback = iterator.next();
+                try {
+                    callback.onNetworkStateChanged(netInfo);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "onNetworkStateChanged: remote exception -- " + e);
+                    iterator.remove();
+                }
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void registerForWifiNotification(int staId, IBinder binder,
+            IWifiNotificationCallback callback,
+            int callbackIdentifier) {
+        if (binder == null || callback == null) {
+            Log.e(TAG, "Binder or callback must not be null");
+            return;
+        }
+
+        if (getNumConcurrentStaSupported() < 2 || staId < STA_SECONDARY) {
+            Log.e(TAG, "registerForWifiNotification not allowed for id:"+staId);
+            return;
+        }
+
+        mLog.info("registerForWifiNotification uid=%").c(Binder.getCallingUid()).flush();
+
+        // post operation to handler thread
+        mWifiThreadRunner.post(() -> {
+            // reserve lowest 4 bits for staId
+            int callbackIdentifierExt = (callbackIdentifier << 4) | (staId & 0xF);
+
+            if (!mRegisteredWifiCallbacks.add(binder, callback, callbackIdentifierExt)) {
+                Log.e(TAG, "registerForWifiNotification: Failed to add callback");
+                return;
+            }
+            // Update the client about the current state immediately after registering the callback
+            try {
+                Integer rssi = mQtiWifiRssi.get(staId);
+                int iRssi = rssi == null ? 0 : rssi.intValue();
+
+                Integer newState = mQtiWifiNewState.get(staId);
+                int iNewState = newState == null ? -1 : newState.intValue();
+
+                LinkProperties lp = mQtiWifiLinkProperties.get(staId);
+                NetworkInfo netInfo = mQtiWifiNetworkInfo.get(staId);
+
+                if (iRssi != 0)
+                    callback.onRssiChanged(rssi);
+                if (iNewState != -1)
+                     callback.onStateChanged(newState);
+                if (lp != null)
+                     callback.onLinkConfigurationChanged(lp);
+                if (netInfo != null)
+                    callback.onNetworkStateChanged(netInfo);
+            } catch (RemoteException e) {
+                Log.e(TAG, "registerForWifiNotification: remote exception -- " + e);
+            }
+        });
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void unregisterForWifiNotification(int staId, int callbackIdentifier) {
+        mLog.info("unregisterForWifiNotification uid=%").c(Binder.getCallingUid()).flush();
+
+        if (getNumConcurrentStaSupported() < 2 || staId < STA_SECONDARY) {
+            Log.e(TAG, "unregisterForWifiNotification not allowed for id:"+staId);
+            return;
+        }
+
+        // post operation to handler thread
+        mWifiThreadRunner.post(() -> {
+            // reserve lowest 4 bits for staId
+            int callbackIdentifierExt = (callbackIdentifier << 4) | (staId & 0xF);
+
+            mRegisteredWifiCallbacks.remove(callbackIdentifierExt);
+        });
+    }
+
+    private int getNumConcurrentStaSupported() {
+        // TODO: isAdditionalStaSupported() only valid when wifi enabled.
+        mLog.info("getNumConcurrentStaSupported uid=%").c(Binder.getCallingUid()).flush();
+        if (mWifiThreadRunner.call(
+                () -> mActiveModeWarden.isDualStaSupported(),
+                false)) {
+            return 2;
+        } else {
+            return 1;
+        }
+    }
+
+    private int getIdentityForNetwork(int netId) {
+        WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId);
+        if (config == null) {
+            for(int i = STA_SECONDARY; i <= getNumConcurrentStaSupported();i++) {
+                config = mWifiInjector.makeOrGetQtiWifiConfigManager().getConfiguredNetwork(netId);
+                if (config != null) {
+                    break;
+                }
+            }
+            if (config == null)
+                return -1;
+        }
+        return config.staId;
+    }
+
+    @Override
+    public boolean isWhitelistNetworkRoamingEnabled() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(WIFI_WHITELIST_ROAMING_ENABLED);
+    }
+
+    @Override
+    public void enableWhitelistNetworkRoaming(boolean enable) {
+        enforceAccessPermission();
+        enforceNetworkSettingsPermission();
+        mLog.info("enableWhitelistNetworkRoaming uid=% enable=%")
+                .c(Binder.getCallingUid())
+                .c(enable).flush();
+        mWifiInjector.getSettingsConfigStore().put(WIFI_WHITELIST_ROAMING_ENABLED, enable);
+    }
+
+    @Override
+    public boolean isNewNetworkAutoConnectionEnabled() {
+        enforceAccessPermission();
+        return mWifiInjector.getSettingsConfigStore().get(WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED);
+    }
+
+    @Override
+    public void enableNewNetworkAutoConnection(boolean enable) {
+        enforceAccessPermission();
+        enforceNetworkSettingsPermission();
+        mLog.info("enableNewNetworkAutoConnection uid=% enable=%")
+                .c(Binder.getCallingUid())
+                .c(enable).flush();
+        mWifiInjector.getSettingsConfigStore().put(WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED, enable);
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
index d77aa48..a17d66d 100644
--- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
@@ -50,6 +50,13 @@
     // List of all allowed keys.
     private static final ArrayList<Key> sKeys = new ArrayList<>();
 
+    /**
+     * Setting to enable Beacon Protection in SAP; disabled by default, and setting to 1
+     * will enable it. In the future, additional values may be supported.
+     */
+    public static final Key<Boolean> SOFTAP_BEACON_PROTECTION_ENABLED =
+            new Key<>("softap_beacon_protection_enabled", false);
+
     /******** Wifi shared pref keys ***************/
     /**
      * Indicate whether factory reset request is pending.
@@ -58,6 +65,13 @@
             new Key<>("wifi_p2p_pending_factory_reset", false);
 
     /**
+     * Setting to enable OCV in SAP; disabled by default, and setting to 1
+     * will enable it. In the future, additional values may be supported.
+     */
+    public static final Key<Boolean> SOFTAP_OCV_ENABLED =
+            new Key<>("softap_ocv_enabled", false);
+
+    /**
      * Allow scans to be enabled even wifi is turned off.
      */
     public static final Key<Boolean> WIFI_SCAN_ALWAYS_AVAILABLE =
@@ -82,7 +96,31 @@
     public static final Key<String> WIFI_P2P_DEVICE_NAME =
             new Key<>("wifi_p2p_device_name", null);
 
-    /******** Wifi shared pref keys ***************/
+    /**
+     * Extend Wifi Coverage
+     */
+    public static final Key<Boolean> WIFI_COVERAGE_EXTEND_FEATURE_ENABLED =
+            new Key<>("wifi_coverage_extend_feature_enabled", false);
+
+    /**
+     * Enable/disbale Wi-Fi whitelist network roaming
+     */
+    public static final Key<Boolean> WIFI_WHITELIST_ROAMING_ENABLED =
+            new Key<>("wifi_whitelist_roaming_enabled", true);
+
+    /**
+     * Enable/disble Wi=Fi new network auto connection attempts
+     */
+    public static final Key<Boolean> WIFI_NEW_NETWORK_AUTO_CONNECTION_ENABLED =
+            new Key<>("wifi_new_network_auto_connection_enabled", true);
+    /**
+     * Concurrent network session support
+     */
+    public static final Key<Integer> HW_SUPPORTED_FEATURES =
+            new Key<>("hw_supported_features", 0);
+
+
+   /******** Wifi shared pref keys ***************/
 
     private final Context mContext;
     private final Handler mHandler;
@@ -387,5 +425,12 @@
             // Shared general store.
             return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
         }
+
+        @Override
+        public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+            // Shared general store. 
+            // Return is independent of staId as Settings is not used for secondary.
+            return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
+        }
     }
 }
diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java
index a3cae77..93bf48e 100644
--- a/service/java/com/android/server/wifi/WifiShellCommand.java
+++ b/service/java/com/android/server/wifi/WifiShellCommand.java
@@ -118,6 +118,7 @@
     private final Context mContext;
     private final ConnectivityManager mConnectivityManager;
     private final WifiCarrierInfoManager mWifiCarrierInfoManager;
+    private final WifiSecShellCmd mSecCmd;
 
     WifiShellCommand(WifiInjector wifiInjector, WifiServiceImpl wifiService, Context context) {
         mClientModeImpl = wifiInjector.getClientModeImpl();
@@ -132,6 +133,7 @@
         mContext = context;
         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
         mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager();
+        mSecCmd = new WifiSecShellCmd(wifiInjector);
     }
 
     @Override
@@ -662,6 +664,9 @@
                     mWifiService.clearWifiConnectedNetworkScorer(); // clear any previous scorer
                     return 0;
                 }
+                case "sec": {
+                    return execSecondaryCommand(pw);
+                }
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -675,6 +680,134 @@
         }
     }
 
+    private int execSecondaryCommand(PrintWriter pw) throws InterruptedException {
+        String subCmd = getNextArgRequired();
+        switch(subCmd != null ? subCmd : "") {
+            case "enable": {
+                pw.println("Enabling Secondary station");
+                mSecCmd.enable();
+                break;
+            }
+            case "disable": {
+                pw.println("Disabling Secondary station");
+                mSecCmd.disable();
+                break;
+            }
+            case "add-network": {
+                String ssid = getNextArgRequired();
+                String password = getNextArg();
+                pw.println("Add network on Secondary station. ssid="+ssid+ " password="+password);
+                int id = mSecCmd.addNetwork(ssid, password);
+                pw.println(" network id=" + id);
+                break;
+            }
+            case "remove-network": {
+                int netId = Integer.parseInt(getNextArgRequired());
+                pw.println("Remove network on Secondary station id=" + netId);
+                mSecCmd.removeNetwork(netId);
+                break;
+            }
+            case "connect": {
+                String ssid = getNextArgRequired();
+                String password = getNextArg();
+                pw.println("connect on Secondary station ssid=" + ssid);
+                mSecCmd.connectNetwork(ssid, password);
+                break;
+            }
+            case "connect-netId": {
+                int netId = Integer.parseInt(getNextArgRequired());
+                pw.println("connect on Secondary station ssid=" + netId);
+                mSecCmd.connectNetwork(netId);
+                break;
+            }
+            case "disconnect": {
+                pw.println("disconnect on Secondary station");
+                mSecCmd.disconnect();
+                break;
+            }
+            case "forget-network": {
+                int netId = Integer.parseInt(getNextArgRequired());
+                pw.println("forget network on Secondary station id=" + netId);
+                mSecCmd.forgetNetwork(netId);
+                break;
+            }
+            case "save-network": {
+                String ssid = getNextArgRequired();
+                String password = getNextArg();
+                pw.println("save network on Secondary station. ssid="+ssid+ " password="+password);
+                mSecCmd.saveNetwork(ssid, password);
+                break;
+            }
+            case "enable-network": {
+                int netId = Integer.parseInt(getNextArgRequired());
+                pw.println("enable network on Secondary station id=" + netId);
+                mSecCmd.enableNetwork(netId);
+                break;
+            }
+            case "disable-network": {
+                int netId = Integer.parseInt(getNextArgRequired());
+                pw.println("disable network on Secondary station id=" + netId);
+                mSecCmd.disableNetwork(netId);
+                break;
+            }
+            case "list-network": {
+                mSecCmd.listNetwork(pw);
+                break;
+            }
+            case "status": {
+                mSecCmd.status(pw);
+                break;
+            }
+/*
+            case "": {
+                break;
+            }
+            case "": {
+                break;
+            }
+*/
+            case "help":
+            default:
+                return printSecHelp(pw);
+        }
+        return 0;
+    }
+
+    private int printSecHelp(PrintWriter pw) throws InterruptedException {
+        pw.println("Secondary Wi-Fi (wifi) commands:");
+        pw.println("  help");
+        pw.println("    Print this help text for secondary inteface.");
+        pw.println("  enable");
+        pw.println("    enable's secondary station through wifi controller");
+        pw.println("  disable");
+        pw.println("    disable's secondary station through wifi controller");
+        pw.println("  add-network <SSID> <PSK>");
+        pw.println("     add a new network with SSID and PSK(optional)");
+        pw.println("  save-network <SSID> <PSK>");
+        pw.println("     similar to 'add' but uses SAVE_NETWORK command");
+        pw.println("  remove-network <NET-ID>");
+        pw.println("     remove existing network with id NET-ID");
+        pw.println("  forget-network <NET-ID>");
+        pw.println("     similar to 'remove' but uses FORGET_NETWORK command");
+        pw.println("  connect-netId <NET-ID>");
+        pw.println("     connect to a network with NET-ID");
+        pw.println("  connect <SSID> <PSK>");
+        pw.println("     connect to a network with given ssid and password");
+        pw.println("  disconnect");
+        pw.println("     discconnect existing network");
+        pw.println("  enable-network <NET-ID>");
+        pw.println("     enable a network for connection");
+        pw.println("  disable-network <NET-ID>");
+        pw.println("     disconnect and disable a network for connection");
+        pw.println("  list-network");
+        pw.println("     list saved network for secondary");
+        pw.println("  status");
+        pw.println("     get current status of secondary station");
+        pw.println();
+
+        return 0;
+    }
+
     private boolean getNextArgRequiredTrueOrFalse(String trueString, String falseString)
             throws IllegalArgumentException {
         String nextArg = getNextArgRequired();
diff --git a/service/java/com/android/server/wifi/WifiTrafficPoller.java b/service/java/com/android/server/wifi/WifiTrafficPoller.java
index 8349f7b..48c8781 100644
--- a/service/java/com/android/server/wifi/WifiTrafficPoller.java
+++ b/service/java/com/android/server/wifi/WifiTrafficPoller.java
@@ -54,6 +54,7 @@
     }
 
     private final ExternalCallbackTracker<CallbackWrapper> mRegisteredCallbacks;
+    private String mInterface;
 
     public WifiTrafficPoller(@NonNull Handler handler) {
         mRegisteredCallbacks = new ExternalCallbackTracker<>(handler);
@@ -75,6 +76,12 @@
         mRegisteredCallbacks.remove(callbackId);
     }
 
+    void setInterface(String iface) {
+        mTxPkts = mRxPkts = 0;
+        mLastActivity = 0;
+        mInterface = iface;
+    }
+
     /**
      * Notifies clients of data activity if the activity changed since the last update.
      */
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index fd90c35..9817451 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -431,6 +431,10 @@
         }
     }
 
+    private Handler getHandlerForStaSapConcurrency() {
+        return (isStaApConcurrencySupported()) ? mHalEventHandler : null;
+    }
+
     /**
      * Create a STA iface using {@link HalDeviceManager}.
      *
@@ -440,7 +444,8 @@
     public String createStaIface(InterfaceDestroyedListener destroyedListener) {
         synchronized (sLock) {
             IWifiStaIface iface = mHalDeviceManager.createStaIface(
-                    new StaInterfaceDestroyedListenerInternal(destroyedListener), null);
+                    new StaInterfaceDestroyedListenerInternal(destroyedListener),
+                    getHandlerForStaSapConcurrency());
             if (iface == null) {
                 mLog.err("Failed to create STA iface").flush();
                 return stringResult(null);
@@ -518,7 +523,8 @@
     public String createApIface(InterfaceDestroyedListener destroyedListener) {
         synchronized (sLock) {
             IWifiApIface iface = mHalDeviceManager.createApIface(
-                    new ApInterfaceDestroyedListenerInternal(destroyedListener), null);
+                    new ApInterfaceDestroyedListenerInternal(destroyedListener),
+                    getHandlerForStaSapConcurrency());
             if (iface == null) {
                 mLog.err("Failed to create AP iface").flush();
                 return stringResult(null);
@@ -2291,7 +2297,18 @@
                     for (String ssidStr : config.whitelistSsids) {
                         byte[] ssid = NativeUtil.byteArrayFromArrayList(
                                 NativeUtil.decodeSsid(ssidStr));
-                        roamingConfig.ssidWhitelist.add(ssid);
+                        if (ssid.length > 32) {
+                            throw new IllegalArgumentException("configureRoaming: ssid too long");
+                        }
+
+                        // StaRoamingConfig.ssidWhitelist is a list of byte arrays with fixed length(32)
+                        // Due to this HAL code doesn't accept byte arrays of length less than 32
+                        // Thus convert all ssids to byte arrays of 32 length
+                        byte[] ssid_32 = new byte[32];
+                        for (int i = 0; i < ssid.length; i++) {
+                            ssid_32[i] = ssid[i];
+                        }
+                        roamingConfig.ssidWhitelist.add(ssid_32);
                     }
                 }
 
@@ -2646,6 +2663,16 @@
         }
     }
 
+    /**
+     * Returns whether Dual STA is supported or not.
+     */
+    public boolean isDualStaSupported() {
+        synchronized (sLock) {
+            return mHalDeviceManager.canSupportIfaceCombo(new SparseArray<Integer>() {{
+                    put(IfaceType.STA, 2);
+                }});
+        }
+    }
     // This creates a blob of IE elements from the array received.
     // TODO: This ugly conversion can be removed if we put IE elements in ScanResult.
     private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) {
@@ -3080,36 +3107,38 @@
     public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener {
         @Override
         public void onStatusChanged() {
-            boolean isReady = mHalDeviceManager.isReady();
-            boolean isStarted = mHalDeviceManager.isStarted();
+            mHalEventHandler.post(() -> {
+                boolean isReady = mHalDeviceManager.isReady();
+                boolean isStarted = mHalDeviceManager.isStarted();
 
-            mVerboseLog.i("Device Manager onStatusChanged. isReady(): " + isReady
-                    + ", isStarted(): " + isStarted);
-            if (!isReady) {
-                // Probably something unpleasant, e.g. the server died
-                WifiNative.VendorHalDeathEventHandler handler;
-                synchronized (sLock) {
-                    clearState();
-                    handler = mDeathEventHandler;
-                }
-                if (handler != null) {
-                    handler.onDeath();
-                }
-            }
-            if (isStarted) {
-                synchronized (sLock) {
-                    if (mStaIfaceAvailableForRequestListener != null) {
-                        mHalDeviceManager.registerInterfaceAvailableForRequestListener(
-                                IfaceType.STA, mStaIfaceAvailableForRequestListener,
-                                mHalEventHandler);
+                mVerboseLog.i("Device Manager onStatusChanged. isReady(): " + isReady
+                        + ", isStarted(): " + isStarted);
+                if (!isReady) {
+                    // Probably something unpleasant, e.g. the server died
+                    WifiNative.VendorHalDeathEventHandler handler;
+                    synchronized (sLock) {
+                        clearState();
+                        handler = mDeathEventHandler;
                     }
-                    if (mApIfaceAvailableForRequestListener != null) {
-                        mHalDeviceManager.registerInterfaceAvailableForRequestListener(
-                                IfaceType.AP, mApIfaceAvailableForRequestListener,
-                                mHalEventHandler);
+                    if (handler != null) {
+                        handler.onDeath();
                     }
                 }
-            }
+                if (isStarted) {
+                    synchronized (sLock) {
+                        if (mStaIfaceAvailableForRequestListener != null) {
+                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
+                                    IfaceType.STA, mStaIfaceAvailableForRequestListener,
+                                    mHalEventHandler);
+                        }
+                        if (mApIfaceAvailableForRequestListener != null) {
+                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
+                                    IfaceType.AP, mApIfaceAvailableForRequestListener,
+                                    mHalEventHandler);
+                        }
+                    }
+                }
+            });
         }
     }
 }
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java b/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
index b715466..0a2e84b 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
@@ -235,7 +235,7 @@
                 boolean hasPermission = mWifiPermissionsUtil.checkCallersLocationPermission(
                         mCallingPackage, mCallingFeatureId, mUid,
                         /* coarseForTargetSdkLessThanQ */ true, null);
-                if (VDBG) Log.v(TAG, "hasPermission=" + hasPermission);
+                if (mDbg) Log.v(TAG, "hasPermission=" + hasPermission);
                 mCallback.onIdentityChanged(hasPermission ? mac : ALL_ZERO_MAC);
             } catch (RemoteException e) {
                 Log.w(TAG, "onIdentityChanged: RemoteException - ignored: " + e);
@@ -271,7 +271,7 @@
                 boolean hasPermission = mWifiPermissionsUtil.checkCallersLocationPermission(
                         mCallingPackage, mCallingFeatureId, mUid,
                         /* coarseForTargetSdkLessThanQ */ true, null);
-                if (VDBG) Log.v(TAG, "hasPermission=" + hasPermission);
+                if (mDbg) Log.v(TAG, "hasPermission=" + hasPermission);
                 mCallback.onIdentityChanged(
                         hasPermission ? currentDiscoveryInterfaceMac : ALL_ZERO_MAC);
             } catch (RemoteException e) {
@@ -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..c3693a9 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -150,7 +150,7 @@
     public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
             WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
             NetdWrapper netdWrapper) {
-        if (VDBG) Log.v(TAG, "start");
+        if (mDbg) Log.v(TAG, "start");
 
         mContext = context;
         mAwareMetrics = awareMetrics;
@@ -187,10 +187,10 @@
 
     private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
                 getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) {
-        if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci);
+        if (mDbg) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci);
         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
                 mNetworkRequestsCache.entrySet()) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue()
                         + " --> cci=" + entry.getValue().getCanonicalDescriptor());
             }
@@ -396,7 +396,7 @@
         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                 getNetworkRequestByNdpId(ndpId);
         if (nnriE != null) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG,
                         "onDataPathRequest: initiator-side indication for " + nnriE.getValue());
             }
@@ -423,7 +423,7 @@
         if (nnri == null) {
             Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
                     + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
             }
             mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false);
@@ -481,7 +481,7 @@
         if (nnri == null) {
             Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
                     + ndpId);
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onRespondToDataPathRequest: network request cache = "
                         + mNetworkRequestsCache);
             }
@@ -580,7 +580,7 @@
                     return networkSpecifier;
                 }
             } else {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "onDataPathConfirm: interface already configured: "
                             + nnri.interfaceName);
                 }
@@ -607,7 +607,7 @@
             nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis();
             handleAddressValidation(nnri, ndpId, networkSpecifier.isOutOfBand(), mac);
         } else {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
                         + " rejected - reason=" + reason);
             }
@@ -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;
         }
@@ -715,7 +716,7 @@
         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                 getNetworkRequestByNdpId(ndpId);
         if (nnriE == null) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
             }
             return;
@@ -811,7 +812,7 @@
 
         public void tickleConnectivityIfWaiting() {
             if (mWaitingForTermination) {
-                if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!");
+                if (mDbg) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!");
                 mWaitingForTermination = false;
                 reevaluateAllRequests();
             }
@@ -819,13 +820,13 @@
 
         @Override
         public boolean acceptRequest(NetworkRequest request, int score) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score="
                         + score);
             }
 
             if (!mMgr.isUsageEnabled()) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                             + " -- Aware disabled");
                 }
@@ -851,7 +852,7 @@
             // look up specifier - are we being called again?
             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
             if (nnri != null) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                             + " - already in cache with state=" + nnri.state);
                 }
@@ -880,7 +881,7 @@
             Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest =
                     getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor());
             if (primaryRequest != null) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                             + ", already has a primary request=" + primaryRequest.getKey()
                             + " with state=" + primaryRequest.getValue().state);
@@ -920,7 +921,7 @@
             }
 
             if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
                             + networkRequest + " - already in progress");
                     // TODO: understand how/when can be called again/while in progress (seems
@@ -973,7 +974,7 @@
             }
 
             if (nnri.networkAgent != null) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
                             + networkRequest + ", nnri=" + nnri
                             + ": agent already created - deferring ending data-path to agent"
@@ -994,7 +995,7 @@
                             + networkRequest);
                 }
                 if (nnri.ndpId != 0) { // 0 is never a valid ID!
-                    if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated");
+                    if (mDbg) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated");
                     mMgr.endDataPath(nnri.ndpId);
                     nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
                 } else {
@@ -1004,7 +1005,7 @@
                     }
                 }
             } else {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating "
                             + "networkRequest=" + networkRequest);
                 }
@@ -1057,7 +1058,7 @@
     }
 
     private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) {
-        if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri);
+        if (mDbg) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri);
 
         if (!TextUtils.isEmpty(nnri.interfaceName)) {
             boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
@@ -1126,7 +1127,7 @@
             }
         }
 
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "selectInterfaceForRequest: potential=" + potential + ", used=" + used);
         }
 
@@ -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..f4b32df 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
@@ -174,18 +174,18 @@
         final PrintWriter pw = parentShell.getErrPrintWriter();
 
         String subCmd = parentShell.getNextArgRequired();
-        if (VDBG) Log.v(TAG, "onCommand: subCmd='" + subCmd + "'");
+        if (mDbg) Log.v(TAG, "onCommand: subCmd='" + subCmd + "'");
         switch (subCmd) {
             case "set": {
                 String name = parentShell.getNextArgRequired();
-                if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'");
+                if (mDbg) Log.v(TAG, "onCommand: name='" + name + "'");
                 if (!mSettableParameters.containsKey(name)) {
                     pw.println("Unknown parameter name -- '" + name + "'");
                     return -1;
                 }
 
                 String valueStr = parentShell.getNextArgRequired();
-                if (VDBG) Log.v(TAG, "onCommand: valueStr='" + valueStr + "'");
+                if (mDbg) Log.v(TAG, "onCommand: valueStr='" + valueStr + "'");
                 int value;
                 try {
                     value = Integer.valueOf(valueStr);
@@ -201,7 +201,7 @@
                 String name = parentShell.getNextArgRequired();
                 String valueStr = parentShell.getNextArgRequired();
 
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'" + ", value='"
                             + valueStr + "'");
                 }
@@ -227,7 +227,7 @@
             }
             case "get": {
                 String name = parentShell.getNextArgRequired();
-                if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'");
+                if (mDbg) Log.v(TAG, "onCommand: name='" + name + "'");
                 if (!mSettableParameters.containsKey(name)) {
                     pw.println("Unknown parameter name -- '" + name + "'");
                     return -1;
@@ -239,7 +239,7 @@
             case "get-power": {
                 String mode = parentShell.getNextArgRequired();
                 String name = parentShell.getNextArgRequired();
-                if (VDBG) Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'");
+                if (mDbg) Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'");
                 if (!mSettablePowerParameters.containsKey(mode)) {
                     pw.println("Unknown mode -- '" + mode + "'");
                     return -1;
@@ -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/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 73e2d04..48e6b6d 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -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;
@@ -502,7 +503,7 @@
     public void requestMacAddresses(int uid, List<Integer> peerIds,
             IWifiAwareMacAddressProvider callback) {
         mSm.getHandler().post(() -> {
-            if (VDBG) Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds=" + peerIds);
+            if (mDbg) Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds=" + peerIds);
             Map<Integer, byte[]> peerIdToMacMap = new HashMap<>();
             for (int i = 0; i < mClients.size(); ++i) {
                 WifiAwareClientState client = mClients.valueAt(i);
@@ -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);
     }
@@ -1237,7 +1238,7 @@
         private class DefaultState extends State {
             @Override
             public boolean processMessage(Message msg) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, getName() + msg.toString());
                 }
 
@@ -1274,7 +1275,7 @@
         private class WaitState extends State {
             @Override
             public boolean processMessage(Message msg) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, getName() + msg.toString());
                 }
 
@@ -1320,7 +1321,7 @@
 
             @Override
             public boolean processMessage(Message msg) {
-                if (VDBG) {
+                if (mDbg) {
                     Log.v(TAG, getName() + msg.toString());
                 }
 
@@ -1364,7 +1365,7 @@
         }
 
         private void processNotification(Message msg) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "processNotification: msg=" + msg);
             }
 
@@ -1432,7 +1433,7 @@
                 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: {
                     short transactionId = (short) msg.arg2;
                     Message queuedSendCommand = mFwQueuedSendMessages.get(transactionId);
-                    if (VDBG) {
+                    if (mDbg) {
                         Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: queuedSendCommand="
                                 + queuedSendCommand);
                     }
@@ -1455,7 +1456,7 @@
                     short transactionId = (short) msg.arg2;
                     int reason = (Integer) msg.obj;
                     Message sentMessage = mFwQueuedSendMessages.get(transactionId);
-                    if (VDBG) {
+                    if (mDbg) {
                         Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: sentMessage="
                                 + sentMessage);
                     }
@@ -1548,7 +1549,7 @@
          * disconnected/terminate commands failure is not possible.
          */
         private boolean processCommand(Message msg) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "processCommand: msg=" + 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,14 +1636,15 @@
                 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);
                     break;
                 }
                 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: {
-                    if (VDBG) {
+                    if (mDbg) {
                         Log.v(TAG, "processCommand: ENQUEUE_SEND_MESSAGE - messageId="
                                 + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID)
                                 + ", mSendArrivalSequenceCounter=" + mSendArrivalSequenceCounter);
@@ -1674,13 +1676,13 @@
                 }
                 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: {
                     if (mSendQueueBlocked || mHostQueuedSendMessages.size() == 0) {
-                        if (VDBG) {
+                        if (mDbg) {
                             Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - blocked or "
                                     + "empty host queue");
                         }
                         waitForResponse = false;
                     } else {
-                        if (VDBG) {
+                        if (mDbg) {
                             Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - "
                                     + "sendArrivalSequenceCounter="
                                     + mHostQueuedSendMessages.keyAt(0));
@@ -1714,7 +1716,7 @@
                         waitForResponse = mWifiAwareNativeApi.getCapabilities(
                                 mCurrentTransactionId);
                     } else {
-                        if (VDBG) {
+                        if (mDbg) {
                             Log.v(TAG, "COMMAND_TYPE_GET_CAPABILITIES: already have capabilities - "
                                     + "skipping");
                         }
@@ -1815,7 +1817,7 @@
         }
 
         private void processResponse(Message msg) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "processResponse: msg=" + msg);
             }
 
@@ -1860,7 +1862,7 @@
                         transmitNextMessage();
                     }
 
-                    if (VDBG) {
+                    if (mDbg) {
                         Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_SUCCESS - arrivalSeq="
                                 + sentMessage.getData().getInt(
                                 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ));
@@ -1868,7 +1870,7 @@
                     break;
                 }
                 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL: {
-                    if (VDBG) {
+                    if (mDbg) {
                         Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - blocking!");
                     }
                     int reason = (Integer) msg.obj;
@@ -1880,7 +1882,7 @@
                         mHostQueuedSendMessages.put(arrivalSeq, sentMessage);
                         mSendQueueBlocked = true;
 
-                        if (VDBG) {
+                        if (mDbg) {
                             Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - arrivalSeq="
                                     + arrivalSeq + " -- blocking");
                         }
@@ -2056,7 +2058,7 @@
         }
 
         private void updateSendMessageTimeout() {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "updateSendMessageTimeout: mHostQueuedSendMessages.size()="
                         + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()="
                         + mFwQueuedSendMessages.size() + ", mSendQueueBlocked="
@@ -2164,7 +2166,7 @@
     }
 
     private void sendAwareStateChangedBroadcast(boolean enabled) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "sendAwareStateChangedBroadcast: enabled=" + enabled);
         }
         final Intent intent = new Intent(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
@@ -2180,7 +2182,7 @@
             String callingPackage, @Nullable String callingFeatureId,
             IWifiAwareEventCallback callback, ConfigRequest configRequest,
             boolean notifyIdentityChange) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "connectLocal(): transactionId=" + transactionId + ", clientId=" + clientId
                     + ", uid=" + uid + ", pid=" + pid + ", callingPackage=" + callingPackage
                     + ", callback=" + callback + ", configRequest=" + configRequest
@@ -2202,7 +2204,7 @@
             Log.e(TAG, "connectLocal: entry already exists for clientId=" + clientId);
         }
 
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "mCurrentAwareConfiguration=" + mCurrentAwareConfiguration
                     + ", mCurrentIdentityNotification=" + mCurrentIdentityNotification);
         }
@@ -2218,7 +2220,7 @@
                 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e);
             }
             return false;
-        } else if (VDBG) {
+        } else if (mDbg) {
             Log.v(TAG, "connectLocal: merged=" + merged);
         }
 
@@ -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);
@@ -2261,7 +2264,7 @@
     }
 
     private boolean disconnectLocal(short transactionId, int clientId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "disconnectLocal(): transactionId=" + transactionId + ", clientId=" + clientId);
         }
@@ -2292,17 +2295,20 @@
             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) {
-        if (VDBG) Log.v(TAG, "reconfigureLocal(): transactionId=" + transactionId);
+        if (mDbg) Log.v(TAG, "reconfigureLocal(): transactionId=" + transactionId);
 
         if (mClients.size() == 0) {
             // no clients - Aware is not enabled, nothing to reconfigure
@@ -2310,14 +2316,15 @@
         }
 
         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) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "terminateSessionLocal(): clientId=" + clientId + ", sessionId=" + 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());
@@ -2337,7 +2348,7 @@
 
     private boolean publishLocal(short transactionId, int clientId, PublishConfig publishConfig,
             IWifiAwareDiscoverySessionCallback callback) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "publishLocal(): transactionId=" + transactionId + ", clientId=" + clientId
                     + ", publishConfig=" + publishConfig + ", callback=" + callback);
         }
@@ -2364,7 +2375,7 @@
 
     private boolean updatePublishLocal(short transactionId, int clientId, int sessionId,
             PublishConfig publishConfig) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "updatePublishLocal(): transactionId=" + transactionId + ", clientId="
                     + clientId + ", sessionId=" + sessionId + ", publishConfig=" + publishConfig);
         }
@@ -2392,7 +2403,7 @@
 
     private boolean subscribeLocal(short transactionId, int clientId,
             SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "subscribeLocal(): transactionId=" + transactionId + ", clientId=" + clientId
                     + ", subscribeConfig=" + subscribeConfig + ", callback=" + callback);
         }
@@ -2419,7 +2430,7 @@
 
     private boolean updateSubscribeLocal(short transactionId, int clientId, int sessionId,
             SubscribeConfig subscribeConfig) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "updateSubscribeLocal(): transactionId=" + transactionId + ", clientId="
                             + clientId + ", sessionId=" + sessionId + ", subscribeConfig="
@@ -2449,7 +2460,7 @@
 
     private boolean sendFollowonMessageLocal(short transactionId, int clientId, int sessionId,
             int peerId, byte[] message, int messageId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "sendFollowonMessageLocal(): transactionId=" + transactionId + ", clientId="
                             + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId
@@ -2473,7 +2484,7 @@
     }
 
     private void enableUsageLocal() {
-        if (VDBG) Log.v(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled);
+        if (mDbg) Log.v(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled);
 
         if (mCapabilities == null) {
             getAwareInterface();
@@ -2491,7 +2502,7 @@
     }
 
     private boolean disableUsageLocal(short transactionId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "disableUsageLocal: transactionId=" + transactionId + ", mUsageEnabled="
                     + mUsageEnabled);
         }
@@ -2516,7 +2527,7 @@
             WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType,
             int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase,
             boolean isOutOfBand, byte[] appInfo) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "initiateDataPathSetupLocal(): transactionId=" + transactionId
                     + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId
                     + ", channelRequestType=" + channelRequestType + ", channel=" + channel
@@ -2540,7 +2551,7 @@
     private boolean respondToDataPathRequestLocal(short transactionId, boolean accept,
             int ndpId, String interfaceName, byte[] pmk, String passphrase, byte[] appInfo,
             boolean isOutOfBand) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "respondToDataPathRequestLocal(): transactionId=" + transactionId + ", accept="
                             + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName
@@ -2558,7 +2569,7 @@
     }
 
     private boolean endDataPathLocal(short transactionId, int ndpId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "endDataPathLocal: transactionId=" + transactionId + ", ndpId=" + ndpId);
         }
@@ -2571,7 +2582,7 @@
      */
 
     private void onConfigCompletedLocal(Message completedCommand) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onConfigCompleted: completedCommand=" + completedCommand);
         }
 
@@ -2624,10 +2635,11 @@
             Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?");
         }
         mCurrentIdentityNotification = doesAnyClientNeedIdentityChangeNotifications();
+        mCurrentRangingEnabled = doesAnyClientNeedRanging();
     }
 
     private void onConfigFailedLocal(Message failedCommand, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "onConfigFailedLocal: failedCommand=" + failedCommand + ", reason=" + reason);
         }
@@ -2661,7 +2673,7 @@
     }
 
     private void onDisableResponseLocal(Message command, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onDisableResponseLocal: command=" + command + ", reason=" + reason);
         }
 
@@ -2680,11 +2692,31 @@
 
     private void onSessionConfigSuccessLocal(Message completedCommand, byte pubSubId,
             boolean isPublish) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onSessionConfigSuccessLocal: completedCommand=" + completedCommand
                     + ", 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,16 +2779,22 @@
                 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();
         }
     }
 
     private void onSessionConfigFailLocal(Message failedCommand, boolean isPublish, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onSessionConfigFailLocal: failedCommand=" + failedCommand + ", isPublish="
                     + isPublish + ", reason=" + reason);
         }
@@ -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);
@@ -2836,7 +2857,7 @@
     }
 
     private void onMessageSendSuccessLocal(Message completedCommand) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onMessageSendSuccess: completedCommand=" + completedCommand);
         }
 
@@ -2865,7 +2886,7 @@
     }
 
     private void onMessageSendFailLocal(Message failedCommand, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onMessageSendFail: failedCommand=" + failedCommand + ", reason=" + reason);
         }
 
@@ -2894,7 +2915,7 @@
     }
 
     private void onCapabilitiesUpdatedResponseLocal(Capabilities capabilities) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onCapabilitiesUpdatedResponseLocal: capabilites=" + capabilities);
         }
 
@@ -2904,13 +2925,13 @@
 
     private void onCreateDataPathInterfaceResponseLocal(Message command, boolean success,
             int reasonOnFailure) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: command=" + command + ", success="
                     + success + ", reasonOnFailure=" + reasonOnFailure);
         }
 
         if (success) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: successfully created interface "
                         + command.obj);
             }
@@ -2925,13 +2946,13 @@
 
     private void onDeleteDataPathInterfaceResponseLocal(Message command, boolean success,
             int reasonOnFailure) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: command=" + command + ", success="
                     + success + ", reasonOnFailure=" + reasonOnFailure);
         }
 
         if (success) {
-            if (VDBG) {
+            if (mDbg) {
                 Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: successfully deleted interface "
                         + command.obj);
             }
@@ -2945,7 +2966,7 @@
     }
 
     private void onInitiateDataPathResponseSuccessLocal(Message command, int ndpId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onInitiateDataPathResponseSuccessLocal: command=" + command + ", ndpId="
                     + ndpId);
         }
@@ -2954,7 +2975,7 @@
     }
 
     private void onInitiateDataPathResponseFailLocal(Message command, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onInitiateDataPathResponseFailLocal: command=" + command + ", reason="
                     + reason);
         }
@@ -2964,7 +2985,7 @@
 
     private void onRespondToDataPathSetupRequestResponseLocal(Message command, boolean success,
             int reasonOnFailure) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onRespondToDataPathSetupRequestResponseLocal: command=" + command
                     + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure);
         }
@@ -2973,7 +2994,7 @@
     }
 
     private void onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onEndPathEndResponseLocal: command=" + command
                     + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure);
         }
@@ -2986,7 +3007,7 @@
      */
 
     private void onInterfaceAddressChangeLocal(byte[] mac) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onInterfaceAddressChange: mac=" + String.valueOf(HexEncoding.encode(mac)));
         }
 
@@ -3001,7 +3022,7 @@
     }
 
     private void onClusterChangeLocal(int flag, byte[] clusterId) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onClusterChange: flag=" + flag + ", clusterId="
                     + String.valueOf(HexEncoding.encode(clusterId)));
         }
@@ -3016,7 +3037,7 @@
 
     private void onMatchLocal(int pubSubId, int requestorInstanceId, byte[] peerMac,
             byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "onMatch: pubSubId=" + pubSubId + ", requestorInstanceId=" + requestorInstanceId
                             + ", peerDiscoveryMac=" + String.valueOf(HexEncoding.encode(peerMac))
@@ -3040,7 +3061,7 @@
     }
 
     private void onSessionTerminatedLocal(int pubSubId, boolean isPublish, int reason) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onSessionTerminatedLocal: pubSubId=" + pubSubId + ", isPublish=" + isPublish
                     + ", reason=" + reason);
         }
@@ -3059,13 +3080,16 @@
                     "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e);
         }
         data.first.removeSession(data.second.getSessionId());
+        if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) {
+            reconfigure();
+        }
         mAwareMetrics.recordDiscoverySessionDuration(data.second.getCreationTime(),
                 data.second.isPublishSession());
     }
 
     private void onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac,
             byte[] message) {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG,
                     "onMessageReceivedLocal: pubSubId=" + pubSubId + ", requestorInstanceId="
                             + requestorInstanceId + ", peerDiscoveryMac="
@@ -3083,7 +3107,7 @@
     }
 
     private void onAwareDownLocal() {
-        if (VDBG) {
+        if (mDbg) {
             Log.v(TAG, "onAwareDown: mCurrentAwareConfiguration=" + mCurrentAwareConfiguration);
         }
         if (mCurrentAwareConfiguration == null) {
@@ -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/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
index 752cebf..fdb7892 100644
--- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
+++ b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
@@ -10,6 +10,8 @@
 import com.android.server.wifi.hotspot2.anqp.Constants;
 import com.android.server.wifi.hotspot2.anqp.RawByteElement;
 import com.android.server.wifi.util.InformationElementUtil;
+import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.WifiGbk;
 
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
@@ -264,6 +266,13 @@
             }
 
             if (ssid == null) {
+                // wifigbk++
+                String ssid2 = WifiGbk.encodeSsid(ssidOctets, "GBK");
+                if (ssid2 != null) {
+                    ssid = NativeUtil.removeEnclosingQuotes(ssid2);
+                }
+                else
+                // wifigbk--
                 if (extendedCapabilities.isStrictUtf8() && exception != null) {
                     throw new IllegalArgumentException("Failed to decode SSID in dubious IE string");
                 }
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java
index b956983..4f2499c 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java
@@ -22,6 +22,7 @@
 import com.android.server.wifi.WifiConfigStore;
 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
 import com.android.server.wifi.util.XmlUtil;
+import static android.net.wifi.WifiManager.STA_SECONDARY;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -119,6 +120,13 @@
         // Shared general store.
         return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
     }
+    @Override
+    public @WifiConfigStore.StoreFileId int getStoreFileId(int staId) {
+        // Shared general store.
+        if (staId == STA_SECONDARY)
+                return WifiConfigStore.QTI_STORE_FILE_SHARED_SECONDARY;
+        return WifiConfigStore.STORE_FILE_SHARED_GENERAL;
+    }
 
     /**
      * Serialize share data (system wide Passpoint configurations) to a XML block.
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index b77a021..cd4321f 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -18,6 +18,7 @@
 
 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;
 
@@ -25,6 +26,7 @@
 import android.app.ActivityManager;
 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;
@@ -41,6 +43,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;
@@ -120,6 +123,7 @@
     private final PasspointProvisioner mPasspointProvisioner;
     private final AppOpsManager mAppOps;
     private final WifiCarrierInfoManager mWifiCarrierInfoManager;
+    private final MacAddressUtil mMacAddressUtil;
     private final WifiPermissionsUtil mWifiPermissionsUtil;
     private final boolean mIsLowMemory;
     /**
@@ -308,6 +312,7 @@
             WifiConfigStore wifiConfigStore,
             WifiMetrics wifiMetrics,
             WifiCarrierInfoManager wifiCarrierInfoManager,
+            MacAddressUtil macAddressUtil,
             WifiPermissionsUtil wifiPermissionsUtil) {
         mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative,
                 new CallbackHandler(context));
@@ -332,6 +337,7 @@
         mIsLowMemory = activityManager.isLowRamDevice();
         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         sPasspointManager = this;
+        mMacAddressUtil = macAddressUtil;
         mWifiPermissionsUtil = wifiPermissionsUtil;
     }
 
@@ -1127,6 +1133,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/SupplicantP2pIfaceCallback.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java
index ea74678..b0a78ee 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallback.java
@@ -17,6 +17,7 @@
 package com.android.server.wifi.p2p;
 
 import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorP2PIfaceCallback;
 import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
 import android.net.wifi.WpsInfo;
 import android.net.wifi.p2p.WifiP2pConfig;
@@ -569,3 +570,97 @@
     }
 }
 
+class SupplicantVendorP2pIfaceCallback extends ISupplicantVendorP2PIfaceCallback.Stub {
+    private static final String TAG = "SupplicantVendorP2pIfaceCallback ";
+    private static final boolean DBG = true;
+
+    private final String mInterface;
+    private final WifiP2pMonitor mMonitor;
+
+    public SupplicantVendorP2pIfaceCallback(String iface, WifiP2pMonitor monitor) {
+        mInterface = iface;
+        mMonitor = monitor;
+    }
+
+
+    protected static void logd(String s) {
+        if (DBG) Log.d(TAG, s);
+    }
+
+    /**
+     * Used to indicate that a P2P device- with WFDR2 has been found.
+     *
+     * @param srcAddress MAC address of the device found. This must either
+     *        be the P2P device address or the P2P interface address.
+     * @param p2pDeviceAddress P2P device address.
+     * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+     *        Technical specification v1.2.
+     * @param deviceName Name of the device.
+     * @param configMethods Mask of WPS configuration methods supported by the
+     *        device.
+     * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+     *        technical specification v1.0.0.
+     * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12
+     *        of WFD technical specification v2.0.0
+     */
+    @Override
+    public void onR2DeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType,
+            String deviceName, short configMethods, byte deviceCapabilities, int groupCapabilities,
+            byte[] wfdDeviceInfo, byte[] wfdR2DeviceInfo) {
+        WifiP2pDevice device = new WifiP2pDevice();
+        device.deviceName = deviceName;
+
+        if (deviceName == null) {
+            Log.e(TAG, "Missing device name.");
+            return;
+        }
+
+        try {
+            device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
+        } catch (Exception e) {
+            Log.e(TAG, "Could not decode device address.", e);
+            return;
+        }
+
+        try {
+            device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType);
+        } catch (Exception e) {
+            Log.e(TAG, "Could not encode device primary type.", e);
+            return;
+        }
+
+        device.deviceCapability = deviceCapabilities;
+        device.groupCapability = groupCapabilities;
+        device.wpsConfigMethodsSupported = configMethods;
+        device.status = WifiP2pDevice.AVAILABLE;
+
+        if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) {
+            device.wfdInfo = new WifiP2pWfdInfo(
+                    (wfdDeviceInfo[0] << 8) + wfdDeviceInfo[1],
+                    (wfdDeviceInfo[2] << 8) + wfdDeviceInfo[3],
+                    (wfdDeviceInfo[4] << 8) + wfdDeviceInfo[5]);
+        }
+        if (wfdR2DeviceInfo != null && wfdR2DeviceInfo.length >= 2) {
+            device.wfdInfo.setWfdR2Device(
+                    (wfdR2DeviceInfo[0] << 8) + wfdR2DeviceInfo[1]);
+        }
+        logd("R2 Device discovered on " + mInterface + ": " + device + "R2 Info:" + wfdR2DeviceInfo);
+        mMonitor.broadcastP2pDeviceFound(mInterface, device);
+    }
+
+    /**
+     * Used to indicate that a P2P device with some addition IEs has been found.
+     *
+     * @param info Vendor Extension Info as described in Section 12 of WSC
+     *        specification version 2.0.4
+     * @param type Vendor Extension Attribute for identification
+     *
+     */
+    @Override
+    public void onVendorExtensionFound(ArrayList<Byte> info, byte type) {
+    }
+}
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
index 2d08861..2dad0c0 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
@@ -18,6 +18,10 @@
 
 import android.annotation.NonNull;
 import android.hardware.wifi.supplicant.V1_0.ISupplicant;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendor;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorIface;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorP2PIface;
+import vendor.qti.hardware.wifi.supplicant.V2_0.ISupplicantVendorP2PIfaceCallback;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIface;
@@ -63,7 +67,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.
@@ -77,8 +80,10 @@
     // Supplicant HAL HIDL interface objects
     private IServiceManager mIServiceManager = null;
     private ISupplicant mISupplicant = null;
+    private ISupplicantVendor mISupplicantVendor; // Supplicant Vendor HAL interface objects
     private ISupplicantIface mHidlSupplicantIface = null;
     private ISupplicantP2pIface mISupplicantP2pIface = null;
+    private ISupplicantVendorP2PIface mISupplicantVendorP2pIface = null;
     private final IServiceNotification mServiceNotificationCallback =
             new IServiceNotification.Stub() {
         public void onRegistration(String fqName, String name, boolean preexisting) {
@@ -112,8 +117,17 @@
                 }
             };
 
+    private final DeathRecipient mSupplicantVendorDeathRecipient =
+            cookie -> {
+                synchronized (mLock) {
+                    Log.w(TAG, "ISupplicantVendor/ISupplicantVendorP2PIface died: cookie=" + cookie);
+                    supplicantVendorServiceDiedHandler();
+                }
+            };
+
     private final WifiP2pMonitor mMonitor;
     private SupplicantP2pIfaceCallback mCallback = null;
+    private SupplicantVendorP2pIfaceCallback mVendorCallback = null;
 
     public SupplicantP2pIfaceHal(WifiP2pMonitor monitor) {
         mMonitor = monitor;
@@ -158,7 +172,9 @@
                 return true;
             }
             mISupplicant = null;
+            mISupplicantVendor = null;
             mISupplicantP2pIface = null;
+            mISupplicantVendorP2pIface = null;
             try {
                 mIServiceManager = getServiceManagerMockable();
                 if (mIServiceManager == null) {
@@ -171,7 +187,7 @@
                 /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
                    exists */
                 if (!mIServiceManager.registerForNotifications(
-                        ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) {
+                        ISupplicant.kInterfaceName, "default", mServiceNotificationCallback)) {
                     Log.e(TAG, "Failed to register for notifications to "
                             + ISupplicant.kInterfaceName);
                     mIServiceManager = null; // Will need to register a new ServiceNotification
@@ -205,6 +221,23 @@
         return true;
     }
 
+    private boolean linkToSupplicantVendorDeath() {
+        synchronized (mLock) {
+            if (mISupplicantVendor == null) return false;
+            try {
+                if (!mISupplicantVendor.linkToDeath(mSupplicantVendorDeathRecipient, 0)) {
+                    Log.wtf(TAG, "Error on linkToDeath on ISupplicantVendor");
+                    supplicantVendorServiceDiedHandler();
+                    return false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.linkToDeath exception", e);
+                return false;
+            }
+            return true;
+        }
+    }
+
     private boolean initSupplicantService() {
         synchronized (mLock) {
             try {
@@ -221,6 +254,32 @@
                 return false;
             }
         }
+        if (!initSupplicantVendorService())
+            Log.e(TAG, "Failed to init SupplicantVendor service");
+        return true;
+    }
+
+    private boolean initSupplicantVendorService() {
+        synchronized (mLock) {
+            try {
+                // Discovering supplicantvendor service
+                mISupplicantVendor = getSupplicantVendorMockable();
+                if (mISupplicantVendor != null) {
+                   Log.e(TAG, "Discover ISupplicantVendor service successfull");
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.getService exception: " + e);
+                return false;
+            }
+            if (mISupplicantVendor == null) {
+                Log.e(TAG, "Got null ISupplicantVendor service. Stopping supplicantVendor HIDL startup");
+                return false;
+            }
+            // check mISupplicantVendor service and trigger death service
+            if (!linkToSupplicantVendorDeath()) {
+                return false;
+            }
+        }
         return true;
     }
 
@@ -239,6 +298,23 @@
         return true;
     }
 
+    private boolean linkToSupplicantVendorP2pIfaceDeath(ISupplicantVendorP2PIface iface) {
+        synchronized (mLock) {
+            if (iface == null) return false;
+            try {
+                if (!iface.linkToDeath(mSupplicantVendorDeathRecipient, 0)) {
+                    Log.wtf(TAG, "Error on linkToDeath on ISupplicantVendorP2PIface");
+                    supplicantVendorServiceDiedHandler();
+                    return false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendorP2PIface.linkToDeath exception", e);
+                return false;
+            }
+            return true;
+        }
+    }
+
     /**
      * Setup the P2p iface.
      *
@@ -269,10 +345,116 @@
                     return false;
                 }
             }
+            /** creation vendor p2p iface binder */
+            if (!vendor_setupIface(ifaceName))
+                Log.e(TAG, "Failed to create vendor setupiface");
+
             return true;
         }
     }
 
+    /**
+     * Setup a Vendor P2P interface for the specified iface name.
+     *
+     * @param ifaceName Name of the interface.
+     * @return true on success, false otherwise.
+     */
+    public boolean vendor_setupIface(@NonNull String ifaceName) {
+        final String methodStr = "vendor_setupIface";
+        if (checkSupplicantVendorP2pIfaceAndLogFailure(methodStr)) {
+            Log.e(TAG, "Already created vendor setupinterface");
+            return true;
+        }
+        ISupplicantVendorIface Vendor_ifaceHwBinder = null;
+
+        if (isVendor_2_0()) {
+            Log.e(TAG, "Try to get Vendor HIDL@2.0 interface");
+            Vendor_ifaceHwBinder = getVendorIfaceV2_0(ifaceName);
+        }
+        if (Vendor_ifaceHwBinder == null) {
+            Log.e(TAG, "Failed to get vendor iface binder");
+            return false;
+        }
+
+        mISupplicantVendorP2pIface = getVendorP2pIfaceMockable(Vendor_ifaceHwBinder);
+        if (mISupplicantVendorP2pIface == null) {
+            Log.e(TAG, "Failed to get ISupplicantVendorP2PIface proxy");
+            return false;
+        }
+        else
+            Log.e(TAG, "Successful get Vendor p2p interface");
+
+        if (!linkToSupplicantVendorP2pIfaceDeath(mISupplicantVendorP2pIface )) {
+            return false;
+        }
+
+        if (mISupplicantVendorP2pIface != null && mMonitor != null) {
+            mVendorCallback = new SupplicantVendorP2pIfaceCallback(ifaceName, mMonitor);
+            if (!registerVendorCallback(mVendorCallback)) {
+                Log.e(TAG, "Callback registration failed. Initialization incomplete.");
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Get a Vendor P2P interface for the specified iface name.
+     *
+     * @param ifaceName Name of the interface.
+     * @return true on success, false otherwise.
+     */
+    private ISupplicantVendorIface getVendorIfaceV2_0(@NonNull String ifaceName) {
+        synchronized (mLock) {
+            /** List all supplicant Ifaces */
+            final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
+            try {
+                final String methodStr = "listVendorInterfaces";
+                if (!checkSupplicantVendorAndLogFailure(methodStr)) return null;
+                mISupplicantVendor.listVendorInterfaces((SupplicantStatus status,
+                                             ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
+                    if (!checkSupplicantVendorStatusAndLogFailure(status, methodStr)) {
+                        return;
+                    }
+                    supplicantIfaces.addAll(ifaces);
+                });
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.listInterfaces exception: " + e);
+                supplicantVendorServiceDiedHandler();
+                return null;
+            }
+            if (supplicantIfaces.size() == 0) {
+                Log.e(TAG, "Got zero HIDL supplicant vendor ifaces. Stopping supplicant vendor HIDL startup.");
+                return null;
+            }
+            SupplicantResult<ISupplicantVendorIface> supplicantVendorIface = new SupplicantResult<>("getVendorInterface");
+            for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
+                if (ifaceInfo.type == IfaceType.P2P && ifaceName.equals(ifaceInfo.name)) {
+                    try {
+                        final String methodStr = "getVendorInterface";
+                        if (!checkSupplicantVendorAndLogFailure(methodStr)) return null;
+                        mISupplicantVendor.getVendorInterface(ifaceInfo,
+                                (SupplicantStatus status, ISupplicantVendorIface iface) -> {
+                                    if (!checkSupplicantVendorStatusAndLogFailure(status, methodStr)) {
+                                        return;
+                                    }
+                                    // supplicantVendorIface.value = iface;
+                                    supplicantVendorIface.setResult(status, iface);
+                                });
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "ISupplicantVendor.getInterface exception: " + e);
+                        supplicantVendorServiceDiedHandler();
+                        return null;
+                    }
+                    break;
+                }
+            }
+            // return supplicantVendorIface.value;
+            return supplicantVendorIface.getResult();
+        }
+    }
+
     private ISupplicantIface getIfaceV1_0(@NonNull String ifaceName) {
         /** List all supplicant Ifaces */
         final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList();
@@ -307,7 +489,7 @@
                                 }
                                 supplicantIface.setResult(status, iface);
                             });
-                } catch (RemoteException e) {
+                } catch (RemoteException | IllegalArgumentException e) {
                     Log.e(TAG, "ISupplicant.getInterface exception: " + e);
                     supplicantServiceDiedHandler();
                     return null;
@@ -361,8 +543,16 @@
             if (mISupplicantP2pIface == null) return false;
             // Only supported for V1.1
             if (isV1_1()) {
-                return removeIfaceV1_1(ifaceName);
+                if (!removeIfaceV1_1(ifaceName)) {
+                    Log.e(TAG, "Failed to remove iface = " + ifaceName);
+                    return false;
+                }
             }
+            if (mISupplicantVendorP2pIface == null) {
+                Log.e(TAG, "Trying to teardown unknown vendor interface");
+                return false;
+            }
+            mISupplicantVendorP2pIface = null;
             return true;
         }
     }
@@ -400,10 +590,19 @@
         }
     }
 
+    private void supplicantVendorServiceDiedHandler() {
+        synchronized (mLock) {
+            mISupplicantVendor = null;
+            mISupplicantVendorP2pIface = null;
+        }
+    }
+
     private void supplicantServiceDiedHandler() {
         synchronized (mLock) {
             mISupplicant = null;
+            mISupplicantVendor = null;
             mISupplicantP2pIface = null;
+            mISupplicantVendorP2pIface = null;
         }
     }
 
@@ -441,6 +640,17 @@
         }
     }
 
+    protected ISupplicantVendor getSupplicantVendorMockable() throws RemoteException {
+        synchronized (mLock) {
+            try {
+                return ISupplicantVendor.getService();
+            } catch (NoSuchElementException e) {
+                Log.e(TAG, "Failed to get ISupplicant", e);
+                return null;
+            }
+        }
+    }
+
     protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1()
             throws RemoteException {
         synchronized (mLock) {
@@ -469,6 +679,10 @@
         return ISupplicantP2pNetwork.asInterface(network.asBinder());
     }
 
+    protected ISupplicantVendorP2PIface getVendorP2pIfaceMockable(ISupplicantVendorIface iface) {
+        return ISupplicantVendorP2PIface.asInterface(iface.asBinder());
+    }
+
     /**
      * Check if the device is running V1_1 supplicant service.
      * @return
@@ -485,6 +699,86 @@
         }
     }
 
+    /**
+     * Check if the device is running V2_0 supplicant vendor service.
+     * @return
+     */
+    private boolean isVendor_2_0() {
+        synchronized (mLock) {
+            try {
+                return (getSupplicantVendorMockable() != null);
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendor.getService exception: " + e);
+                supplicantServiceDiedHandler();
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Returns false if SupplicantVendor is null, and logs failure to call methodStr
+     */
+    private boolean checkSupplicantVendorAndLogFailure(final String methodStr) {
+        synchronized (mLock) {
+            if (mISupplicantVendor == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendor is null");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Returns false if mISupplicantVendorP2pIface is null, and logs failure to call methodStr
+     */
+    private boolean checkSupplicantVendorP2pIfaceAndLogFailure(final String methodStr) {
+        synchronized (mLock) {
+            if (mISupplicantVendorP2pIface == null) {
+                Log.e(TAG, "Can't call " + methodStr + ", ISupplicantVendorP2PIface is null");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Returns true if provided supplicant vendor status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkSupplicantVendorStatusAndLogFailure(SupplicantStatus status,
+            final String methodStr) {
+        synchronized (mLock) {
+            if (status.code != SupplicantStatusCode.SUCCESS) {
+                Log.e(TAG, "ISupplicantVendor." + methodStr + " failed: " + status);
+                return false;
+            } else {
+                if (sVerboseLoggingEnabled) {
+                    Log.d(TAG, "ISupplicantVendor." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Returns true if provided Vendor status code is SUCCESS, logs debug message and returns false
+     * otherwise
+     */
+    private boolean checkVendorStatusAndLogFailure(SupplicantStatus status,
+            final String methodStr) {
+        synchronized (mLock) {
+            if (status.code != SupplicantStatusCode.SUCCESS) {
+                Log.e(TAG, "ISupplicantVendorP2pIface." + methodStr + " failed: " + status);
+                return false;
+            } else {
+                if (sVerboseLoggingEnabled) {
+                    Log.d(TAG, "ISupplicantVendorP2PIface." + methodStr + " succeeded");
+                }
+                return true;
+            }
+        }
+    }
+
     protected static void logd(String s) {
         if (sVerboseLoggingEnabled) Log.d(TAG, s);
     }
@@ -596,6 +890,32 @@
         }
     }
 
+    /**
+     * Register for callbacks from vendor interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param receiver An instance of the |ISupplicantVendorP2pIfaceCallback| HIDL
+     *        interface object.
+     * @return boolean value indicating whether operation was successful.
+     */
+    public boolean registerVendorCallback(ISupplicantVendorP2PIfaceCallback receiver) {
+        synchronized (mLock) {
+            if (!checkSupplicantVendorP2pIfaceAndLogFailure("registerVendorCallback")) return false;
+            SupplicantResult<Void> result = new SupplicantResult("registerVendorCallback()");
+            try {
+                result.setResult(mISupplicantVendorP2pIface.registerVendorCallback(receiver));
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantVendorP2pIface exception: " + e);
+                supplicantVendorServiceDiedHandler();
+            }
+            return result.isSuccess();
+        }
+    }
+
 
     /**
      * Initiate a P2P service discovery with a (optional) timeout.
@@ -828,13 +1148,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 +1158,7 @@
             try {
                 mISupplicantP2pIface.connect(
                         peerAddress, provisionMethod, preSelectedPin, joinExistingGroup,
-                        persistent, goIntent,
+                        persistent, config.groupOwnerIntent,
                         (SupplicantStatus status, String generatedPin) -> {
                             result.setResult(status, generatedPin);
                         });
@@ -1908,6 +2224,42 @@
     }
 
     /**
+     * Set Wifi Display R2 device info.
+     *
+     * @param info WFD device info as described in section 5.1.12 of
+     *        WFD technical specification v2.0.0.
+     * @return true, if operation was successful.
+     */
+    public boolean setWfdR2DeviceInfo(String info) {
+        synchronized (mLock) {
+            if (!checkSupplicantVendorP2pIfaceAndLogFailure("setWfdR2DeviceInfo")) return false;
+
+            if (info == null) {
+                Log.e(TAG, "Cannot parse null WFD info string.");
+                return false;
+            }
+            byte[] wfdInfo = null;
+            try {
+                wfdInfo = NativeUtil.hexStringToByteArray(info);
+            } catch (Exception e) {
+                Log.e(TAG, "Could not parse WFD Device Info string.");
+                return false;
+            }
+
+            SupplicantResult<Void> result = new SupplicantResult(
+                    "setWfdDeviceInfo(" + info + ")");
+            try {
+                result.setResult(mISupplicantVendorP2pIface.setWfdR2DeviceInfo(wfdInfo));
+            } catch (RemoteException e) {
+                Log.e(TAG, "ISupplicantP2pIface exception: " + e);
+                supplicantServiceDiedHandler();
+            }
+
+            return result.isSuccess();
+        }
+    }
+
+    /**
      * Remove network with provided id.
      *
      * @param networkId Id of the network to lookup.
@@ -2037,6 +2389,9 @@
                         && !resultSsid.getResult().isEmpty()) {
                     group.setNetworkName(NativeUtil.removeEnclosingQuotes(
                             NativeUtil.encodeSsid(resultSsid.getResult())));
+                } else {
+                    Log.e(TAG, "group ssid is invalid! resultSsid = " + resultSsid);
+                    continue;
                 }
 
                 SupplicantResult<byte[]> resultBssid =
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
index 300b7a1..179c820 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
@@ -436,6 +436,17 @@
         return mSupplicantP2pIfaceHal.setWfdDeviceInfo(hex);
     }
 
+     /**
+     * Set Wifi Display device info.
+     *
+     * @param hex WFD device info as described in section 5.1.12 of
+     *        WFD technical specification v2.0.0.
+     * @return true, if operation was successful.
+     */
+    public boolean setWfdR2DeviceInfo(String hex) {
+        return mSupplicantP2pIfaceHal.setWfdR2DeviceInfo(hex);
+    }
+
     /**
      * Initiate a P2P service discovery indefinitely.
      * Will trigger {@link WifiP2pMonitor#P2P_DEVICE_FOUND_EVENT} on finding devices.
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 61e6c16..3b904e9 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;
@@ -96,6 +99,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent;
 import com.android.server.wifi.util.NetdWrapper;
 import com.android.server.wifi.util.WifiAsyncChannel;
+import com.android.server.wifi.WifiNative;
 import com.android.server.wifi.util.WifiHandler;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -114,6 +118,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 +134,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;
 
@@ -238,9 +245,16 @@
     public static final int ENABLED                         = 1;
     public static final int DISABLED                        = 0;
 
+    private static final int P2P_CONNECT_TRIGGER_GROUP_NEG_REQ      = 1;
+    private static final int P2P_CONNECT_TRIGGER_INVITATION_REQ     = 2;
+    private static final int P2P_CONNECT_TRIGGER_OTHER              = 3;
+
+    static final int P2P_BLUETOOTH_COEXISTENCE_MODE_DISABLED    = 1;
+    static final int P2P_BLUETOOTH_COEXISTENCE_MODE_SENSE       = 2;
+
     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
@@ -383,6 +397,7 @@
             switch (msg.what) {
                 case WifiP2pManager.SET_DEVICE_NAME:
                 case WifiP2pManager.SET_WFD_INFO:
+                case WifiP2pManager.SET_WFDR2_INFO:
                 case WifiP2pManager.DISCOVER_PEERS:
                 case WifiP2pManager.STOP_DISCOVERY:
                 case WifiP2pManager.CONNECT:
@@ -486,7 +501,9 @@
         mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported);
         mP2pStateMachine.start();
     }
-
+    public void enableVerboseLogging(int verbose) {
+        mVerboseLoggingEnabled = verbose > 0;
+    }
     /**
      * Obtains the service interface for Managements services
      */
@@ -700,6 +717,11 @@
     public void setMiracastMode(int mode) {
         checkConfigureWifiDisplayPermission();
         mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode);
+        if (mWifiChannel != null) {
+            mWifiChannel.sendMessage(WifiP2pServiceImpl.SET_MIRACAST_MODE, mode);
+        } else {
+            Log.e(TAG, "setMiracastMode(): WifiChannel is null");
+        }
     }
 
     @Override
@@ -771,6 +793,7 @@
 
         private WifiP2pNative mWifiNative = mWifiInjector.getWifiP2pNative();
         private WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor();
+        private WifiNative mWifNative = mWifiInjector.getWifiNative();
         private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
         private String mInterfaceName;
 
@@ -793,16 +816,52 @@
                 });
         private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
         private WifiP2pGroup mGroup;
+        private boolean mIsBTCoexDisabled = false;
         // Is the HAL (HIDL) interface available for use.
         private boolean mIsHalInterfaceAvailable = false;
         // Is wifi on or off.
         private boolean mIsWifiEnabled = false;
 
+        // p2p start failure count.
+        // Current design keeps on calling setupIface even though p2p init fails in supplicant.
+        // Break this infinite loop by maintaining a temp counter for continuous setup failures.
+        private int mSetupFailureCount = 0;
+        // Threshold for continuous setup failure.
+        private static final int P2P_SETUP_FAILURE_COUNT_THRESHOLD = 10;
+
         // Saved WifiP2pConfig for an ongoing peer connection. This will never be null.
         // The deviceAddress will be an empty string when the device is inactive
         // or if it is connected without any ongoing join request
         private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig();
 
+        private void logStateAndMessage(Message message, State state) {
+            StringBuilder b = new StringBuilder();
+
+            if (message != null) {
+                b.append("{ what=");
+                b.append(message.what);
+
+                if (message.arg1 != 0) {
+                    b.append(" arg1=");
+                    b.append(message.arg1);
+                }
+
+                if (message.arg2 != 0) {
+                    b.append(" arg2=");
+                    b.append(message.arg2);
+                }
+
+                if (message.obj != null) {
+                    b.append(" obj=");
+                    b.append(message.obj.getClass().getSimpleName());
+                }
+
+                b.append(" }");
+            }
+
+            logd(" " + state.getClass().getSimpleName() + " " + b.toString());
+        }
+
         P2pStateMachine(String name, Looper looper, boolean p2pSupported) {
             super(name, looper);
 
@@ -844,6 +903,7 @@
                             checkAndReEnableP2p();
                         } else {
                             mIsWifiEnabled = false;
+                            mSetupFailureCount = 0;
                             // Teardown P2P if it's up already.
                             sendMessage(DISABLE_P2P);
                         }
@@ -884,7 +944,11 @@
                 // Register for interface availability from HalDeviceManager
                 mWifiNative.registerInterfaceAvailableListener((boolean isAvailable) -> {
                     mIsHalInterfaceAvailable = isAvailable;
-                    checkAndSendP2pStateChangedBroadcast();
+                    if (mSetupFailureCount < P2P_SETUP_FAILURE_COUNT_THRESHOLD) {
+                        checkAndSendP2pStateChangedBroadcast();
+                    } else {
+                        Log.i(TAG, "Ignore InterfaceAvailable for continuous failures. count=" +mSetupFailureCount);
+                    }
                 }, getHandler());
 
                 mSettingsConfigStore.registerChangeListener(
@@ -1062,6 +1126,15 @@
                                     WifiP2pManager.BUSY);
                         }
                         break;
+                    case WifiP2pManager.SET_WFDR2_INFO:
+                        if (!getWfdPermission(message.sendingUid)) {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.ERROR);
+                        } else {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.BUSY);
+                        }
+                        break;
                     case WifiP2pManager.REQUEST_PEERS:
                         replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,
                                 getPeers(getCallingPkgName(message.sendingUid, message.replyTo),
@@ -1257,6 +1330,7 @@
         class P2pNotSupportedState extends State {
             @Override
             public boolean processMessage(Message message) {
+                if (mVerboseLoggingEnabled) logStateAndMessage(message, this);
                 switch (message.what) {
                     case WifiP2pManager.DISCOVER_PEERS:
                         replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
@@ -1329,6 +1403,15 @@
                                     WifiP2pManager.P2P_UNSUPPORTED);
                         }
                         break;
+                    case WifiP2pManager.SET_WFDR2_INFO:
+                        if (!getWfdPermission(message.sendingUid)) {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.ERROR);
+                        } else {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.P2P_UNSUPPORTED);
+                        }
+                        break;
                     case WifiP2pManager.START_WPS:
                         replyToMessage(message, WifiP2pManager.START_WPS_FAILED,
                                 WifiP2pManager.P2P_UNSUPPORTED);
@@ -1419,9 +1502,11 @@
                             checkAndSendP2pStateChangedBroadcast();
                         }, getHandler());
                         if (mInterfaceName == null) {
+                            mSetupFailureCount++;
                             Log.e(TAG, "Failed to setup interface for P2P");
                             break;
                         }
+                        mSetupFailureCount = 0;
                         setupInterfaceFeatures(mInterfaceName);
                         try {
                             mNetdWrapper.setInterfaceUp(mInterfaceName);
@@ -1531,6 +1616,20 @@
                         }
                         break;
                     }
+                    case WifiP2pManager.SET_WFDR2_INFO:
+                    {
+                        WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj;
+                        if (!getWfdPermission(message.sendingUid)) {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.ERROR);
+                        } else if (d != null && setWfdR2Info(d)) {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_SUCCEEDED);
+                        } else {
+                            replyToMessage(message, WifiP2pManager.SET_WFDR2_INFO_FAILED,
+                                    WifiP2pManager.ERROR);
+                        }
+                        break;
+                    }
                     case BLOCK_DISCOVERY:
                         boolean blocked = (message.arg1 == ENABLED ? true : false);
                         if (mDiscoveryBlocked == blocked) break;
@@ -1953,7 +2052,7 @@
                         WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
                         WifiP2pDevice device = provDisc.device;
                         if (device == null) {
-                            loge("Device entry is null");
+                            Log.d(TAG, "Device entry is null");
                             break;
                         }
                         mSavedPeerConfig = new WifiP2pConfig();
@@ -2226,7 +2325,7 @@
                 switch (message.what) {
                     case PEER_CONNECTION_USER_ACCEPT:
                         mWifiNative.p2pStopFind();
-                        p2pConnectWithPinDisplay(mSavedPeerConfig);
+                        p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_GROUP_NEG_REQ);
                         mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
                         sendPeersChangedBroadcast();
                         transitionTo(mGroupNegotiationState);
@@ -2239,6 +2338,8 @@
                         break;
                     case PEER_CONNECTION_USER_CONFIRM:
                         mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
+                        mSavedPeerConfig.groupOwnerIntent =
+                                selectGroupOwnerIntentIfNecessary(mSavedPeerConfig);
                         mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
                         transitionTo(mGroupNegotiationState);
                         break;
@@ -2270,7 +2371,7 @@
                         mWifiNative.p2pStopFind();
                         if (!reinvokePersistentGroup(mSavedPeerConfig)) {
                             // Do negotiation when persistence fails
-                            p2pConnectWithPinDisplay(mSavedPeerConfig);
+                            p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_INVITATION_REQ);
                         }
                         mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
                         sendPeersChangedBroadcast();
@@ -2320,7 +2421,7 @@
                         }
                         if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
                             if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig);
-                            p2pConnectWithPinDisplay(mSavedPeerConfig);
+                            p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER);
                             transitionTo(mGroupNegotiationState);
                         }
                         break;
@@ -2339,7 +2440,7 @@
                             if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig);
                             // we already have the pin
                             if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) {
-                                p2pConnectWithPinDisplay(mSavedPeerConfig);
+                                p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER);
                                 transitionTo(mGroupNegotiationState);
                             } else {
                                 mJoinExistingGroup = false;
@@ -2364,7 +2465,7 @@
                         if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) {
                             if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig);
                             mSavedPeerConfig.wps.pin = provDisc.pin;
-                            p2pConnectWithPinDisplay(mSavedPeerConfig);
+                            p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER);
                             notifyInvitationSent(provDisc.pin, device.deviceAddress);
                             transitionTo(mGroupNegotiationState);
                         }
@@ -2451,6 +2552,9 @@
 
                         mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
                         startIpClient(mGroup.getInterface(), getHandler());
+                        mWifNative.setBluetoothCoexistenceMode(
+                            mInterfaceName, P2P_BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+                        mIsBTCoexDisabled = true;
                         WifiP2pDevice groupOwner = mGroup.getOwner();
                         WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress);
                         if (peer != null) {
@@ -2519,7 +2623,7 @@
 
                             // Reinvocation has failed, try group negotiation
                             mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT;
-                            p2pConnectWithPinDisplay(mSavedPeerConfig);
+                            p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER);
                         } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) {
 
                             // Devices setting persistent_reconnect to 0 in wpa_supplicant
@@ -2527,7 +2631,7 @@
                             // "information is currently unavailable" error.
                             // So, try another way to connect for interoperability.
                             mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT;
-                            p2pConnectWithPinDisplay(mSavedPeerConfig);
+                            p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER);
                         } else if (status == P2pStatus.NO_COMMON_CHANNEL) {
                             transitionTo(mFrequencyConflictState);
                         } else {
@@ -2757,6 +2861,7 @@
                         break;
                     case IPC_POST_DHCP_ACTION:
                         mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
+                        enableBTCoex();
                         break;
                     case IPC_DHCP_RESULTS:
                         mDhcpResultsParcelable = (DhcpResultsParcelable) message.obj;
@@ -2788,6 +2893,11 @@
                         break;
                     case WifiP2pManager.REMOVE_GROUP:
                         if (mVerboseLoggingEnabled) logd(getName() + " remove group");
+                        /*  We need to check BTCOex state, because some times
+                         *  user can interupt connection before dhcp sucess, then
+                         *  BTcoex will be in disabled state.
+                         */
+                        enableBTCoex();
                         if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
                             transitionTo(mOngoingGroupRemovalState);
                             replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
@@ -2810,6 +2920,11 @@
                         // Treating network disconnection as group removal causes race conditions
                         // since supplicant would still maintain the group at that stage.
                         if (mVerboseLoggingEnabled) logd(getName() + " group removed");
+                        /*  We need to check BTCOex state, because if group
+                         *  is removed at GO side before dhcp sucess, then
+                         *  BTCoex will be in disabled state.
+                         */
+                        enableBTCoex();
                         handleGroupRemoved();
                         transitionTo(mInactiveState);
                         break;
@@ -3171,7 +3286,9 @@
             intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo());
             intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup));
 
-            sendBroadcastMultiplePermissions(intent);
+            Context context = mContext.createContextAsUser(UserHandle.ALL, 0);
+            context.sendBroadcastWithMultiplePermissions(
+                    intent, RECEIVER_PERMISSIONS_FOR_BROADCAST);
         }
 
         private void sendP2pPersistentGroupsChangedBroadcast() {
@@ -3229,6 +3346,7 @@
                                 sendMessage(PEER_CONNECTION_USER_CONFIRM);
                             }
                     })
+                    .setCancelable(false)
                     .create();
             dialog.setCanceledOnTouchOutside(false);
             dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
@@ -3323,7 +3441,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 +3451,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);
                     }
                 }
@@ -3522,7 +3644,7 @@
          * Start a p2p group negotiation and display pin if necessary
          * @param config for the peer
          */
-        private void p2pConnectWithPinDisplay(WifiP2pConfig config) {
+        private void p2pConnectWithPinDisplay(WifiP2pConfig config, int triggerType) {
             if (config == null) {
                 Log.e(TAG, "Illegal argument(s)");
                 return;
@@ -3532,7 +3654,16 @@
                 Log.e(TAG, "Invalid device");
                 return;
             }
-            String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner());
+
+            boolean joinExistingGroup = dev.isGroupOwner();
+            if (triggerType == P2P_CONNECT_TRIGGER_GROUP_NEG_REQ) {
+                joinExistingGroup = false;
+            } else if (triggerType == P2P_CONNECT_TRIGGER_INVITATION_REQ) {
+                joinExistingGroup = true;
+            }
+
+            config.groupOwnerIntent = selectGroupOwnerIntentIfNecessary(config);
+            String pin = mWifiNative.p2pConnect(config, joinExistingGroup);
             try {
                 Integer.parseInt(pin);
                 notifyInvitationSent(pin, config.deviceAddress);
@@ -3792,6 +3923,27 @@
             return true;
         }
 
+        private boolean setWfdR2Info(WifiP2pWfdInfo wfdInfo) {
+            boolean success;
+
+            if (!wfdInfo.isEnabled()) {
+                success = mWifiNative.setWfdEnable(false);
+            } else {
+                success =
+                    mWifiNative.setWfdEnable(true)
+                    && mWifiNative.setWfdR2DeviceInfo(wfdInfo.getR2DeviceInfoHex());
+            }
+
+            if (!success) {
+                loge("Failed to set wfd properties");
+                return false;
+            }
+
+            mThisDevice.wfdInfo = wfdInfo;
+            sendThisDeviceChangedBroadcast();
+            return true;
+        }
+
         private void initializeP2pSettings() {
             mThisDevice.deviceName = getPersistedDeviceName();
             mThisDevice.primaryDeviceType = mContext.getResources().getString(
@@ -4226,6 +4378,17 @@
             }
         }
 
+        /**
+         * Enable BTCOEXMODE after DHCP or GROUP REMOVE
+         */
+        private void enableBTCoex() {
+            if (mIsBTCoexDisabled) {
+                mWifNative.setBluetoothCoexistenceMode(
+                    mInterfaceName, P2P_BLUETOOTH_COEXISTENCE_MODE_SENSE);
+                mIsBTCoexDisabled = false;
+            }
+        }
+
         private void setPendingFactoryReset(boolean pending) {
             mSettingsConfigStore.put(WIFI_P2P_PENDING_FACTORY_RESET, pending);
         }
@@ -4308,6 +4471,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/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index 716b206..ff122e9 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -690,10 +690,13 @@
                         case WifiNative.WIFI_SCAN_RESULTS_AVAILABLE:
                         case WifiNative.WIFI_SCAN_THRESHOLD_NUM_SCANS:
                         case WifiNative.WIFI_SCAN_THRESHOLD_PERCENT:
-                            reportScanStatusForImpl(mImplIfaceName, STATUS_SUCCEEDED);
+                            reportScanStatusForImpl(mImplIfaceName, STATUS_SUCCEEDED, WifiScanner.ON_COMPLETE_SCAN_RESULTS);
                             break;
+                        case WifiNative.WIFI_SCAN_PARTIAL_RESULTS_AVAILABLE:
+                            reportScanStatusForImpl(mImplIfaceName, STATUS_SUCCEEDED, WifiScanner.ON_PARTIAL_SCAN_RESULTS);
+			    break;
                         case WifiNative.WIFI_SCAN_FAILED:
-                            reportScanStatusForImpl(mImplIfaceName, STATUS_FAILED);
+                            reportScanStatusForImpl(mImplIfaceName, STATUS_FAILED, 0);
                             break;
                         default:
                             Log.e(TAG, "Unknown scan status event: " + event);
@@ -794,7 +797,11 @@
                 }
             }
 
-            private void reportScanStatusForImpl(@NonNull String implIfaceName, int newStatus) {
+            private void reportScanStatusForImpl(@NonNull String implIfaceName, int newStatus, int isPartialScanResult) {
+                if (isPartialScanResult == WifiScanner.ON_PARTIAL_SCAN_RESULTS) {
+                    sendMessage(CMD_SCAN_RESULTS_AVAILABLE, WifiScanner.ON_PARTIAL_SCAN_RESULTS);
+                    return;
+                }
                 Integer currentStatus = mStatusPerImpl.get(implIfaceName);
                 if (currentStatus != null && currentStatus == STATUS_PENDING) {
                     mStatusPerImpl.put(implIfaceName, newStatus);
@@ -802,7 +809,7 @@
                 // Now check if all the scanner impls scan status is available.
                 int consolidatedStatus = getConsolidatedStatus();
                 if (consolidatedStatus == STATUS_SUCCEEDED) {
-                    sendMessage(CMD_SCAN_RESULTS_AVAILABLE);
+                    sendMessage(CMD_SCAN_RESULTS_AVAILABLE, WifiScanner.ON_COMPLETE_SCAN_RESULTS);
                 } else if (consolidatedStatus == STATUS_FAILED) {
                     sendMessage(CMD_SCAN_FAILED);
                 }
@@ -1012,12 +1019,17 @@
                             mWifiMetrics.incrementScanReturnEntry(
                                     WifiMetricsProto.WifiLog.SCAN_SUCCESS,
                                     mActiveScans.size());
-                            reportScanResults(latestScanResults);
-                            mActiveScans.clear();
+                            if (msg.arg1 == WifiScanner.ON_COMPLETE_SCAN_RESULTS) {
+                                reportScanResults(latestScanResults, WifiScanner.ON_COMPLETE_SCAN_RESULTS);
+                                mActiveScans.clear();
+                            } else
+                                reportScanResults(latestScanResults, WifiScanner.ON_PARTIAL_SCAN_RESULTS);
+
                         } else {
                             Log.e(TAG, "latest scan results null unexpectedly");
                         }
-                        transitionTo(mIdleState);
+                        if (msg.arg1 == WifiScanner.ON_COMPLETE_SCAN_RESULTS)
+                            transitionTo(mIdleState);
                         return HANDLED;
                     case CMD_FULL_SCAN_RESULTS:
                         reportFullScanResult((ScanResult) msg.obj, /* bucketsScanned */ msg.arg2);
@@ -1251,7 +1263,7 @@
             }
         }
 
-        void reportScanResults(@NonNull ScanData results) {
+        void reportScanResults(@NonNull ScanData results, int partialScanResultsFlag) {
             if (results != null && results.getResults() != null) {
                 if (results.getResults().length > 0) {
                     mWifiMetrics.incrementNonEmptyScanResultCount();
@@ -1267,9 +1279,9 @@
                         new WifiScanner.ParcelableScanData(resultsToDeliver);
                 logCallback("singleScanResults",  entry.clientInfo, entry.handlerId,
                         describeForLog(resultsToDeliver));
-                entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableResultsToDeliver);
+                entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, partialScanResultsFlag, parcelableResultsToDeliver);
                 // make sure the handler is removed
-                entry.reportEvent(WifiScanner.CMD_SINGLE_SCAN_COMPLETED, 0, null);
+                entry.reportEvent(WifiScanner.CMD_SINGLE_SCAN_COMPLETED, partialScanResultsFlag, null);
             }
 
             WifiScanner.ParcelableScanData parcelableAllResults =
@@ -1277,7 +1289,7 @@
             for (RequestInfo<Void> entry : mSingleScanListeners) {
                 logCallback("singleScanResults",  entry.clientInfo, entry.handlerId,
                         describeForLog(allResults));
-                entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableAllResults);
+                entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, partialScanResultsFlag, parcelableAllResults);
             }
 
             // Cache full band (with DFS or not) scan results.
diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
index 66e0cfb..6207888 100644
--- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
@@ -28,6 +28,7 @@
 
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.ScanDetail;
+import com.android.server.wifi.WifiGbk;
 import com.android.server.wifi.WifiMonitor;
 import com.android.server.wifi.WifiNative;
 import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection;
@@ -268,8 +269,9 @@
                 pollLatestScanDataForPno();
                 break;
             case WifiMonitor.SCAN_RESULTS_EVENT:
+                boolean isPartialScanResults = (msg.arg1 == WifiScanner.ON_PARTIAL_SCAN_RESULTS);
                 cancelScanTimeout();
-                pollLatestScanData();
+                pollLatestScanData(isPartialScanResults);
                 break;
             default:
                 // ignore unknown event
@@ -321,6 +323,7 @@
             int numFilteredScanResults = 0;
             for (int i = 0; i < mNativePnoScanResults.size(); ++i) {
                 ScanResult result = mNativePnoScanResults.get(i).getScanResult();
+                WifiGbk.processScanResult(result); // wifigbk++
                 long timestamp_ms = result.timestamp / 1000; // convert us -> ms
                 if (timestamp_ms > mLastPnoScanSettings.startTime) {
                     hwPnoScanResults.add(result);
@@ -355,7 +358,7 @@
         return bandScanned;
     }
 
-    private void pollLatestScanData() {
+    private void pollLatestScanData(boolean isPartial) {
         synchronized (mSettingsLock) {
             if (mLastScanSettings == null) {
                  // got a scan before we started scanning or after scan was canceled
@@ -367,6 +370,7 @@
             int numFilteredScanResults = 0;
             for (int i = 0; i < mNativeScanResults.size(); ++i) {
                 ScanResult result = mNativeScanResults.get(i).getScanResult();
+                WifiGbk.processScanResult(result); // wifigbk++
                 long timestamp_ms = result.timestamp / 1000; // convert us -> ms
                 if (timestamp_ms > mLastScanSettings.startTime) {
                     if (mLastScanSettings.singleScanFreqs.containsChannel(
@@ -393,11 +397,18 @@
                 mLatestSingleScanResult = new WifiScanner.ScanData(0, 0, 0,
                         getBandScanned(mLastScanSettings.singleScanFreqs),
                         singleScanResults.toArray(new ScanResult[singleScanResults.size()]));
-                mLastScanSettings.singleScanEventHandler
-                        .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+                if (isPartial) {
+                    mLastScanSettings.singleScanEventHandler
+                            .onScanStatus(WifiNative.WIFI_SCAN_PARTIAL_RESULTS_AVAILABLE);
+                } else {
+                    mLastScanSettings.singleScanEventHandler
+                            .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+                }
             }
-
-            mLastScanSettings = null;
+            if (!isPartial) {
+                WifiGbk.ageBssCache(); // wifigbk++
+                mLastScanSettings = null;
+            }
         }
     }
 
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 39d0df5..d303378 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});
     }
 
     /**
@@ -151,6 +152,8 @@
                 return SoftApConfiguration.BAND_5GHZ;
             case WifiConfiguration.AP_BAND_ANY:
                 return SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
+            case WifiConfiguration.AP_BAND_DUAL:
+                return SoftApConfiguration.BAND_DUAL;
             default:
                 return SoftApConfiguration.BAND_2GHZ;
         }
@@ -160,7 +163,8 @@
      * Checks if band is a valid combination of {link  SoftApConfiguration#BandType} values
      */
     public static boolean isBandValid(@BandType int band) {
-        return ((band != 0) && ((band & ~SoftApConfiguration.BAND_ANY) == 0));
+        return ((band != 0) && (((band & ~SoftApConfiguration.BAND_ANY) == 0)
+                                || (band == SoftApConfiguration.BAND_DUAL)));
     }
 
     /**
@@ -411,6 +415,9 @@
                 case WifiConfiguration.AP_BAND_5GHZ:
                     band = SoftApConfiguration.BAND_5GHZ;
                     break;
+                case WifiConfiguration.AP_BAND_DUAL:
+                    band = SoftApConfiguration.BAND_DUAL;
+                    break;
                 default:
                     // WifiConfiguration.AP_BAND_ANY means only 2GHz and 5GHz bands
                     band = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
@@ -454,6 +461,11 @@
             Log.d(TAG, "Update Softap capability, add SAE feature support");
             features |= SoftApCapability.SOFTAP_FEATURE_WPA3_SAE;
         }
+
+        if (isWpa3OweSupported(context)) {
+            Log.d(TAG, "Update Softap capability, add OWE feature support");
+            features |= SoftApCapability.SOFTAP_FEATURE_WPA3_OWE;
+        }
         SoftApCapability capability = new SoftApCapability(features);
         int hardwareSupportedMaxClient = context.getResources().getInteger(
                 R.integer.config_wifiHardwareSoftapMaxClientCount);
@@ -488,6 +500,17 @@
     }
 
     /**
+     * Helper function to get OWE support or not.
+     *
+     * @param context the caller context used to get value from resource file.
+     * @return true if supported, false otherwise.
+     */
+    public static boolean isWpa3OweSupported(@NonNull Context context) {
+        return context.getResources().getBoolean(
+                R.bool.config_vendor_wifi_softap_owe_supported);
+    }
+
+    /**
      * Helper function to get ACS support or not.
      *
      * @param context the caller context used to get value from resource file.
diff --git a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java b/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java
index 225e68a..846753c 100644
--- a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java
+++ b/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java
@@ -186,4 +186,18 @@
         }
         mCallbacks.clear();
     }
+
+    /**
+     * Retrieve all the callback objects in the tracker with proper mask
+     */
+    public List<T> getCallbacks(int mask) {
+        List<T> callbacks = new ArrayList<>();
+        for(int callbackIdentifier: mCallbacks.keySet()) {
+            if (mask == (callbackIdentifier & mask)) {
+                callbacks.add(mCallbacks.get(callbackIdentifier).getCallback());
+            }
+        }
+        return callbacks;
+    }
+
 }
diff --git a/service/java/com/android/server/wifi/util/FileUtils.java b/service/java/com/android/server/wifi/util/FileUtils.java
index fb82142..54cb58c 100644
--- a/service/java/com/android/server/wifi/util/FileUtils.java
+++ b/service/java/com/android/server/wifi/util/FileUtils.java
@@ -20,6 +20,7 @@
 import android.system.Os;
 import android.util.Log;
 
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -49,6 +50,17 @@
         }
     }
 
+    public static void rename(File source, File target) {
+        if (target.isDirectory()) {
+            if (!target.delete()) {
+                Log.e(TAG, "Failed to delete file which is a directory " + target);
+            }
+        }
+        if (!source.renameTo(target)) {
+            Log.e(TAG, "Failed to rename " + source + " to " + target);
+        }
+    }
+
     /**
      * Writes the bytes given in {@code content} to the file whose absolute path
      * is {@code filename}.
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 60d074e..af16272 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -898,6 +898,7 @@
      * by wpa_supplicant.
      */
     public static class Capabilities {
+        private static final int CAP_VHT_8SS_OFFSET = 224; //(0xEO)
         private static final int WPA_VENDOR_OUI_TYPE_ONE = 0x01f25000;
         private static final int WPS_VENDOR_OUI_TYPE = 0x04f25000;
         private static final short WPA_VENDOR_OUI_VERSION = 0x0001;
@@ -918,8 +919,9 @@
         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 WPA2_AKM_DPP = 0x029a6f50;
 
         private static final int WPA_CIPHER_NONE = 0x00f25000;
         private static final int WPA_CIPHER_TKIP = 0x02f25000;
@@ -939,6 +941,8 @@
         public boolean isIBSS;
         public boolean isPrivacy;
         public boolean isWPS;
+        public boolean isHe;
+        public boolean isVht8ss;
 
         public Capabilities() {
         }
@@ -1007,6 +1011,9 @@
                         case RSN_AKM_PSK_SHA256:
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_PSK_SHA256);
                             break;
+                        case WPA2_AKM_DPP:
+                            rsnKeyManagement.add(ScanResult.KEY_MGMT_DPP);
+                            break;
                         case RSN_AKM_SAE:
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_SAE);
                             break;
@@ -1017,15 +1024,16 @@
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_OWE);
                             break;
                         case RSN_AKM_EAP_SUITE_B_192:
+                            Log.e("informationelement", "captured suite b" );
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP_SUITE_B_192);
                             break;
                         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:
@@ -1243,6 +1251,15 @@
                         keyManagement.add(oweKeyManagement);
                     }
                 }
+
+                if (ie.id == InformationElement.EID_VHT_CAPABILITIES && ie.bytes != null
+                        && ie.bytes.length > 1
+                        && ((ie.bytes[1] & CAP_VHT_8SS_OFFSET) == CAP_VHT_8SS_OFFSET)) {
+                    isVht8ss = true;
+                } else if (ie.id == InformationElement.EID_EXTENSION_PRESENT
+                               && ie.idExt == InformationElement.EID_EXT_HE_CAPABILITIES) {
+                    isHe = true;
+                }
             }
         }
 
@@ -1306,10 +1323,12 @@
                     return "WAPI-PSK";
                 case ScanResult.KEY_MGMT_WAPI_CERT:
                     return "WAPI-CERT";
+                case ScanResult.KEY_MGMT_DPP:
+                    return "DPP";
                 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 "?";
             }
@@ -1362,6 +1381,9 @@
             if (isWPS) {
                 capabilities.append("[WPS]");
             }
+            if (isVht8ss && isHe) {
+                capabilities.append("[WFA-HE-READY]");
+            }
 
             return capabilities.toString();
         }
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/NativeUtil.java b/service/java/com/android/server/wifi/util/NativeUtil.java
index bcc426c..e8fb084 100644
--- a/service/java/com/android/server/wifi/util/NativeUtil.java
+++ b/service/java/com/android/server/wifi/util/NativeUtil.java
@@ -41,7 +41,6 @@
     private static final int MAC_LENGTH = 6;
     private static final int MAC_OUI_LENGTH = 3;
     private static final int MAC_STR_LENGTH = MAC_LENGTH * 2 + 5;
-    private static final int SSID_BYTES_MAX_LEN = 32;
 
     /**
      * Convert the string to byte array list.
@@ -272,11 +271,7 @@
      * @throws IllegalArgumentException for null string.
      */
     public static ArrayList<Byte> decodeSsid(String ssidStr) {
-        ArrayList<Byte> ssidBytes = hexOrQuotedStringToBytes(ssidStr);
-        if (ssidBytes.size() > SSID_BYTES_MAX_LEN) {
-            throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size());
-        }
-        return ssidBytes;
+        return hexOrQuotedStringToBytes(ssidStr);
     }
 
     /**
@@ -290,9 +285,6 @@
      * @throws IllegalArgumentException for null bytes.
      */
     public static String encodeSsid(ArrayList<Byte> ssidBytes) {
-        if (ssidBytes.size() > SSID_BYTES_MAX_LEN) {
-            throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size());
-        }
         return bytesToHexOrQuotedString(ssidBytes);
     }
 
diff --git a/service/java/com/android/server/wifi/util/ScanResultUtil.java b/service/java/com/android/server/wifi/util/ScanResultUtil.java
index dc2281a..c4afd03 100644
--- a/service/java/com/android/server/wifi/util/ScanResultUtil.java
+++ b/service/java/com/android/server/wifi/util/ScanResultUtil.java
@@ -95,6 +95,14 @@
     }
 
     /**
+     * Helper method to check if the provided |scanResult| corresponds to DPP network.
+     * This checks if the provided capabilities string contains DPP or not.
+     */
+    public static boolean isScanResultForDppNetwork(ScanResult scanResult) {
+        return scanResult.capabilities.contains("DPP");
+    }
+
+    /**
      * Helper method to check if the provided |scanResult| corresponds to OWE network.
      * This checks if the provided capabilities string contains OWE or not.
      */
@@ -233,6 +241,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/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java
index eb204e7..65d032c 100644
--- a/service/java/com/android/server/wifi/util/XmlUtil.java
+++ b/service/java/com/android/server/wifi/util/XmlUtil.java
@@ -355,6 +355,12 @@
         public static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled";
         public static final String XML_TAG_IS_TRUSTED = "Trusted";
         private static final String XML_TAG_IS_MOST_RECENTLY_CONNECTED = "IsMostRecentlyConnected";
+        public static final String XML_TAG_SHARE_THIS_AP = "ShareThisAp";
+
+        public static final String XML_TAG_DPP_CONNECTOR = "DppConnector";
+        public static final String XML_TAG_DPP_NETACCESSKEY = "DppNetAccessKey";
+        public static final String XML_TAG_DPP_NETACCESSKEY_EXPIRY = "DppNetAccessKeyExpiry";
+        public static final String XML_TAG_DPP_CSIGN = "DppCsign";
 
         /**
          * Write WepKeys to the XML stream.
@@ -427,6 +433,7 @@
                 throws XmlPullParserException, IOException {
             XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.getKey());
             XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID);
+            XmlUtil.writeNextValue(out, XML_TAG_SHARE_THIS_AP, configuration.shareThisAp);
             writePreSharedKeyToXml(out, configuration.preSharedKey, encryptionUtil);
             writeWepKeysToXml(out, configuration.wepKeys);
             XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex);
@@ -520,6 +527,11 @@
             XmlUtil.writeNextValue(out, XML_TAG_CARRIER_ID, configuration.carrierId);
             XmlUtil.writeNextValue(out, XML_TAG_IS_MOST_RECENTLY_CONNECTED,
                     configuration.isMostRecentlyConnected);
+
+            XmlUtil.writeNextValue(out, XML_TAG_DPP_CONNECTOR, configuration.dppConnector);
+            XmlUtil.writeNextValue(out, XML_TAG_DPP_NETACCESSKEY, configuration.dppNetAccessKey);
+            XmlUtil.writeNextValue(out, XML_TAG_DPP_NETACCESSKEY_EXPIRY, configuration.dppNetAccessKeyExpiry);
+            XmlUtil.writeNextValue(out, XML_TAG_DPP_CSIGN, configuration.dppCsign);
         }
 
         /**
@@ -586,6 +598,9 @@
                         case XML_TAG_BSSID:
                             configuration.BSSID = (String) value;
                             break;
+                        case XML_TAG_SHARE_THIS_AP:
+                            configuration.shareThisAp = (boolean) value;
+                            break;
                         case XML_TAG_PRE_SHARED_KEY:
                             configuration.preSharedKey = (String) value;
                             break;
@@ -697,6 +712,18 @@
                             configuration.setRandomizedMacAddress(
                                     MacAddress.fromString((String) value));
                             break;
+                        case XML_TAG_DPP_CONNECTOR:
+                            configuration.dppConnector = (String) value;
+                            break;
+                        case XML_TAG_DPP_NETACCESSKEY:
+                            configuration.dppNetAccessKey = (String) value;
+                            break;
+                        case XML_TAG_DPP_NETACCESSKEY_EXPIRY:
+                            configuration.dppNetAccessKeyExpiry = (int) value;
+                            break;
+                        case XML_TAG_DPP_CSIGN:
+                            configuration.dppCsign = (String) value;
+                            break;
                         case XML_TAG_MAC_RANDOMIZATION_SETTING:
                             configuration.macRandomizationSetting = (int) value;
                             macRandomizationSettingExists = true;
@@ -1114,6 +1141,7 @@
         public static final String XML_TAG_REALM = "Realm";
         public static final String XML_TAG_OCSP = "Ocsp";
         public static final String XML_TAG_WAPI_CERT_SUITE = "WapiCertSuite";
+        public static final String XML_TAG_SIMNUM = "SimNum";
 
         /**
          * Write password key to the XML stream.
@@ -1187,6 +1215,7 @@
             XmlUtil.writeNextValue(out, XML_TAG_OCSP, enterpriseConfig.getOcsp());
             XmlUtil.writeNextValue(out,
                     XML_TAG_WAPI_CERT_SUITE, enterpriseConfig.getWapiCertSuite());
+            XmlUtil.writeNextValue(out, XML_TAG_SIMNUM, enterpriseConfig.getSimNum());
         }
 
         /**
@@ -1287,6 +1316,17 @@
                         case XML_TAG_WAPI_CERT_SUITE:
                             enterpriseConfig.setWapiCertSuite((String) value);
                             break;
+                        case XML_TAG_SIMNUM:
+                            int sim_num;
+                            try {
+                                sim_num = Integer.parseInt((String) value);
+                            } catch (NumberFormatException e) {
+                                sim_num = -1;
+                            }
+                            if (sim_num > 0) {
+                                enterpriseConfig.setSimNum(sim_num);
+                            }
+                            break;
                         default:
                             Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]);
                             break;
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-af/strings.xml b/service/res/values-af/strings.xml
index d4e52ba..ff81fd3 100644
--- a/service/res/values-af/strings.xml
+++ b/service/res/values-af/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Netwerke wat deur <xliff:g id="NAME">%s</xliff:g> voorgestel is. Toestel sal dalk outomaties koppel."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Laat toe"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nee, dankie"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> wil outomaties koppel"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Hierdie netwerke ontvang \'n unieke ID wat gebruik kan word om toestelligging na te spoor"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Koppel in elk geval"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Koppel aan <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Hierdie netwerke ontvang \'n SIM-ID wat gebruik kan word om toestelligging na te spoor"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Koppel"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Moenie koppel nie"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bevestig verbinding?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"As jy koppel, kan <xliff:g id="CARRIERNAME">%s</xliff:g> se Wi‑Fi-netwerke toegang kry tot \'n unieke ID wat met jou SIM geassosieer word, of dit deel. Dit kan dit vir hulle moontlik maak om jou toestel se ligging na te spoor."</string>
diff --git a/service/res/values-am/strings.xml b/service/res/values-am/strings.xml
index 5d8bac3..64c045e 100644
--- a/service/res/values-am/strings.xml
+++ b/service/res/values-am/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"በ<xliff:g id="NAME">%s</xliff:g> የተጠቆሙ አውታረ መረቦች። መሣሪያ በራስ-ሰር ሊገናኝ ይችላል።"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ፍቀድ"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"አይ፣ አመሰግናለሁ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> በራስ-ሰር መገናኘት ይፈልጋል"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"እነዚህ አውታረ መረቦች የመሣሪያ አካባቢን ለመከታተል ሥራ ላይ ሊውል የሚችል ልዩ መታወቂያ ተቀብለዋል።"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ለማንኛውም ተገናኝ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ከ<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi ጋር ይገናኙ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"እነዚህ አውታረ መረቦች የመሣሪያ አካባቢን ለመከታተል ሥራ ላይ ሊውል የሚችል የሲም መታወቂያ ተቀብለዋል።"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"አገናኝ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"አታገናኝ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ግንኙነት ይረጋገጥ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ከተገናኙ የ<xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi አውትረ መረቦች ከእርስዎ ሲም ጋር የተጎዳኘ ልዩ መታወቂያ ሊደርሱ ወይም ሊያጋሩ ይችላሉ። ይህ የመሣሪያዎ አካባቢ ክትትል እንዲደረግበት ሊያስችል ይችላል።"</string>
diff --git a/service/res/values-ar/strings.xml b/service/res/values-ar/strings.xml
index fd9df74..0ca4266 100644
--- a/service/res/values-ar/strings.xml
+++ b/service/res/values-ar/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"شبكات <xliff:g id="NAME">%s</xliff:g> المقترحة - قد يتم توصيل الجهاز تلقائيًا."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"سماح"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"لا، شكرًا"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"يريد مشغِّل شبكة الجوّال <xliff:g id="CARRIERNAME">%s</xliff:g> الاتصال التلقائي بالشبكة."</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"تتلقّى هذه الشبكات معرّفًا فريدًا يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"الاتصال على أي حال"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"‏هل تريد ربط <xliff:g id="CARRIERNAME">%s</xliff:g> بشبكة Wi-Fi؟"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"‏تتلقّى هذه الشبكات رقم تعريف لشريحة SIM يمكن استخدامه لتتبُّع الموقع الجغرافي للجهاز."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ربط"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"عدم الاتصال"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"هل تريد تأكيد الاتصال بالشبكة؟"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"‏في حال اتصال بالشبكة، يمكن لشبكات Wi‑Fi من <xliff:g id="CARRIERNAME">%s</xliff:g> الوصول إلى المعرّف الفريد المرتبط بشريحة SIM أو مشاركته. قد يسمح هذا بتتبُّع الموقع الجغرافي لجهازك."</string>
diff --git a/service/res/values-as/strings.xml b/service/res/values-as/strings.xml
index 0ece64d..a38a860 100644
--- a/service/res/values-as/strings.xml
+++ b/service/res/values-as/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>এ পৰামর্শ হিচাপে দিয়া নেটৱর্কবোৰ। ডিভাইচটো স্বয়ংক্ৰিয়ভাৱে সংযোগ হ\'ব পাৰে।"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"অনুমতি দিয়ক"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"নালাগে, ধন্যবাদ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>এ স্বয়ংক্ৰিয়ভাৱে সংযোগ কৰিবলৈ বিচাৰিছে"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"এই নেটৱৰ্কসমূহে এটা সুকীয়া আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পৰা যায়"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"যিহ’লেও সংযোগ কৰক"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ৱাই-ফাইৰ সৈতে সংযোগ কৰিবনে?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"এই নেটৱৰ্কটোৱে এটা ছিম আইডি পায়, যিটো ডিভাইচৰ অৱস্থান ট্ৰেক কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"সংযোগ কৰক"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"সংযোগ নকৰিব"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"সংযোগ নিশ্চিত কৰিবনে?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"আপুনি যদি সংযোগ কৰে, <xliff:g id="CARRIERNAME">%s</xliff:g>ৰ ৱাই-ফাই নেটৱৰ্কসমূহে আপোনাৰ ছিমৰ সৈতে জড়িত এটা সুকীয়া আইডি এক্সেছ কৰিব অথবা সেইটো শ্বেয়াৰ কৰিব পাৰে। এইটোৱে আপোনাৰ ডিভাইচটোৰ অৱস্থান ট্ৰেক কৰাৰ অনুমতি দিব পাৰে।"</string>
diff --git a/service/res/values-az/strings.xml b/service/res/values-az/strings.xml
index db40150..ae0455e 100644
--- a/service/res/values-az/strings.xml
+++ b/service/res/values-az/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> təklif edilən şəbəkə. Cihaz avtomatik qoşula bilər."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"İcazə verin"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Xeyr, təşəkkürlər"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> avtomatik qoşulmaq istəyir"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Bu şəbəkələr cihaz məkanını izləmək üçün istifadə edilə biləcək unikal ID qəbul edir"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"İstənilən halda qoşulun"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi şəbəkəsinə qoşulsun?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu şəbəkələr cihaz məkanını izləmək üçün istifadə edilə biləcək SIM ID qəbul edir"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Qoşun"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Qoşulmayın"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bağlantı təsdiq edilsin?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Qoşulsanız, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi şəbəkələri SIM kartınızla əlaqəli unikal ID\'ə daxil ola və ya onu paylaşa bilər. Bu, cihazınızın məkanının izlənilməsinə icazə verə bilər."</string>
diff --git a/service/res/values-b+sr+Latn/strings.xml b/service/res/values-b+sr+Latn/strings.xml
index 08970f9..634f9a7 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>
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže <xliff:g id="NAME">%s</xliff:g>. Uređaj će se možda povezati automatski."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dozvoli"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> želi da se automatski poveže"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ove mreže zahtevaju jedinstveni ID koji može da se koristi za praćenje lokacije uređaja"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ipak poveži"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite da se povežete na WiFi mrežu <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže dobijaju ID SIM kartice koji može da se koristi za praćenje lokacije uređaja"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne povezuj"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite li da potvrdite povezivanje?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wi‑Fi mreže operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu da pristupaju jedinstvenom ID-u povezanom sa SIM karticom ili da ga dele. To može da omogući praćenje lokacije uređaja."</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_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>
+    <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>, stavite <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM karticu"</string>
 </resources>
diff --git a/service/res/values-be/strings.xml b/service/res/values-be/strings.xml
index b66cb9a..76e9c02 100644
--- a/service/res/values-be/strings.xml
+++ b/service/res/values-be/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Праграма \"<xliff:g id="NAME">%s</xliff:g>\" прапанавала сеткі. Прылада можа падключыцца да ніх аўтаматычна."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дазволіць"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, дзякуй"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> запытвае дазвол на аўтаматычнае падключэнне"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Гэтыя сеткі атрымліваюць унікальны ідэнтыфікатар, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Усё роўна падключыцца"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Падключыцца да Wi-Fi аператара \"<xliff:g id="CARRIERNAME">%s</xliff:g>\"?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Гэтыя сеткі атрымліваюць ідэнтыфікатар SIM-карты, які можа выкарыстоўвацца для адсочвання месцазнаходжання прылады"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Падключыцца"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не падключацца"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Пацвердзіць падключэнне?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Калі вы падключыцеся, сеткі Wi‑Fi аператара \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" змогуць атрымаць доступ да ўнікальнага ідэнтыфікатара, звязанага з вашай SIM-картай, ці абагуліць яго. Можа ўзнікнуць магчымасць адсочваць месцазнаходжанне вашай прылады."</string>
diff --git a/service/res/values-bg/strings.xml b/service/res/values-bg/strings.xml
index 915b7fa..d849753 100644
--- a/service/res/values-bg/strings.xml
+++ b/service/res/values-bg/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Предложени от <xliff:g id="NAME">%s</xliff:g> мрежи. Устройството може да се свърже автоматично."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Разрешаване"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, благодаря"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> иска да се свързва автоматично"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Тези мрежи получават уникален идентификатор, който може да се използва за проследяване на местоположението на устройството"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Свързване въпреки това"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Искате ли да се свържете с Wi-Fi от <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Тези мрежи получават идентификатор за SIM карта, който може да се използва за проследяване на местоположението на устройството"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Свързване"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Без свързване"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Потвърждавате ли връзката?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се свържете, Wi-Fi мрежите на <xliff:g id="CARRIERNAME">%s</xliff:g> може да имат достъп или да споделят уникален идентификатор, свързан със SIM картата ви. Това може да позволи проследяването на местоположението на устройството ви."</string>
diff --git a/service/res/values-bn/strings.xml b/service/res/values-bn/strings.xml
index 6973575..2ca2fa9 100644
--- a/service/res/values-bn/strings.xml
+++ b/service/res/values-bn/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>-এর সাজেস্ট করা নেটওয়ার্ক। ডিভাইস নিজে থেকে কানেক্ট হতে পারে।"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"অনুমতি দিন"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"না থাক"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> অটোমেটিক কানেক্ট করতে চায়"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"এই নেটওয়ার্ক যে অনন্য আইডি পায় সেটি ব্যবহার করে ডিভাইসের লোকেশন ট্র্যাক করা যায়"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"তা সত্ত্বেও কানেক্ট করুন"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ওয়াই-ফাইতে কানেক্ট করবেন?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"এই নেটওয়ার্কগুলির কাছে একটি সিম আইডি থাকে যা ব্যবহার করে এই নেটওয়ার্কের সাথে যুক্ত থাকা ডিভাইসের লোকেশন ট্র্যাক করা যেত পারে"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"কানেক্ট করুন"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"কানেক্ট করবেন না"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"কানেকশন কনফার্ম করতে চান?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"আপনি কানেক্ট করলে, <xliff:g id="CARRIERNAME">%s</xliff:g> ওয়াই-ফাই নেটওয়ার্ক আপনার সিমের সাথে সম্পর্কযুক্ত একটি অনন্য আইডি অ্যাক্সেস বা শেয়ার করতে পারে। এর ফলে আপনার ডিভাইসের লোকেশন ট্র্যাক করা যেতে পারে।"</string>
diff --git a/service/res/values-bs/strings.xml b/service/res/values-bs/strings.xml
index 2b3d563..1afb4a2 100644
--- a/service/res/values-bs/strings.xml
+++ b/service/res/values-bs/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže <xliff:g id="NAME">%s</xliff:g>. Uređaj će se možda povezati automatski."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dozvoli"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> se želi automatski povezati"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ove mreže primaju jedinstveni ID koji se može koristiti za praćenje lokacije uređaja"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ipak se poveži"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Povezati se s WiFi mrežom operatera <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže primaju ID SIM-a koji se može koristiti za praćenje lokacije uređaja"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nemoj se povezati"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potvrditi povezivanje?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wi-Fi mreže mobilnog operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu pristupiti jedinstvenom ID-u koji je povezan s vašom SIM karticom ili ga podijeliti. Na taj način možete dozvoliti da se prati lokacija vašeg uređaja."</string>
diff --git a/service/res/values-ca/strings.xml b/service/res/values-ca/strings.xml
index d9de95f..84ec898 100644
--- a/service/res/values-ca/strings.xml
+++ b/service/res/values-ca/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Xarxes suggerides de l\'aplicació <xliff:g id="NAME">%s</xliff:g>. El dispositiu pot connectar-se automàticament."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permet"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gràcies"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"L\'operador <xliff:g id="CARRIERNAME">%s</xliff:g> vol connectar-se automàticament"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Aquestes xarxes reben un identificador únic que es pot utilitzar per fer un seguiment de la ubicació del dispositiu"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Connecta\'t de totes maneres"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vols connectar-te a la Wi‑Fi de l\'operador <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Aquestes xarxes reben un identificador de SIM que es pot utilitzar per fer el seguiment de la ubicació del dispositiu"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connecta"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No et connectis"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vols confirmar la connexió?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si et connectes, les xarxes Wi‑Fi de l\'operador <xliff:g id="CARRIERNAME">%s</xliff:g> poden compartir un identificador únic associat a la teva SIM o bé accedir-hi. Això pot permetre que es faci un seguiment de la ubicació del teu dispositiu."</string>
diff --git a/service/res/values-cs/strings.xml b/service/res/values-cs/strings.xml
index 68b2cab..dcc7b9f 100644
--- a/service/res/values-cs/strings.xml
+++ b/service/res/values-cs/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Sítě navrhované aplikací <xliff:g id="NAME">%s</xliff:g>. Zařízení se může připojovat automaticky."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Povolit"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, díky"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Operátor <xliff:g id="CARRIERNAME">%s</xliff:g> se chce automaticky připojit"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Tyto sítě dostávají jedinečné ID, pomocí něhož lze sledovat polohu zařízení"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Přesto připojit"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Připojit k Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tyto sítě dostávají identifikátor SIM karty, pomocí něhož lze sledovat polohu zařízení"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Připojit"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nepřipojovat"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potvrdit připojení?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Pokud se připojíte, sítě Wi-Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g> mohou získat přístup k jedinečnému ID přidruženému k vaší SIM kartě. Může to umožnit sledování polohy zařízení."</string>
diff --git a/service/res/values-da/strings.xml b/service/res/values-da/strings.xml
index fbd9c92..6f388ee 100644
--- a/service/res/values-da/strings.xml
+++ b/service/res/values-da/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Netværk foreslået af <xliff:g id="NAME">%s</xliff:g>. Enheden opretter muligvis forbindelse automatisk."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillad"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nej tak"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vil gerne oprette forbindelse automatisk"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Disse netværk modtager et unikt id, der kan bruges til at spore enhedens placering"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Opret forbindelse alligevel"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Opret forbindelse til <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi-Fi"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Disse netværk kræver et SIM-id, der kan bruges til at spore enhedens placering"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Opret forbindelse"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Opret ikke forbindelse"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vil du bekræfte forbindelsen?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Hvis du opretter forbindelse, kan Wi-Fi-netværk fra <xliff:g id="CARRIERNAME">%s</xliff:g> få adgang til eller dele et unikt id, der er knyttet til dit SIM-kort. Derved kan din enheds placering muligvis spores."</string>
diff --git a/service/res/values-de/strings.xml b/service/res/values-de/strings.xml
index 21aa008..ad695ce 100644
--- a/service/res/values-de/strings.xml
+++ b/service/res/values-de/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Von <xliff:g id="NAME">%s</xliff:g> vorgeschlagene Netzwerke. Gerät verbindet sich möglicherweise automatisch."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Zulassen"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nein danke"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> möchte sich automatisch verbinden"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Diese Mobilfunknetze empfangen eine eindeutige ID, mit der der Gerätestandort ermittelt werden kann"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Trotzdem verbinden"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Mit <xliff:g id="CARRIERNAME">%s</xliff:g>-WLAN verbinden?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Diese Netzwerke empfangen eine SIM-ID, mit der der Gerätestandort erfasst werden kann"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Verbinden"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nicht verbinden"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Verbindung bestätigen?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Wenn du eine Verbindung herstellst, können die WLANs von <xliff:g id="CARRIERNAME">%s</xliff:g> möglicherweise eine eindeutige ID abrufen oder teilen, die deiner SIM zugewiesen ist. Damit lässt sich unter Umständen der Standort deines Geräts ermitteln."</string>
diff --git a/service/res/values-el/strings.xml b/service/res/values-el/strings.xml
index 0e3dd9e..83bdbfe 100644
--- a/service/res/values-el/strings.xml
+++ b/service/res/values-el/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Προτεινόμενα δίκτυα <xliff:g id="NAME">%s</xliff:g>. Η συσκευή μπορεί να συνδεθεί αυτόματα."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Αποδοχή"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Όχι, ευχαριστώ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Η εταιρεία κινητής τηλεφωνίας <xliff:g id="CARRIERNAME">%s</xliff:g> θέλει αυτόματη σύνδεση"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Αυτά τα δίκτυα λαμβάνουν ένα μοναδικό αναγνωριστικό που μπορεί να χρησιμοποιηθεί για την παρακολούθηση της τοποθεσίας της συσκευής."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Σύνδεση ούτως ή άλλως"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Σύνδεση στο Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>;"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Αυτά τα δίκτυα λαμβάνουν ένα αναγνωριστικό SIM που μπορεί να χρησιμοποιηθεί για την παρακολούθηση της τοποθεσίας της συσκευής."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Σύνδεση"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Να μην γίνει σύνδεση."</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Επιβεβαίωση της σύνδεσης;"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Εάν συνδεθείτε, τα δίκτυα Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ενδέχεται να έχουν πρόσβαση ή να μοιράζονται ένα μοναδικό αναγνωριστικό που σχετίζεται με την κάρτα σας SIM. Αυτό μπορεί να επιτρέψει την παρακολούθηση της τοποθεσίας της συσκευής σας."</string>
diff --git a/service/res/values-en-rAU/strings.xml b/service/res/values-en-rAU/strings.xml
index 17565ba..43d5ce8 100644
--- a/service/res/values-en-rAU/strings.xml
+++ b/service/res/values-en-rAU/strings.xml
@@ -31,9 +31,9 @@
     <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>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string>
     <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-en-rCA/strings.xml b/service/res/values-en-rCA/strings.xml
index 17565ba..43d5ce8 100644
--- a/service/res/values-en-rCA/strings.xml
+++ b/service/res/values-en-rCA/strings.xml
@@ -31,9 +31,9 @@
     <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>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string>
     <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-en-rGB/strings.xml b/service/res/values-en-rGB/strings.xml
index 17565ba..43d5ce8 100644
--- a/service/res/values-en-rGB/strings.xml
+++ b/service/res/values-en-rGB/strings.xml
@@ -31,9 +31,9 @@
     <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>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string>
     <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-en-rIN/strings.xml b/service/res/values-en-rIN/strings.xml
index 17565ba..43d5ce8 100644
--- a/service/res/values-en-rIN/strings.xml
+++ b/service/res/values-en-rIN/strings.xml
@@ -31,9 +31,9 @@
     <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>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connect to <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"These networks receive a SIM ID that can be used to track device location"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connect"</string>
     <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-en-rXC/strings.xml b/service/res/values-en-rXC/strings.xml
deleted file mode 100644
index 22db537..0000000
--- a/service/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<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">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‎System Wi-Fi Resources‎‏‎‎‏‎"</string>
-    <string name="wifi_available_title" msgid="2844963247498642107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‎Connect to open Wi‑Fi network‎‏‎‎‏‎"</string>
-    <string name="wifi_available_title_connecting" msgid="4308431577637294026">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‎Connecting to Wi‑Fi network‎‏‎‎‏‎"</string>
-    <string name="wifi_available_title_connected" msgid="922603556292157664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎Connected to Wi‑Fi network‎‏‎‎‏‎"</string>
-    <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎Could not connect to Wi‑Fi network‎‏‎‎‏‎"</string>
-    <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎Tap to see all networks‎‏‎‎‏‎"</string>
-    <string name="wifi_available_action_connect" msgid="7989951293406720158">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎Connect‎‏‎‎‏‎"</string>
-    <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‎‎All networks‎‏‎‎‏‎"</string>
-    <string name="notification_channel_network_status" msgid="7808526906954286713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎Network status‎‏‎‎‏‎"</string>
-    <string name="notification_channel_network_alerts" msgid="3638265846217667221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎Network alerts‎‏‎‎‏‎"</string>
-    <string name="notification_channel_network_available" msgid="7791052175212297403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎Network available‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_title" msgid="8724552631151189767">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎Allow suggested Wi‑Fi networks?‎‏‎‎‏‎"</string>
-    <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>
-    <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>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎Connect‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎Don\'t connect‎‏‎‎‏‎"</string>
-    <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎Wi‑Fi will turn on automatically‎‏‎‎‏‎"</string>
-    <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎When you\'re near a high quality saved network‎‏‎‎‏‎"</string>
-    <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎Don\'t turn back on‎‏‎‎‏‎"</string>
-    <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎Wi‑Fi turned on automatically‎‏‎‎‏‎"</string>
-    <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎You\'re near a saved network: ‎‏‎‎‏‏‎<xliff:g id="NETWORK_SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎Couldn\'t connect to Wi-Fi‎‏‎‎‏‎"</string>
-    <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎ has a poor internet connection.‎‏‎‎‏‎"</string>
-    <string name="wifi_connect_alert_title" msgid="6144470472092017636">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎Allow connection?‎‏‎‎‏‎"</string>
-    <string name="wifi_connect_alert_message" msgid="3123801378559831220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎Application %1$s would like to connect to Wifi Network %2$s‎‏‎‎‏‎"</string>
-    <string name="wifi_connect_default_application" msgid="6164721692891325243">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‎An application‎‏‎‎‏‎"</string>
-    <string name="accept" msgid="5931271886782610829">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎Accept‎‏‎‎‏‎"</string>
-    <string name="decline" msgid="6874256900873707640">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎Decline‎‏‎‎‏‎"</string>
-    <string name="ok" msgid="4215387532539340948">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎OK‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎Invitation sent‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎Invitation to connect‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_from_message" msgid="3857436922001981191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎From:‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_to_message" msgid="6664932426704362946">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎To:‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎Type the required PIN:‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎PIN:‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎The tablet will temporarily disconnect from Wi-Fi while it\'s connected to ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎Your Android TV device will temporarily disconnect from Wi-Fi while it\'s connected to ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎The phone will temporarily disconnect from Wi-Fi while it\'s connected to ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="dlg_ok" msgid="3250085870426030310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎OK‎‏‎‎‏‎"</string>
-    <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎Can\'t connect to ‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎Tap to change privacy settings and retry‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎Change privacy setting?‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_message" msgid="6780528750693169829">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎To connect, ‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ needs to use your device MAC address, a unique identifier. Currently, your privacy setting for this network uses a randomized identifier. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This change may allow your device\'s location to be tracked by nearby devices.‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6592972299988727403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎Change setting‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎Setting updated. Try connecting again.‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎Can\'t change privacy setting‎‏‎‎‏‎"</string>
-    <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎Network not found‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32760‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32761‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32762‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32763‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32764‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32765‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : EAP authentication error 32766‎‏‎‎‏‎"</string>
-    <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎Hotspot turned off‎‏‎‎‏‎"</string>
-    <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎No devices connected. Tap to modify.‎‏‎‎‏‎"</string>
-    <string name="wifi_sim_required_title" msgid="8362843050699015640">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎Wi‑Fi disconnected‎‏‎‎‏‎"</string>
-    <string name="wifi_sim_required_message" msgid="6085636103482409595">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎To connect to ‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎, insert a ‎‏‎‎‏‏‎<xliff:g id="CARRIER_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ SIM‎‏‎‎‏‎"</string>
-</resources>
diff --git a/service/res/values-es-rUS/strings.xml b/service/res/values-es-rUS/strings.xml
index 615d844..a512dc4 100644
--- a/service/res/values-es-rUS/strings.xml
+++ b/service/res/values-es-rUS/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> sugirió redes. Es posible que el dispositivo se conecte automáticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gracias"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> quiere conectarse automáticamente"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Estas redes reciben un ID único que puede usarse para realizar el seguimiento de la ubicación del dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectar de todos modos"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"¿Quieres conectarte a la red Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un ID de SIM que puede usarse para realizar el seguimiento de la ubicación del dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No conectar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"¿Confirmar conexión?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si te conectas, las redes de Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> podrán acceder o compartir un ID único asociado con tu SIM. Esto podría permitir que se realice el seguimiento de la ubicación del dispositivo."</string>
diff --git a/service/res/values-es/strings.xml b/service/res/values-es/strings.xml
index 29a33b2..4695bd0 100644
--- a/service/res/values-es/strings.xml
+++ b/service/res/values-es/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> te ha sugerido alguna red. El dispositivo puede que se conecte automáticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, gracias"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> quiere conectarse automáticamente"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Estas redes reciben un ID único con el que se puede rastrear la ubicación del dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectar de todos modos"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"¿Conectarse a la red Wi‑Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un ID de SIM con el que se puede rastrear la ubicación del dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"No conectar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"¿Confirmar conexión?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si te conectas, es posible que la red Wi‑Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> obtenga o comparta un ID único asociado a tu SIM, lo que puede permitir que se rastree la ubicación de tu dispositivo."</string>
diff --git a/service/res/values-et/strings.xml b/service/res/values-et/strings.xml
index f0785b5..00713b6 100644
--- a/service/res/values-et/strings.xml
+++ b/service/res/values-et/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rakenduse <xliff:g id="NAME">%s</xliff:g> soovitatud võrgud. Seade võib automaatselt ühenduse luua."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Luba"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Tänan, ei"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> soovib automaatselt ühenduse luua"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Need võrgud saavad kordumatu ID, mida saab kasutada seadme asukoha jälgimiseks."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ühenda siiski"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kas luua ühendus operaatori <xliff:g id="CARRIERNAME">%s</xliff:g> WiFi-võrguga?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Need võrgud saavad SIM-i ID, mida saab kasutada seadme asukoha jälgimiseks."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ühenda"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ära ühenda"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Kas soovite ühenduse kinnitada?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Kui loote ühenduse, võivad operaatori <xliff:g id="CARRIERNAME">%s</xliff:g> WiFi-võrgud teie SIM-kaardiga seotud kordumatule ID-le juurde pääseda või seda jagada. See võib võimaldada seadme asukohta jälgida."</string>
diff --git a/service/res/values-eu/strings.xml b/service/res/values-eu/strings.xml
index 822d724..ccb1d33 100644
--- a/service/res/values-eu/strings.xml
+++ b/service/res/values-eu/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> aplikazioak sare batzuk iradoki ditu. Baliteke gailua automatikoki konektatzea."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Baimendu"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ez, eskerrik asko"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> operadoreak automatikoki konektatu nahi du"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Sare hauek ID esklusibo bat jasotzen dute, gailuaren kokapenaren jarraipena egin ahal izateko"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Konektatu halere"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> operadorearen wifi-sarera konektatu nahi duzu?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Sare hauek SIM ID bat jasotzen dute, gailuaren kokapenaren jarraipena egin ahal izateko"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Konektatu"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ez konektatu"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Konexioa berretsi nahi duzu?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Konektatzen bazara, baliteke <xliff:g id="CARRIERNAME">%s</xliff:g> operadorearen wifi-sareek zure SIM txartelarekin lotutako ID esklusiboa atzitzea edo partekatzea. Horrela, baliteke zure gailuaren kokapenaren jarraipena egiteko aukera izatea."</string>
@@ -55,7 +55,7 @@
     <string name="wifi_p2p_invitation_sent_title" msgid="6684220950195735982">"Gonbidapena bidali da"</string>
     <string name="wifi_p2p_invitation_to_connect_title" msgid="5020192895172598089">"Konektatzeko gonbidapena"</string>
     <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Igorlea:"</string>
-    <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Hartzailea:"</string>
+    <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Hartzaileak:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Idatzi beharrezko PINa:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PINa:"</string>
     <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tableta wifi-saretik deskonektatuko da <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string>
diff --git a/service/res/values-fa/strings.xml b/service/res/values-fa/strings.xml
index b6d0139..739b5c4 100644
--- a/service/res/values-fa/strings.xml
+++ b/service/res/values-fa/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"شبکه‌های پیشنهادی <xliff:g id="NAME">%s</xliff:g>. ممکن است دستگاه به‌طور خودکار متصل شود."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"مجاز"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"نه متشکرم"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> می‌خواهد به‌طور خودکار متصل شود"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"این شبکه‌ها شناسه یکتایی دریافت می‌کنند که می‌توانید از آن برای ردیابی مکان دستگاه استفاده کرد"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"درهر صورت متصل شود"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"‏به Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> متصل می‌شوید؟"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"این شبکه‌ها شناسه سیم‌کارتی دریافت می‌کنند که می‌توان از آن برای ردیابی مکان دستگاه استفاده کرد"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"اتصال"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"متصل نشود"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"اتصال را تأیید می‌کنید؟"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"‏اگر متصل شوید، شبکه‌های Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g> می‌توانند به شناسه یکتای مربوط به سیم‌کارتتان دسترسی پیدا کنند و از آن به‌صورت مشترک استفاده کنند. این کار ممکن است ردیابی مکان دستگاه را مجاز کند."</string>
@@ -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-fi/strings.xml b/service/res/values-fi/strings.xml
index 583ec42..8efc7df 100644
--- a/service/res/values-fi/strings.xml
+++ b/service/res/values-fi/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ehdotti verkkoja. Laite voi muodostaa yhteyden automaattisesti."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Salli"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ei kiitos"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> haluaa muodostaa yhteyden automaattisesti"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Nämä verkot saavat yksilöllisen tunnuksen, jolla laitteen sijaintia voi seurata."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Yhdistä silti"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Yhdistetäänkö Wi-Fi-verkkoon (<xliff:g id="CARRIERNAME">%s</xliff:g>)?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Nämä verkot saavat SIM-tunnuksen, jolla voidaan seurata laitteen sijaintia."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Yhdistä"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Älä yhdistä"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vahvistetaanko yhteys?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jos muodostat yhteyden, Wi-Fi-verkot (<xliff:g id="CARRIERNAME">%s</xliff:g>) voivat nähdä tai jakaa yksilöllisen tunnuksen, joka liittyy SIM-korttiisi. Tämän kautta laitteesi sijaintia voidaan seurata."</string>
diff --git a/service/res/values-fr-rCA/strings.xml b/service/res/values-fr-rCA/strings.xml
index 3a34f3c..938c2d5 100644
--- a/service/res/values-fr-rCA/strings.xml
+++ b/service/res/values-fr-rCA/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Réseaux suggérés par <xliff:g id="NAME">%s</xliff:g>. L\'appareil peut s\'y connecter automatiquement."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Autoriser"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non merci"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> souhaite se connecter automatiquement"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ces réseaux reçoivent un identifiant unique qui peut être utilisé pour faire le suivi de la position de l\'appareil"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Se connecter sans même"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Connexion au Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ces réseaux reçoivent un identifiant SIM qui peut être utilisé pour faire le suivi de la position de l\'appareil"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connecter"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne pas se connecter"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmer la connexion?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si vous vous connectez, les réseaux Wi-Fi de <xliff:g id="CARRIERNAME">%s</xliff:g> pourront accéder à un identifiant unique associé à votre module SIM ou partager cet identifiant. Cela pourrait permettre à d\'autres appareils de faire le suivi de la position de votre appareil."</string>
diff --git a/service/res/values-fr/strings.xml b/service/res/values-fr/strings.xml
index 62999cc..6949a33 100644
--- a/service/res/values-fr/strings.xml
+++ b/service/res/values-fr/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Réseaux suggérés par <xliff:g id="NAME">%s</xliff:g>. L\'appareil pourra se connecter automatiquement."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Autoriser"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non, merci"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> souhaite se connecter automatiquement"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ces réseaux reçoivent un identifiant unique qui peut être utilisé pour suivre la position de l\'appareil"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Connecter quand même"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Se connecter au Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ces réseaux reçoivent un ID de SIM qui peut être utilisé pour suivre la position de l\'appareil"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Se connecter"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne pas connecter"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmer la connexion ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Si vous établissez la connexion, les réseaux Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> peuvent accéder à un identifiant unique associé à votre carte SIM ou le partager. Suite à cette connexion, la position de votre appareil peut également d\'être suivie."</string>
diff --git a/service/res/values-gl/strings.xml b/service/res/values-gl/strings.xml
index 71fd10f..45cb1e4 100644
--- a/service/res/values-gl/strings.xml
+++ b/service/res/values-gl/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes suxeridas de <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode conectarse automaticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Non, grazas"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> quere conectarse automaticamente"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Estas redes reciben un código exclusivo que se pode usar para facer un seguimento da localización dun dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectar igualmente"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Quéreste conectar á rede wifi de <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes reciben un código SIM que se pode usar para facer un seguimento da localización do dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Non conectar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Queres confirmar a conexión?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se te conectas, as redes wifi de <xliff:g id="CARRIERNAME">%s</xliff:g> poden acceder a un código exclusivo asociado coa túa SIM ou ben compartilo. Deste xeito, pódese facer un seguimento da localización do teu dispositivo."</string>
diff --git a/service/res/values-gu/strings.xml b/service/res/values-gu/strings.xml
index 634199e..facd842 100644
--- a/service/res/values-gu/strings.xml
+++ b/service/res/values-gu/strings.xml
@@ -31,18 +31,18 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> સૂચવેલા નેટવર્ક. ડિવાઇસ ઑટોમૅટિક રીતે કનેક્ટ થાય તેમ બની શકે છે."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"મંજૂરી આપો"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ના, આભાર"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ઑટોમૅટિક રીતે કનેક્ટ કરવા માગે છે"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"આ નેટવર્કને અજોડ ID મળે છે કે જેનો ઉપયોગ ડિવાઇસના સ્થાનને ટ્રૅક કરવા માટે થઈ શકે છે"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"કોઈપણ રીતે કનેક્ટ કરો"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> વાઇ-ફાઇ સાથે કનેક્ટ કરીએ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"આ બધા નેટવર્કને સિમ ID મળે છે કે જેનો ઉપયોગ ડિવાઇસના સ્થાનને ટ્રૅક કરવા માટે થઈ શકે છે"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"કનેક્ટ કરો"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"કનેક્ટ કરશો નહીં"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"કનેક્શનને કન્ફર્મ કરીએ?"</string>
     <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-hi/strings.xml b/service/res/values-hi/strings.xml
index 05c9b68..dabcd3e 100644
--- a/service/res/values-hi/strings.xml
+++ b/service/res/values-hi/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> के सुझाए गए नेटवर्क. डिवाइस अपने आप कनेक्ट हो सकता है."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमति दें"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"रहने दें"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> अपने-आप कनेक्ट करना चाहता है"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"इन नेटवर्क को एक विशेष आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"फिर भी कनेक्ट करें"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> वाई-फ़ाई से कनेक्ट करना चाहते हैं?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"इन नेटवर्क को एक सिम आईडी दिया जाता है जिसका इस्तेमाल डिवाइस की जगह की जानकारी का पता लगाने के लिए किया जा सकता है"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट करें"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"कनेक्ट न करें"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"कनेक्शन की पुष्टि करना चाहते हैं?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"अगर आप कनेक्ट करते हैं, तो <xliff:g id="CARRIERNAME">%s</xliff:g> वाई-फ़ाई नेटवर्क आपकी सिम से जुड़े हुए विशेष आईडी को ऐक्सेस या शेयर कर सकता है. इससे आपके डिवाइस की जगह की जानकारी का पता लगा सकते हैं."</string>
diff --git a/service/res/values-hr/strings.xml b/service/res/values-hr/strings.xml
index 8ebbcad..1c5fa89 100644
--- a/service/res/values-hr/strings.xml
+++ b/service/res/values-hr/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mreže koje predlaže aplikacija <xliff:g id="NAME">%s</xliff:g>. Uređaji se mogu povezati automatski."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dopusti"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> se želi automatski povezati"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Te mreže primaju jedinstveni ID koji se može upotrijebiti za praćenje lokacije uređaja"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Svejedno poveži"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite li se povezati s Wi-Fijem mobilnog operatera <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ove mreže primaju ID SIM-a koji se može upotrijebiti za praćenje lokacije uređaja"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nemoj povezati"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite li potvrditi povezivanje?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ako se povežete, Wifi mreže operatera <xliff:g id="CARRIERNAME">%s</xliff:g> mogu pristupiti jedinstvenom ID-ju povezanom s vašim SIM-om ili ga podijeliti. To može omogućiti praćenje lokacije vašeg uređaja."</string>
diff --git a/service/res/values-hu/strings.xml b/service/res/values-hu/strings.xml
index 92260fc..a8e562b 100644
--- a/service/res/values-hu/strings.xml
+++ b/service/res/values-hu/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"A(z) <xliff:g id="NAME">%s</xliff:g> hálózatokat javasolt. Az eszköz automatikusan csatlakozhat hozzájuk."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Engedélyezés"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nem, köszönöm"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"A(z) <xliff:g id="CARRIERNAME">%s</xliff:g> automatikusan csatlakozni szeretne"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ezek a hálózatok egyedi azonosítót kapnak, amelyek az eszköz helyadatainak követésére használhatók"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Csatlakozás mindenképp"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Csatlakozni szeretne a(z) <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi-hálózathoz?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ezek a hálózatok SIM-azonosítót kapnak, amely felhasználható az eszköz helyadatainak követésére"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Csatlakozás"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne csatlakozzon"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Biztosan csatlakozik?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ha csatlakozik, a(z) <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi-hálózatai hozzáférhetnek a SIM-hez társított egyedi azonosítóhoz, amelyet meg is oszthatnak. Ez lehetővé teheti eszköze helyadatainak követését."</string>
diff --git a/service/res/values-hy/strings.xml b/service/res/values-hy/strings.xml
index 9dea80e..3e60ba0 100644
--- a/service/res/values-hy/strings.xml
+++ b/service/res/values-hy/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> հավելվածի առաջարկվող ցանցեր: Սարքը կարող է ավտոմատ միանալ:"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Թույլատրել"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ոչ, շնորհակալություն"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>-ը հայցում է ավտոմատ միանալու թույլտվություն"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Այս ցանցերը ստանում են եզակի ID, որը կարող է օգտագործվել սարքի տեղադրությունը հետագծելու համար։"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Միանալ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Միանա՞լ <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi ցանցին"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Այս ցանցերը ստանում են SIM քարտի ID, որը կարող է օգտագործվել սարքի տեղադրությունը հետագծելու համար։"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Միանալ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Չմիանալ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Հաստատե՞լ միացումը"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Միանալու դեպքում <xliff:g id="CARRIERNAME">%s</xliff:g>-ի Wi‑Fi ցանցերը կարող են ստանալ ձեր SIM քարտի հետ կապված եզակի ID-ն կամ կիսվել դրանով։ Դա հնարավորություն կտա հետագծել ձեր սարքի տեղադրությունը։"</string>
@@ -57,11 +57,11 @@
     <string name="wifi_p2p_from_message" msgid="3857436922001981191">"Ուղարկող`"</string>
     <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_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="dlg_ok" msgid="3250085870426030310">"Հաստատել"</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>
     <string name="wifi_disable_mac_randomization_dialog_title" msgid="7200723795776228456">"Փոխե՞լ գաղտնիության կարգավորումը"</string>
diff --git a/service/res/values-in/strings.xml b/service/res/values-in/strings.xml
index cfe9254..70fd8af 100644
--- a/service/res/values-in/strings.xml
+++ b/service/res/values-in/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Jaringan yang disarankan <xliff:g id="NAME">%s</xliff:g>. Perangkat dapat terhubung secara otomatis."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Izinkan"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Lain kali"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ingin terhubung otomatis"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Jaringan berikut menerima ID unik yang dapat digunakan untuk melacak lokasi perangkat"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Tetap hubungkan"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Hubungkan ke Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Jaringan ini menerima ID SIM yang dapat digunakan untuk melacak lokasi perangkat"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Hubungkan"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Jangan hubungkan"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Konfirmasi koneksi?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jika Anda menghubungkan, jaringan Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> mungkin mengakses atau membagikan ID unik terkait dengan SIM Anda. Ini memungkinkan lokasi perangkat Anda untuk dilacak."</string>
diff --git a/service/res/values-is/strings.xml b/service/res/values-is/strings.xml
index 28819cc..c60e883 100644
--- a/service/res/values-is/strings.xml
+++ b/service/res/values-is/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> kom með tillögur að netkerfum. Tækið gæti tengst sjálfkrafa."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Leyfa"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nei, takk"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vill tengjast sjálfkrafa"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Þessi net fá einkvæmt auðkenni sem hægt er að nota til að rekja staðsetningu tækisins"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Tengjast samt"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Tengjast við <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Þessi net fá SIM-auðkenni sem hægt er að nota til að rekja staðsetningu tækisins"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Tengja"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ekki tengjast"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Staðfesta tengingu?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ef þú tengist geta Wi-Fi net <xliff:g id="CARRIERNAME">%s</xliff:g> fengið aðgang að eða deilt einkvæmu auðkenni sem er tengt SIM-kortinu þínu. Með þessu er hugsanlega hægt að rekja staðsetningu tækisins þíns."</string>
diff --git a/service/res/values-it/strings.xml b/service/res/values-it/strings.xml
index 84240d7..f675f7e 100644
--- a/service/res/values-it/strings.xml
+++ b/service/res/values-it/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ha suggerito delle reti. Il dispositivo potrebbe collegarsi automaticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Consenti"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"No, grazie"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vuole connettersi automaticamente"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Queste reti ricevono un ID univoco che può essere usato per monitorare la posizione del dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Connetti comunque"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vuoi connetterti alla rete Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Queste reti ricevono un ID SIM che può essere usato per monitorare la posizione del dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Connetti"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Non connettere"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confermi la connessione?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se esegui la connessione, le reti Wi-Fi di <xliff:g id="CARRIERNAME">%s</xliff:g> potranno accedere o condividere un ID univoco associato alla tua SIM. Questa azione potrebbe consentire il monitoraggio della posizione del tuo dispositivo."</string>
diff --git a/service/res/values-iw/strings.xml b/service/res/values-iw/strings.xml
index 51e0432..ad8fc46 100644
--- a/service/res/values-iw/strings.xml
+++ b/service/res/values-iw/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"הצעות לרשתות <xliff:g id="NAME">%s</xliff:g>. ייתכן שחיבור המכשיר ייעשה באופן אוטומטי."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"אישור"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"לא תודה"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> רוצה להתחבר אוטומטית"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"רשתות אלה מקבלות מזהה ייחודי שבו ניתן להשתמש למעקב אחר מיקום של מכשיר"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"יש להתחבר בכל זאת"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"‏האם להתחבר ל-Wi-Fi של <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"‏רשתות אלה מקבלות מזהה SIM שיכול לשמש למעקב אחר מיקום של מכשיר"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"חיבור"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"אין להתחבר"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"לאשר את ההתחברות?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"‏אם תתבצע התחברות, ייתכן שרשתות Wi‑Fi של <xliff:g id="CARRIERNAME">%s</xliff:g> יקבלו גישה או ישתפו מזהה ייחודי שמשויך לכרטיס ה-SUM שלך. בעקבות זאת, ייתכן שניתן יהיה לעקוב אחר מיקום המכשיר שלך."</string>
@@ -77,7 +77,7 @@
     <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"‏<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32764 באימות EAP"</string>
     <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"‏<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32765 באימות EAP"</string>
     <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"‏<xliff:g id="SSID">%1$s</xliff:g> : שגיאה 32766 באימות EAP"</string>
-    <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"נקודה לשיתוף אינטרנט נכבתה"</string>
+    <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"‏נקודת האינטרנט (hotspot) נכבתה"</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_message" msgid="6085636103482409595">"‏יש להכניס SIM של <xliff:g id="CARRIER_NAME">%2$s</xliff:g> כדי להתחבר אל <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/res/values-ja/strings.xml b/service/res/values-ja/strings.xml
index 95be7fa..e494dbd 100644
--- a/service/res/values-ja/strings.xml
+++ b/service/res/values-ja/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> からのネットワーク候補に、デバイスが自動的に接続される可能性があります。"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"許可"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"許可しない"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> が自動接続をリクエストしています"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"これらのネットワークは一意の ID を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"接続する"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> のWi-Fi に接続しますか?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"これらのネットワークは SIM ID を受信します。この ID を使ってデバイスの位置情報が追跡される可能性があります"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"接続"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"接続しない"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"接続を確認しますか?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"接続すると、<xliff:g id="CARRIERNAME">%s</xliff:g> の Wi‑Fi ネットワークが、SIM に関連付けられている一意の ID にアクセスしたりその ID を共有したりする可能性があります。これにより、デバイスの位置情報が追跡される可能性もあります。"</string>
diff --git a/service/res/values-ka/strings.xml b/service/res/values-ka/strings.xml
index 83d9b78..7e12bcc 100644
--- a/service/res/values-ka/strings.xml
+++ b/service/res/values-ka/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> შემოთავაზებული ქსელები. მოწყობილობა შეიძლება ავტომატურად დაუკავშირდეს."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"დაშვება"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"არა, გმადლობთ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>-ს ავტომატურად დაკავშირება სურს"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ეს ქსელები იღებს უნიკალურ ID-ს, რომლის მეშვეობითაც შესაძლებელია მოწყობილობის მდებარეობის აღნუსხვა"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"მაინც დაკავშირება"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"დაუკავშირდებით <xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi-ს?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ეს ქსელები მიიღებს SIM-ის ID-ს, რომლის მეშვეობითაც შესაძლებელია მოწყობილობის მდებარეობაზე თვალის დევნება."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"დაკავშირება"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"არ დაუკავშირდეს"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"გსურთ, დაადასტუროთ დაკავშირება?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"დაკავშირების შემთხვევაში, <xliff:g id="CARRIERNAME">%s</xliff:g>-ის Wi‑Fi ქსელებმა შეიძლება წვდომა იქონიოს ან გააზიაროს უნიკალური ID, რომელიც თქვენს SIM-ბარათთან არის ასოცირებული. ამ ცვლილებამ შესაძლოა თქვენი მოწყობილობის მდებარეობა აღნუსხვადი გახადოს."</string>
diff --git a/service/res/values-kk/strings.xml b/service/res/values-kk/strings.xml
index 5df34c1..0b7a573 100644
--- a/service/res/values-kk/strings.xml
+++ b/service/res/values-kk/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ұсынған желілер. Құрылғы автоматты түрде қосылуы мүмкін."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Рұқсат беру"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Жоқ, рақмет"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> автоматты түрде қосылғысы келеді"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Бұл желілер бірегей идентификатор алады, оны құрылғының орналасқан жерін бақылау үшін қолдануға болады."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Бәрібір қосылу"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> қызметі Wi‑Fi желісімен байланыстырылсын ба?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Бұл желілер SIM идентификаторын алады, оны құрылғының орналасқан жерін бақылау үшін қолдануға болады."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Байланыстыру"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Қосылмау"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Қосылымды растайсыз ба?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Егер қосылсаңыз, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi желілері SIM картаңызға байланыстырылған бірегей идентификаторды пайдалана немесе бөлісе алады. Оның көмегімен құрылғыңыздың орнын қадағалауға болады."</string>
diff --git a/service/res/values-km/strings.xml b/service/res/values-km/strings.xml
index 143d9fd..3a0c18b 100644
--- a/service/res/values-km/strings.xml
+++ b/service/res/values-km/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"បណ្ដាញ​ដែលបាន​ណែនាំ​របស់ <xliff:g id="NAME">%s</xliff:g> ។ ឧបករណ៍​អាច​ភ្ជាប់​ដោយស្វ័យប្រវត្តិ។"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"អនុញ្ញាត"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ទេ អរគុណ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ចង់​ភ្ជាប់​ដោយស្វ័យប្រវត្តិ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"បណ្ដាញ​ទាំងនេះ​ទទួលបាន​លេខសម្គាល់​ពិសេស ដែល​អាចប្រើ​ដើម្បី​តាមដាន​ទីតាំង​ឧបករណ៍"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"មិនអីទេ ភ្ជាប់ចុះ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ភ្ជាប់ Wi-Fi របស់ <xliff:g id="CARRIERNAME">%s</xliff:g> ឬ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"បណ្ដាញ​ទាំងនេះ​ទទួលបាន​លេខសម្គាល់ស៊ីម ដែល​អាចប្រើ​ដើម្បី​តាមដាន​ទីតាំង​ឧបករណ៍"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ភ្ជាប់"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"កុំ​ភ្ជាប់"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"បញ្ជាក់​ការតភ្ជាប់​ដែរទេ​?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ប្រសិនបើ​អ្នក​ភ្ជាប់ នោះបណ្ដាញ Wi-Fi របស់ <xliff:g id="CARRIERNAME">%s</xliff:g> អាច​ចូលប្រើ ឬ​ចែករំលែក​លេខសម្គាល់​ពិសេស​ដែលភ្ជាប់​ជាមួយ​ស៊ីម​របស់អ្នក​។ សកម្មភាពនេះ​អាច​អនុញ្ញាតឱ្យមាន​ការតាមដាន​ទីតាំង​ឧបករណ៍​របស់អ្នក​។"</string>
diff --git a/service/res/values-kn/strings.xml b/service/res/values-kn/strings.xml
index 0e72fee..a313417 100644
--- a/service/res/values-kn/strings.xml
+++ b/service/res/values-kn/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ಸೂಚಿಸಿರುವ ನೆಟ್‌ವರ್ಕ್‌ಗಳು. ಸಾಧನಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಗೊಳ್ಳಬಹುದು."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ಅನುಮತಿಸಿ"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ಬೇಡ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>, ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲು ಬಯಸುತ್ತದೆ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ ಅನನ್ಯ ಐಡಿಯನ್ನು ಈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಸ್ವೀಕರಿಸುತ್ತವೆ"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ಹೇಗಿದ್ದರೂ ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ವೈ-ಫೈ ಗೆ ಕನೆಕ್ಟ್ ಮಾಡುವುದೇ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ SIM ಐಡಿಯನ್ನು ಈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಸ್ವೀಕರಿಸುತ್ತವೆ"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ಕನೆಕ್ಟ್ ಮಾಡಬೇಡಿ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ಕನೆಕ್ಷನ್ ಅನ್ನು ಖಚಿತಪಡಿಸಬೇಕೇ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ನೀವು ಕನೆಕ್ಟ್ ಮಾಡಿದರೆ, <xliff:g id="CARRIERNAME">%s</xliff:g> ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ನಿಮ್ಮ SIM ಗೆ ಸಂಬಂಧಿಸಿದ ಅನನ್ಯ ಐಡಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಬಹುದು ಅಥವಾ ಅದನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು. ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಇದು ಅವಕಾಶ ನೀಡಬಹುದು."</string>
diff --git a/service/res/values-ko/strings.xml b/service/res/values-ko/strings.xml
index 28f7350..4fbca69 100644
--- a/service/res/values-ko/strings.xml
+++ b/service/res/values-ko/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>에서 네트워크를 제안했습니다. 기기가 자동으로 연결될 수 있습니다."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"허용"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"허용 안함"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>에서 자동 연결을 사용하려고 합니다"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"이 네트워크는 기기 위치를 추적하는 데 사용할 수 있는 고유 ID를 수신합니다."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"무시하고 연결하기"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi에 연결하시겠습니까?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"이 네트워크는 기기 위치 추적에 사용할 수 있는 SIM ID를 수신합니다."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"연결"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"연결 안 함"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"연결하시겠습니까?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"연결하면 <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi 네트워크에서 SIM과 연결된 고유 ID에 액세스하거나 고유 ID를 공유할 수 있습니다. 이 경우 내 기기의 위치를 추적할 수도 있습니다."</string>
diff --git a/service/res/values-ky/strings.xml b/service/res/values-ky/strings.xml
index 873d475..4f3aaba 100644
--- a/service/res/values-ky/strings.xml
+++ b/service/res/values-ky/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> сунуштаган тармактар. Түзмөк автоматтык түрдө туташышы мүмкүн."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Уруксат берүү"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Жок, рахмат"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> байланыш оператору автоматтык түрдө туташкысы келип жатат"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Бул тармактарга өзгөчө идентификатор берилип, анын жардамы менен түзмөктүн жайгашкан жерин аныктоого болот"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Баары бир туташуу"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi тармагына туташтырылсынбы?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Бул тармактарга SIM-картанын идентификатору берилип, анын жардамы менен түзмөктүн жайгашкан жерин аныктоого болот"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Туташуу"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Туташпасын"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Туташууну ырастайсызбы?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Туташсаңыз, <xliff:g id="CARRIERNAME">%s</xliff:g> операторунун Wi‑Fi тармактары SIM картаңызга байланышкан өзгөчө идентификаторго мүмкүнчүлүк алып, аны башкалар менен бөлүшө алат. Ушуну менен, түзмөгүңүздүн жайгашкан жерин аныктай аласыз."</string>
diff --git a/service/res/values-lo/strings.xml b/service/res/values-lo/strings.xml
index 8b6adf7..dbe5efb 100644
--- a/service/res/values-lo/strings.xml
+++ b/service/res/values-lo/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"ເຄືອຂ່າຍ <xliff:g id="NAME">%s</xliff:g> ທີ່ແນະນຳ. ອຸປະກອນອາດເຊື່ອມຕໍ່ເອງໂດຍອັດຕະໂນມັດ."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ອະນຸຍາດ"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ບໍ່, ຂອບໃຈ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ຕ້ອງການເຊື່ອມຕໍ່ອັດຕະໂນມັດ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ເຄືອຂ່າຍເຫຼົ່ານີ້ຈະໄດ້ຮັບ unique ID ທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນໄດ້"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ຢືນຢັນການເຊື່ອມຕໍ່"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ເຊື່ອມຕໍ່ກັບ Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ບໍ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ເຄືອຂ່າຍເຫຼົ່ານີ້ຈະໄດ້ຮັບ ID ຊິມທີ່ສາມາດໃຊ້ເພື່ອຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນໄດ້"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ເຊື່ອມຕໍ່"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ຢ່າເຊື່ອມຕໍ່"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ຢືນຢັນການເຊື່ອມຕໍ່ບໍ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ຫາກທ່ານເຊື່ອມຕໍ່, ເຄືອຂ່າຍ Wi-Fi ຂອງ <xliff:g id="CARRIERNAME">%s</xliff:g> ຈະສາມາດເຂົ້າເຖິງ ແລະ ແບ່ງປັນ unique ID ທີ່ເຊື່ອມໂຍງກັບຊິມຂອງທ່ານໄດ້. ນີ້ອາດເຮັດໃຫ້ສາມາດຕິດຕາມສະຖານທີ່ຂອງອຸປະກອນທ່ານໄດ້."</string>
diff --git a/service/res/values-lt/strings.xml b/service/res/values-lt/strings.xml
index f9617a4..3d6a667 100644
--- a/service/res/values-lt/strings.xml
+++ b/service/res/values-lt/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"„<xliff:g id="NAME">%s</xliff:g>“ siūlomi tinklai. Įrenginys gali prisijungti automatiškai."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Leisti"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, ačiū"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"„<xliff:g id="CARRIERNAME">%s</xliff:g>“ nori prijungti automatiškai"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Šie tinklai gauna unikalų ID, kurį galima naudoti įrenginio vietovei stebėti"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Vis tiek prisijungti"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Prisijungti prie „<xliff:g id="CARRIERNAME">%s</xliff:g>“ „Wi-Fi“?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Šie tinklai gauna SIM kortelės ID, kurį galima naudoti įrenginio vietovei stebėti"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Prisijungti"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nesprisijungti"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Patvirtinti prijungimą?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Prisijungus „<xliff:g id="CARRIERNAME">%s</xliff:g>“ teikiami „Wi‑Fi“ tinklai gali pasiekti ar bendrinti su jūsų SIM susietą unikalų ID. Gali būti, kad jūsų įrenginio vieta bus stebima."</string>
diff --git a/service/res/values-lv/strings.xml b/service/res/values-lv/strings.xml
index 6c00359..c8d1865 100644
--- a/service/res/values-lv/strings.xml
+++ b/service/res/values-lv/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Lietotnes <xliff:g id="NAME">%s</xliff:g> ieteiktie tīkli. Ierīcē var tikt automātiski izveidots savienojums."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Atļaut"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nē, paldies"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vēlas automātiski izveidot savienojumu"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Šie tīkli saņem unikālo ID, ko var izmantot, lai izsekotu ierīces atrašanās vietu"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Tik un tā izveidot savienojumu"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vai izveidot savienojumu ar <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Šie tīkli saņem SIM ID, ko var izmantot, lai izsekotu ierīces atrašanās vietu."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Izveidot savienojumu"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Neizveidot savienojumu"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vai apstiprināt savienojumu?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ja izveidosiet savienojumu, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi tīkli varēs piekļūt unikālajam ID, kas saistīts ar jūsu SIM, vai kopīgot to. Tādējādi varēs tikt izsekota jūsu ierīces atrašanās vieta."</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-en-rXC/strings.xml b/service/res/values-mcc310-mnc004-en-rXC/strings.xml
deleted file mode 100644
index cf47a17..0000000
--- a/service/res/values-mcc310-mnc004-en-rXC/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<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>‎‏‎‎‏‏‏‎ : You can’t connect to Verizon Wi-Fi Access from outside the Verizon coverage area.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : You are not subscribed to Verizon Wi-Fi Access. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : You are already connected to Verizon Wi-Fi Access.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem connecting you to Verizon Wi-Fi Access. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem with your Verizon Wi-Fi Access account. Please call us at 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 is not available from your location. Try again later or try from a different location.‎‏‎‎‏‎"</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-mcc310-mnc004-ta/strings.xml b/service/res/values-mcc310-mnc004-ta/strings.xml
index 516a527..9dacf26 100644
--- a/service/res/values-mcc310-mnc004-ta/strings.xml
+++ b/service/res/values-mcc310-mnc004-ta/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 கவரேஜ் பகுதியைத் தாண்டி Verizon Wi-Fi Accessஸுடன் இணைக்க முடியாது."</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 கவரேஜ் பகுதியைத் தாண்டி Verizon வைஃபை Accessஸுடன் இணைக்க முடியாது."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : நீங்கள் Verizon வைஃபை Accessஸிற்கு சந்தா செய்யவில்லை. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் ஏற்கெனவே இணைப்பில் உள்ளீர்கள்."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் இணைப்பதில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் பகுதிக்கு Verizon வைஃபை 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-en-rXC/strings.xml b/service/res/values-mcc311-mnc480-en-rXC/strings.xml
deleted file mode 100644
index 78f4922..0000000
--- a/service/res/values-mcc311-mnc480-en-rXC/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<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>‎‏‎‎‏‏‏‎ : You can’t connect to Verizon Wi-Fi Access from outside the Verizon coverage area.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : You are not subscribed to Verizon Wi-Fi Access. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem with your Verizon Wi-Fi Access account. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : You are already connected to Verizon Wi-Fi Access.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem connecting you to Verizon Wi-Fi Access. Please call us at 800-922-0204.‎‏‎‎‏‎"</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎ : There is a problem with your Verizon Wi-Fi Access account. Please call us at 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 is not available from your location. Try again later or try from a different location.‎‏‎‎‏‎"</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-mcc311-mnc480-ta/strings.xml b/service/res/values-mcc311-mnc480-ta/strings.xml
index 379eeac..79239ef 100644
--- a/service/res/values-mcc311-mnc480-ta/strings.xml
+++ b/service/res/values-mcc311-mnc480-ta/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 கவரேஜ் பகுதியைத் தாண்டி Verizon Wi-Fi Accessஸுடன் இணைக்க முடியாது."</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 கவரேஜ் பகுதியைத் தாண்டி Verizon வைஃபை Accessஸுடன் இணைக்க முடியாது."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : நீங்கள் Verizon வைஃபை Accessஸிற்கு சந்தா செய்யவில்லை. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் ஏற்கெனவே இணைப்பில் உள்ளீர்கள்."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon வைஃபை Accessஸுடன் இணைப்பதில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் Verizon வைஃபை Access கணக்கில் சிக்கல் உள்ளது. 800-922-0204 என்ற எண்ணில் எங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : உங்கள் பகுதிக்கு Verizon வைஃபை Access சேவை கிடைக்கவில்லை. மீண்டும் முயலவும் அல்லது வேறு இருப்பிடத்தில் இருந்து முயலவும்."</string>
 </resources>
diff --git a/service/res/values-mk/strings.xml b/service/res/values-mk/strings.xml
index 1852f52..836a823 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>
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Предложени мрежи од <xliff:g id="NAME">%s</xliff:g>. Уредот може да се поврзе автоматски."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволи"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, фала"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> сака автоматски да се поврзе"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Мреживе примаат уникатен ID што може да се користи за следење на локацијата на уредот"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Сепак поврзи се"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Да се поврзе на Wi-Fi на <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Мреживе примаат уникатен ID на SIM што може да се користи за следење на локацијата на уредот"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Поврзи"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не поврзувај"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Да се потврди врската?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се поврзете, Wi‑Fi мрежите на <xliff:g id="CARRIERNAME">%s</xliff:g> може да имаат пристап до уникатен ID поврзан со вашата SIM-картичка или да го споделуваат. Ова може да овозможи следење на локацијата на вашиот уред."</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-ml/strings.xml b/service/res/values-ml/strings.xml
index 2e927f1..648d760 100644
--- a/service/res/values-ml/strings.xml
+++ b/service/res/values-ml/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> നിർദ്ദേശിച്ച നെറ്റ്‌വർക്കുകൾ. ഉപകരണം സ്വയമേവ കണക്‌റ്റ് ചെയ്‌തേക്കാം."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"അനുവദിക്കുക"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"വേണ്ട"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> സ്വയമേവ കണക്റ്റ് ചെയ്യാൻ താൽപ്പര്യപ്പെടുന്നു"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന തനത് ഐഡി ഈ നെറ്റ്‌വർക്കുകൾക്ക് ലഭിക്കും"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"എന്തായാലും കണക്‌റ്റ് ചെയ്യുക"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> വൈഫൈയിൽ കണക്റ്റ് ചെയ്യണോ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഉപയോഗിക്കാവുന്ന സിം ഐഡി ഈ നെറ്റ്‌വർക്കുകൾക്ക് ലഭിക്കും"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"കണക്‌റ്റ് ചെയ്യുക"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"കണക്റ്റ് ചെയ്യരുത്"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"കണക്ഷൻ സ്ഥിരീകരിക്കണോ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"നിങ്ങൾ കണക്റ്റ് ചെയ്യുകയാണെങ്കിൽ, സിമ്മുമായി ബന്ധപ്പെട്ട തനത് ഐഡി <xliff:g id="CARRIERNAME">%s</xliff:g> വൈഫൈ നെറ്റ്‌വർക്കുകൾ ആക്സസ് ചെയ്യുകയോ പങ്കിടുകയോ ചെയ്തേക്കാം. നിങ്ങളുടെ ഉപകരണ ലൊക്കേഷൻ ട്രാക്ക് ചെയ്യാൻ ഇത് അനുവദിച്ചേക്കാം."</string>
diff --git a/service/res/values-mn/strings.xml b/service/res/values-mn/strings.xml
index 9cacf88..691c9d1 100644
--- a/service/res/values-mn/strings.xml
+++ b/service/res/values-mn/strings.xml
@@ -31,12 +31,12 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> сүлжээ санал болголоо. Төхөөрөмж автоматаар холбогдож магадгүй."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Зөвшөөрөх"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Үгүй, баярлалаа"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> нь автоматаар холбогдох хүсэлтэй байна"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Эдгээр сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой цор ганц дугаарыг хүлээн авдаг"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ямар ч тохиолдолд холбогдох"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g>-н Wi‑Fi-д холбоогдох уу?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Эдгээр сүлжээ нь төхөөрөмжийн байршлыг тандахад ашиглах боломжтой SIM ID-г хүлээн авдаг"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Холбогдох"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Битгий холбогд"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Холболтыг баталгаажуулах уу?"</string>
-    <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Хэрэв та холбогдвол <xliff:g id="CARRIERNAME">%s</xliff:g>-н Wi‑Fi сүлжээ нь таны СИМ-тэй холбоотой цор ганц дугаарт хандаж эсвэл түүнийг хуваалцаж болзошгүй. Энэ нь таны төхөөрөмжийн байршлыг тандахыг зөвшөөрч болзошгүй."</string>
+    <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Хэрэв та холбогдвол <xliff:g id="CARRIERNAME">%s</xliff:g>-н Wi‑Fi сүлжээ нь таны SIM-тэй холбоотой цор ганц дугаарт хандаж эсвэл түүнийг хуваалцаж болзошгүй. Энэ нь таны төхөөрөмжийн байршлыг тандахыг зөвшөөрч болзошгүй."</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">"Wi‑Fi автоматаар асна"</string>
@@ -80,5 +80,5 @@
     <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">"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> СИМ-г хийнэ үү"</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-mr/strings.xml b/service/res/values-mr/strings.xml
index e34c664..3612227 100644
--- a/service/res/values-mr/strings.xml
+++ b/service/res/values-mr/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> सुचवलेली नेटवर्क. डिव्हाइस आपोआप कनेक्ट होऊ शकते."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमती द्या"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"नाही, नको"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ला ऑटो‑कनेक्ट करायचे आहे"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"या नेटवर्कना एक युनिक आयडी मिळतो जो डिव्हाइस स्थानाचा मागोवा घेण्यासाठी वापरला जाऊ शकतो"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"तरीही कनेक्ट करा"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> वाय-फायशी कनेक्ट करायचे आहे का?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"या नेटवर्कना एक सिम आयडी मिळतो जो डिव्हाइस स्थानाचा माग ठेवण्यासाठी वापरला जाऊ शकतो"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट करा"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"कनेक्ट करू नका"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"कनेक्शन निश्चित करायचे आहे का?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"तुम्ही कनेक्ट केल्यास, <xliff:g id="CARRIERNAME">%s</xliff:g> वाय-फाय नेटवर्क तुमच्या सिम शी संबंधित एक युनिक आयडी अ‍ॅक्सेस किंवा शेअर करू शकतात. यामुळे तुमच्या डिव्हाइस स्थानाचा मागोवा घेतला जाऊ शकतो."</string>
diff --git a/service/res/values-ms/strings.xml b/service/res/values-ms/strings.xml
index 76f7b4f..0ecdb4f 100644
--- a/service/res/values-ms/strings.xml
+++ b/service/res/values-ms/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rangkaian yang dicadangkan oleh <xliff:g id="NAME">%s</xliff:g>. Peranti mungkin disambungkan secara automatik."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Benarkan"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Tidak perlu"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> mahu membuat autosambungan"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Rangkaian ini memerlukan ID unit yang boleh digunakan untuk menjejaki lokasi peranti."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Sambungkan juga"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Sambung ke Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Rangkaian ini menerima ID SIM yang boleh digunakan untuk menjejaki lokasi peranti"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Sambung"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Jangan sambung"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Sahkan sambungan?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jika anda bersambung, rangkaian Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> mungkin mengakses atau berkongsi ID unik yang dikaitkan dengan SIM anda. Hal ini mungkin membenarkan lokasi peranti anda dijejaki."</string>
diff --git a/service/res/values-my/strings.xml b/service/res/values-my/strings.xml
index f46860c..d88c369 100644
--- a/service/res/values-my/strings.xml
+++ b/service/res/values-my/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> သည် ကွန်ရက်များကို အကြံပြုထားသည်။ စက်သည် အလိုအလျောက် ချိတ်ဆက်နိုင်သည်။"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ခွင့်ပြုရန်"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"မလိုပါ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> က အလိုအလျောက် ချိတ်ဆက်လိုသည်"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ဤကွန်ရက်များက စက်တည်နေရာကို ခြေရာခံရန် အသုံးပြုနိုင်သည့် သီးသန့် ID ကို ရရှိပါသည်"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန်"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi သို့ ချိတ်ဆက်မလား။"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ဤကွန်ရက်များက စက်တည်နေရာကို ခြေရာခံရန် အသုံးပြုနိုင်သည့် SIM ID တစ်ခုကို ရရှိပါသည်"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ချိတ်ဆက်ပါ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"မချိတ်ဆက်ပါနှင့်"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ချိတ်ဆက်မှု အတည်ပြုမလား။"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"သင်ချိတ်ဆက်ပါက <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi ကွန်ရက်များက သင့်ဆင်းမ်ကတ်နှင့် ဆက်စပ်နေသည့် သီးသန့် ID ကို သုံးခြင်း သို့မဟုတ် မျှဝေခြင်းတို့ ပြုလုပ်နိုင်သည်။ ၎င်းက သင့်စက်၏တည်နေရာကို ခြေရာခံခွင့် ပြုနိုင်သည်။"</string>
diff --git a/service/res/values-nb/strings.xml b/service/res/values-nb/strings.xml
index ea826c1..898d50a 100644
--- a/service/res/values-nb/strings.xml
+++ b/service/res/values-nb/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>-foreslåtte nettverk. Enheten kan koble til automatisk."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillat"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nei takk"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vil koble til automatisk"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Disse nettverkene mottar en unik ID som kan brukes til å spore enhetsposisjonen"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Koble til likevel"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vil du koble til <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi-Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Disse nettverkene mottar en SIM-ID som kan brukes til å spore enhetsposisjonen"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Koble til"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ikke koble til"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vil du bekrefte tilkoblingen?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Hvis du kobler til, kan <xliff:g id="CARRIERNAME">%s</xliff:g>-Wi‑Fi-nettverk få tilgang til eller dele en unik ID som er knyttet til SIM-kortet ditt. Dette gjør at enhetens posisjon kan spores."</string>
diff --git a/service/res/values-ne/strings.xml b/service/res/values-ne/strings.xml
index 9315db3..9b2aec5 100644
--- a/service/res/values-ne/strings.xml
+++ b/service/res/values-ne/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ले सिफारिस गरेका नेटवर्कहरू। यन्त्र स्वतः जडान हुन सक्छ।"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"अनुमति दिनुहोस्"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"पर्दैन, धन्यवाद"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> स्वतः जोडिन चाहन्छ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"यी नेटवर्कहरूले यन्त्रको स्थान पहिल्याउन प्रयोग गर्न सकिने एउटा अद्वित्तीय ID प्राप्त गर्छन्"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"जे भए पनि पनि जोड्नुहोस्"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi मा कनेक्ट गर्ने हो?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"यी नेटवर्कहरूलाई यन्त्रको स्थान पहिल्याउन प्रयोग गर्न मिल्ने एउटा अद्वितीय SIM कार्ड ID उपलब्ध गराइन्छ"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"कनेक्ट गर्नुहोस्"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"नजोड्नुहोस्"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"जोडिने हो?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"तपाईं जोडिनुभयो भने <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi नेटवर्कहरूले तपाईंको SIM सँग सम्बद्ध अद्वित्तीय ID प्रयोग गर्न वा उक्त ID आदान प्रदान गर्न सक्छ। उक्त ID प्रयोग गरी तपाईंको यन्त्रको स्थान पहिल्याउन सकिन्छ।"</string>
diff --git a/service/res/values-nl/strings.xml b/service/res/values-nl/strings.xml
index 8c79433..1baa7ff 100644
--- a/service/res/values-nl/strings.xml
+++ b/service/res/values-nl/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> heeft netwerken voorgesteld. Apparaat kan automatisch verbinding maken."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Toestaan"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nee, bedankt"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> wil automatisch verbinding maken"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Deze netwerken ontvangen een unieke ID die kan worden gebruikt om de apparaatlocatie bij te houden"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Toch verbinding maken"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Verbinding maken met wifi van <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Deze netwerken ontvangen een simkaart-ID die kan worden gebruikt om de apparaatlocatie bij te houden"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Verbinding maken"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Geen verbinding maken"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Verbinding bevestigen?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Als je verbinding maakt, hebben de wifi-netwerken van <xliff:g id="CARRIERNAME">%s</xliff:g> mogelijk toegang tot de unieke ID die aan je simkaart is gekoppeld of kunnen ze deze delen. Op deze manier kan de locatie van je apparaat worden bijgehouden."</string>
diff --git a/service/res/values-or/strings.xml b/service/res/values-or/strings.xml
index 4212759..c1150ae 100644
--- a/service/res/values-or/strings.xml
+++ b/service/res/values-or/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ପ୍ରସ୍ତାବିତ ନେଟ୍‌ୱାର୍କଗୁଡ଼ିକ। ଡିଭାଇସ୍ ହୁଏତ ସ୍ୱଚାଳିତ ଭାବେ ସଂଯୋଗ ହୋଇପାରେ।"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ନାହିଁ, ଥାଉ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ସ୍ୱତଃ-ସଂଯୋଗ କରିବାକୁ ଚାହେଁ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ଏହି ନେଟୱାର୍କଗୁଡ଼ିକ ଏକ ସ୍ଵତନ୍ତ୍ର ID ପାଇଥାଏ ଯାହାକୁ ଡିଭାଇସର ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାକୁ ବ୍ୟବହାର କରାଯାଇପାରେ"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ଯେ କୌଣସି ମତେ ସଂଯୋଗ କରନ୍ତୁ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> ୱାଇ-ଫାଇ ସହ ସଂଯୋଗ କରିବେ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ଏହି ନେଟୱାର୍କଗୁଡ଼ିକ ଏକ SIM ID ପ୍ରାପ୍ତ କରେ ଯାହା ଡିଭାଇସର ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାରେ ବ୍ୟବହାର କରାଯାଇପାରିବ"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ସଂଯୋଗ କରନ୍ତୁ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ସଂଯୋଗ କରନ୍ତୁ ନାହିଁ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ସଂଯୋଗ ସୁନିଶ୍ଚିତ କରିବେ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ଯଦି ଆପଣ ସଂଯୋଗ କରିବେ, ତେବେ <xliff:g id="CARRIERNAME">%s</xliff:g> ୱାଇ-ଫାଇ ନେଟୱାର୍କଗୁଡ଼ିକ ଆପଣଙ୍କ SIM ସମ୍ବନ୍ଧିତ ଏକ ସ୍ଵତନ୍ତ୍ର ID ଆକ୍ସେସ୍ କିମ୍ବା ସେୟାର୍ କରିପାରେ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ଟ୍ରାକ୍ କରିବାକୁ ଅନୁମତି ଦେଇପାରେ।"</string>
diff --git a/service/res/values-pa/strings.xml b/service/res/values-pa/strings.xml
index ee68453..e4e7c77 100644
--- a/service/res/values-pa/strings.xml
+++ b/service/res/values-pa/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> ਦੇ ਸੁਝਾਏ ਨੈੱਟਵਰਕ। ਸ਼ਾਇਦ ਡੀਵਾਈਸ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਵੇ।"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ਵਰਤਣ ਦਿਓ"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ਸਵੈ-ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਵਿਲੱਖਣ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦੇ ਹਨ ਜੋ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤੀ ਜਾ ਸਕਦੀ ਹੈ"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰੋ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"ਕੀ <xliff:g id="CARRIERNAME">%s</xliff:g> ਵਾਈ-ਫਾਈ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਹੈ?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"ਇਹ ਨੈੱਟਵਰਕ ਇੱਕ ਸਿਮ ਆਈਡੀ ਪ੍ਰਾਪਤ ਕਰਦੇ ਹਨ ਜਿਨ੍ਹਾਂ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਨੂੰ ਟਰੈਕ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"ਕਨੈਕਟ ਕਰੋ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ਕਨੈਕਟ ਨਾ ਕਰੋ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ਕੀ ਕਨੈਕਸ਼ਨ ਦੀ ਤਸਦੀਕ ਕਰਨੀ ਹੈ?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ਜੇ ਤੁਸੀਂ ਕਨੈਕਟ ਕਰਦੇ ਹੋ, ਤਾਂ <xliff:g id="CARRIERNAME">%s</xliff:g> ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੁਹਾਡੇ ਸਿਮ ਨਾਲ ਸੰਬੰਧਿਤ ਵਿਲੱਖਣ ਆਈਡੀ ਤੱਕ ਪਹੁੰਚ ਜਾਂ ਉਸ ਨੂੰ ਸਾਂਝਾ ਕਰ ਸਕਦੇ ਹਨ। ਇਸ ਨਾਲ ਸ਼ਾਇਦ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਟਿਕਾਣਾ ਟਰੈਕ ਕੀਤਾ ਜਾ ਸਕੇ।"</string>
diff --git a/service/res/values-pl/strings.xml b/service/res/values-pl/strings.xml
index 89628ee..468495d 100644
--- a/service/res/values-pl/strings.xml
+++ b/service/res/values-pl/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Sugerowane sieci: <xliff:g id="NAME">%s</xliff:g>. Urządzenie może łączyć się automatycznie."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Zezwól"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nie, dziękuję"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> chce łączyć się automatycznie"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Te sieci otrzymują unikalny identyfikator, który można wykorzystać do śledzenia lokalizacji urządzenia"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Połącz mimo to"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Połączyć z Wi-Fi operatora <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Te sieci otrzymują identyfikator SIM, który można wykorzystać do śledzenia lokalizacji urządzenia"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Połącz"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nie łącz"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Potwierdzić połączenie?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Jeśli się połączysz, sieci Wi-Fi operatora <xliff:g id="CARRIERNAME">%s</xliff:g> będą mogły korzystać z unikalnego identyfikatora powiązanego z Twoją kartą SIM oraz go udostępniać. To może pozwolić na monitorowanie lokalizacji Twojego urządzenia."</string>
diff --git a/service/res/values-pt-rBR/strings.xml b/service/res/values-pt-rBR/strings.xml
index 15b5e39..c5cef56 100644
--- a/service/res/values-pt-rBR/strings.xml
+++ b/service/res/values-pt-rBR/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas pelo app <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode se conectar automaticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> quer fazer a conexão automática"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Essas redes recebem um código exclusivo que pode ser usado para monitorar o local do dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectar assim mesmo"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Conectar à rede Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Essas redes recebem um ID de chip que pode ser usado para monitorar o local do dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não conectar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmar a conexão?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se você fizer a conexão, as redes Wi-Fi da <xliff:g id="CARRIERNAME">%s</xliff:g> poderão acessar ou compartilhar o código exclusivo associado ao seu chip. Isso talvez permita que o local do dispositivo seja monitorado."</string>
diff --git a/service/res/values-pt-rPT/strings.xml b/service/res/values-pt-rPT/strings.xml
index 72d4661..e051c21 100644
--- a/service/res/values-pt-rPT/strings.xml
+++ b/service/res/values-pt-rPT/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas por <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode estabelecer ligação automaticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não, obrigado"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"O operador <xliff:g id="CARRIERNAME">%s</xliff:g> pretende efetuar uma ligação automática"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Estas redes recebem um ID exclusivo que pode ser utilizado para monitorizar a localização dos dispositivos."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ligar mesmo assim"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Pretende estabelecer ligação à rede Wi-Fi do operador <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Estas redes recebem um ID do SIM que pode ser utilizado para monitorizar a localização dos dispositivos."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ligar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não ligar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Pretende confirmar a ligação?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Caso proceda à ligação, as redes Wi-Fi do operador <xliff:g id="CARRIERNAME">%s</xliff:g> podem partilhar ou aceder a um ID exclusivo associado ao seu SIM. Esta ação pode permitir que a localização do seu dispositivo seja monitorizada."</string>
diff --git a/service/res/values-pt/strings.xml b/service/res/values-pt/strings.xml
index 15b5e39..c5cef56 100644
--- a/service/res/values-pt/strings.xml
+++ b/service/res/values-pt/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Redes sugeridas pelo app <xliff:g id="NAME">%s</xliff:g>. O dispositivo pode se conectar automaticamente."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permitir"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Não"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> quer fazer a conexão automática"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Essas redes recebem um código exclusivo que pode ser usado para monitorar o local do dispositivo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectar assim mesmo"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Conectar à rede Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Essas redes recebem um ID de chip que pode ser usado para monitorar o local do dispositivo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectar"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Não conectar"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmar a conexão?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Se você fizer a conexão, as redes Wi-Fi da <xliff:g id="CARRIERNAME">%s</xliff:g> poderão acessar ou compartilhar o código exclusivo associado ao seu chip. Isso talvez permita que o local do dispositivo seja monitorado."</string>
diff --git a/service/res/values-ro/strings.xml b/service/res/values-ro/strings.xml
index 52b4252..b6ee6be 100644
--- a/service/res/values-ro/strings.xml
+++ b/service/res/values-ro/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> a sugerat rețele. Dispozitivul se poate conecta automat."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Permiteți"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nu, mulțumesc"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> încearcă să se conecteze automat"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Aceste rețele primesc un ID unic care se poate folosi pentru a urmări locația dispozitivului"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Conectați oricum"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vă conectați la rețeaua Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Aceste rețele primesc un cod SIM care se poate folosi pentru a urmări locația dispozitivului"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Conectați"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nu conectați"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Confirmați conexiunea?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Dacă vă conectați, rețelele Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> pot să acceseze sau să trimită un ID unic asociat profilului dvs. SIM. Astfel, locația dispozitivului poate fi urmărită."</string>
diff --git a/service/res/values-ru/strings.xml b/service/res/values-ru/strings.xml
index c5f2521..266ee0d 100644
--- a/service/res/values-ru/strings.xml
+++ b/service/res/values-ru/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Приложение \"<xliff:g id="NAME">%s</xliff:g>\" рекомендует сети, к которым устройство может подключаться автоматически."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Разрешить"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Нет, спасибо"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> запрашивает разрешение на автоподключение"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Эти сети получат доступ к уникальному идентификатору, с помощью которого можно отслеживать местоположение устройства."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Все равно подключиться"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Подключиться к сети Wi-Fi оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\"?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Этим сетям будет передан идентификатор SIM-карты, с помощью которого можно отслеживать местоположение устройства."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Подключиться"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не подключаться"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Подтвердите подключение"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Если вы установите подключение, Wi‑Fi-сети оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" смогут получать доступ к уникальному идентификатору, связанному с вашей SIM-картой, или делиться им. Это позволит отслеживать местоположение устройства."</string>
diff --git a/service/res/values-si/strings.xml b/service/res/values-si/strings.xml
index 8e6b17f..959f31c 100644
--- a/service/res/values-si/strings.xml
+++ b/service/res/values-si/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> යෝජිත ජාල. උපාංගය ස්වයංක්‍රියව සම්බන්ධ වනු ඇත."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"ඉඩ දෙන්න"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"එපා, ස්තූතියි"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> හට ස්වයං නිවැරදි කිරීමට අවශ්‍යයි"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"උපාංග ස්ථානය නිරීක්ෂණය කිරීමට භාවිත කළ හැකි අනන්‍ය ID එකක් මෙම ජාලවලට ලැබේ"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"කෙසේ වෙතත් සම්බන්ධ කරන්න"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi වෙත සබඳින්නද?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"උපාංග ස්ථානය නිරීක්ෂණය කිරීමට භාවිත කළ හැකි SIM ID එකක් මෙම ජාලවලට ලැබේ"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"සම්බන්ධ කරන්න"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"සම්බන්ධ නොකරන්න"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"නිවැරදි කිරීම තහවුරු කරන්නද?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"ඔබ සම්බන්ධ වුවහොත්, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi ජාල ඔබේ SIM එක හා සම්බන්ධිත අනන්‍ය ID එකකට ප්‍රවේශ වීමට හෝ එය බෙදා ගැනීමට හැකිය. මෙය ඔබේ උපාංගයෙහි ස්ථානය නිරීක්ෂණය කිරීමට ඉඩ දිය හැකිය."</string>
diff --git a/service/res/values-sk/strings.xml b/service/res/values-sk/strings.xml
index fe58277..db3478b 100644
--- a/service/res/values-sk/strings.xml
+++ b/service/res/values-sk/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Siete navrhuje aplikácia <xliff:g id="NAME">%s</xliff:g>. Zariadenie sa môže pripájať automaticky."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Povoliť"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nie, ďakujem"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Operátor <xliff:g id="CARRIERNAME">%s</xliff:g> chce používať automatické pripojenie"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Tieto siete prijímajú jedinečný identifikátor, ktorý môže byť použitý na sledovanie polohy zariadenia"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Pripojiť aj tak"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Chcete sa pripojiť k sieti Wi‑Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tieto siete dostávajú jedinečný identifikátor SIM karty, pomocou ktorého je možné sledovať polohu zariadenia"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Pripojiť"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Nepripojiť"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Chcete potvrdiť pripojenie?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Po pripojení môžu siete Wi‑Fi operátora <xliff:g id="CARRIERNAME">%s</xliff:g> pristupovať k jedinečnému identifikátoru spojenému s vašou SIM kartou alebo ho zdieľať. To umožňuje sledovať polohu vášho zariadenia."</string>
diff --git a/service/res/values-sl/strings.xml b/service/res/values-sl/strings.xml
index c27f985..990cddd 100644
--- a/service/res/values-sl/strings.xml
+++ b/service/res/values-sl/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> – predlagana omrežja. Naprava se lahko poveže samodejno."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Dovoli"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ne, hvala"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Operater <xliff:g id="CARRIERNAME">%s</xliff:g> se želi samodejno povezati"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ta omrežja prejmejo enolični ID, s katerim je mogoče spremljati lokacijo naprave."</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Vseeno poveži"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Želite vzpostaviti povezavo z omrežjem Wi-Fi operaterja <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ta omrežja prejmejo ID kartice SIM, s katerim je mogoče spremljati lokacijo naprave."</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Poveži"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ne poveži"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Želite potrditi povezavo?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Če vzpostavite povezavo, lahko omrežja Wi-Fi operaterja <xliff:g id="CARRIERNAME">%s</xliff:g> dostopajo do enoličnega ID-ja, povezanega s kartico SIM, in ga delijo. To lahko omogoči spremljanje lokacije naprave."</string>
diff --git a/service/res/values-sq/strings.xml b/service/res/values-sq/strings.xml
index 708503d..1bee498 100644
--- a/service/res/values-sq/strings.xml
+++ b/service/res/values-sq/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Rrjet e sugjeruara të <xliff:g id="NAME">%s</xliff:g>. Pajisja mund të lidhet automatikisht."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Lejo"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Jo, faleminderit"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> dëshiron të lidhet automatikisht"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Këto rrjete marrin një ID unike që mund të përdoret për të monitoruar vendndodhjen"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Lidhu gjithsesi"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Do të lidhesh me Wi-Fi nga <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Këto rrjete marrin një ID karte SIM që mund të përdoret për të monitoruar vendndodhjen"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Lidh"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Mos u lidh"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Të konfirmohet lidhja?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Nëse lidhesh, rrjetet Wi-Fi të <xliff:g id="CARRIERNAME">%s</xliff:g> mund të kenë qasje ose mund të ndajnë një ID unike që lidhet me kartën tënde SIM. Kjo mund të lejojë monitorimin e vendndodhjes sate."</string>
diff --git a/service/res/values-sr/strings.xml b/service/res/values-sr/strings.xml
index c488c21..74bf982 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>
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Мреже које предлаже <xliff:g id="NAME">%s</xliff:g>. Уређај ће се можда повезати аутоматски."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволи"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Не, хвала"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> жели да се аутоматски повеже"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ове мреже захтевају јединствени ИД који може да се користи за праћење локације уређаја"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Ипак повежи"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Желите да се повежете на WiFi мрежу <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ове мреже добијају ИД SIM картице који може да се користи за праћење локације уређаја"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Повежи"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не повезуј"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Желите ли да потврдите повезивање?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ако се повежете, Wi‑Fi мреже оператера <xliff:g id="CARRIERNAME">%s</xliff:g> могу да приступају јединственом ИД-у повезаном са SIM картицом или да га деле. То може да омогући праћење локације уређаја."</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_message" msgid="6085636103482409595">"Да бисте се повезали на мрежу <xliff:g id="SSID">%1$s</xliff:g>, уметните <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM картицу"</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-sv/strings.xml b/service/res/values-sv/strings.xml
index 6b97f4a..01fe1a8 100644
--- a/service/res/values-sv/strings.xml
+++ b/service/res/values-sv/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Nätverk som föreslagits av <xliff:g id="NAME">%s</xliff:g>. Enheten kan anslutas automatiskt."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Tillåt"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Nej tack"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> vill ansluta automatiskt"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Dessa nätverk får ett unikt id som kan användas till att spåra enhetens plats"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Anslut ändå"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Vill du ansluta till Wi-Fi från <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Dessa nätverk får ett SIM-id som kan användas till att spåra enhetens plats"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Anslut"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Anslut inte"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Vill du bekräfta anslutningen?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Om du ansluter kan Wi-Fi-nätverk från <xliff:g id="CARRIERNAME">%s</xliff:g> få åtkomst till eller dela ett unikt id som är kopplat till ditt SIM-kort. Detta kan göra det möjligt att spåra enhetens plats."</string>
diff --git a/service/res/values-sw/strings.xml b/service/res/values-sw/strings.xml
index 12bc190..5ab27d3 100644
--- a/service/res/values-sw/strings.xml
+++ b/service/res/values-sw/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mitandao inayopendekezwa kwa ajili ya <xliff:g id="NAME">%s</xliff:g>. Huenda kifaa kikaunganisha kiotomatiki."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Ruhusu"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hapana"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> inataka kuunganisha kiotomatiki"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Mitandao hii hupokea kitambulisho cha kipekee kinachoweza kutumika ili kufuatilia mahali kifaa kilipo"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Unganisha hata hivyo"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Ungependa kuunganisha kwenye Wi‑Fi ya <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Mitandao hii hupokea kitambulisho cha SIM kinachoweza kutumika ili kufuatilia mahali kifaa kilipo"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Unganisha"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Usiunganishe"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Ungependa kuthibitisha muunganisho?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Ukiunganisha, huenda mitandao ya Wi-Fi ya <xliff:g id="CARRIERNAME">%s</xliff:g> ikafikia au kushiriki kitambulisho cha kipekee kinachohusishwa na SIM yako. Huenda hii ikaruhusu ufuatiliaji wa mahali kifaa chako kilipo."</string>
diff --git a/service/res/values-ta/strings.xml b/service/res/values-ta/strings.xml
index fd4af15..0fe47fe 100644
--- a/service/res/values-ta/strings.xml
+++ b/service/res/values-ta/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> பரிந்துரைக்கும் நெட்வொர்க்குகள். சாதனம் தானாக இணைக்கப்படக்கூடும்."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"அனுமதி"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"வேண்டாம்"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> தானாக இணைக்க விரும்புகிறது"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"சாதன இருப்பிடத்தை டிராக் செய்யப் பயன்படுத்தப்படும் தனிப்பட்ட ஐடியை இந்த நெட்வொர்க்குகள் பெறும்"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"பரவாயில்லை, இணை"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> வைஃபையுடன் இணைக்கவா?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"சாதன இருப்பிடத்தைக் கண்காணிக்கப் பயன்படுத்தப்படும் சிம் ஐடியை இந்த நெட்வொர்க்குகள் பெறும்"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"இணை"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"இணைக்காதே"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"நிச்சயமாக இணைக்கவா?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"இணைத்தால், உங்கள் SIMமுடன் இணைக்கப்பட்டிருக்கும் தனிப்பட்ட ஐடியை <xliff:g id="CARRIERNAME">%s</xliff:g> வைஃபை நெட்வொர்க்குகள் அணுகக்கூடும் அல்லது பகிரக்கூடும். இதனால் உங்கள் சாதனத்தின் இருப்பிடத்தை டிராக் செய்ய அனுமதிக்கப்படலாம்."</string>
diff --git a/service/res/values-te/strings.xml b/service/res/values-te/strings.xml
index 465f587..fedd990 100644
--- a/service/res/values-te/strings.xml
+++ b/service/res/values-te/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> సూచించిన నెట్‌వర్క్‌లు. పరికరం ఆటోమేటిక్‌గా కనెక్ట్ అవచ్చు."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"అనుమతించు"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"వద్దు"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ఆటోమేటిక్‌గా కనెక్షన్ అనుమతిని కోరుతోంది"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"ఈ నెట్‌వర్క్‌లకు, పరికర లొకేషన్‌ను ట్రాక్ చేయడానికి ఉపయోగించగల ప్రత్యేక ID అందుతాయి"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ఏదేమైనా కనెక్ట్ చేయి"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fiకి కనెక్ట్ చేయాలా?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"పరికర లొకేషన్‌ను ట్రాక్ చేయడానికి ఉపయోగపడే SIM IDని ఈ నెట్‌వర్క్‌లు అందుకుంటాయి"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"కనెక్ట్ చేయి"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"కనెక్ట్ చేయవద్దు"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ఖచ్చితంగా కనెక్ట్ చేయాలా?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"<xliff:g id="CARRIERNAME">%s</xliff:g> నెట్‌వర్క్‌కు మీరు కనెక్ట్ చేస్తే, ఆ క్యారియర్ Wi‑Fi నెట్‌వర్క్‌లు మీ SIMకు అనుబంధితమైన ప్రత్యేక IDని యాక్సెస్ లేదా షేర్ చేయగలగవచ్చు. దీని వలన మీ పరికరం లొకేషన్ ట్రాక్ చేయబడవచ్చు."</string>
diff --git a/service/res/values-th/strings.xml b/service/res/values-th/strings.xml
index 5cd4e6e..b6a0691 100644
--- a/service/res/values-th/strings.xml
+++ b/service/res/values-th/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"เครือข่ายที่แนะนำโดย <xliff:g id="NAME">%s</xliff:g> และอุปกรณ์อาจเชื่อมต่อโดยอัตโนมัติ"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"อนุญาต"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"ไม่เป็นไร"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> ต้องการเชื่อมต่อโดยอัตโนมัติ"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"เครือข่ายเหล่านี้จะได้รับรหัสที่ไม่ซ้ำกันซึ่งใช้ในการติดตามตำแหน่งของอุปกรณ์ได้"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"ยังต้องการเชื่อมต่อ"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"เชื่อมต่อกับ Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> ไหม"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"เครือข่ายเหล่านี้จะได้รับรหัส SIM ซึ่งใช้ติดตามตำแหน่งอุปกรณ์ได้"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"เชื่อมต่อ"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"ไม่เชื่อมต่อ"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"ยืนยันการเชื่อมต่อใช่ไหม"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"หากเชื่อมต่อ เครือข่าย Wi-Fi ของ <xliff:g id="CARRIERNAME">%s</xliff:g> อาจเข้าถึงหรือแชร์รหัสที่ไม่ซ้ำกันซึ่งเชื่อมโยงกับซิมของคุณ และอาจอนุญาตให้มีการติดตามตำแหน่งอุปกรณ์ของคุณ"</string>
diff --git a/service/res/values-tl/strings.xml b/service/res/values-tl/strings.xml
index bc38fd4..b26679d 100644
--- a/service/res/values-tl/strings.xml
+++ b/service/res/values-tl/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Mga iminumungkahing network ng <xliff:g id="NAME">%s</xliff:g>. Posibleng awtomatikong kumonekta ang device."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Payagan"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hindi, salamat na lang"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Gustong awtomatikong kumonekta ng <xliff:g id="CARRIERNAME">%s</xliff:g>"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Makakatanggap ang mga network na ito ng isang natatanging ID na puwedeng gamitin sa pagsusubaybay ng lokasyon ng device"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Kumonekta pa rin"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kumonekta sa <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Tumatanggap ang mga network na ito ng SIM ID na magagamit sa pag-track sa lokasyon ng device"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Kumonekta"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Huwag kumonekta"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Kumpirmahin ang koneksyon?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Kung kokonekta ka, posibleng ma-access o maging kapareho ng mga Wi-Fi network ng <xliff:g id="CARRIERNAME">%s</xliff:g> ang natatanging ID na nauugnay sa iyong SIM. Baka mapahintulutan nito ang pagsubaybay sa lokasyon ng iyong device."</string>
diff --git a/service/res/values-tr/strings.xml b/service/res/values-tr/strings.xml
index c5c605d..16cf1a2 100644
--- a/service/res/values-tr/strings.xml
+++ b/service/res/values-tr/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> tarafından önerilen ağlar. Cihaz otomatik olarak bağlanabilir."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"İzin ver"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Hayır, teşekkürler"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>, otomatik olarak bağlanmak istiyor"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Bu ağlar, cihazın konumunu izlemek için kullanılabilecek benzersiz bir kimlik alır"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Yine de bağlan"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> kablosuz ağına bağlanılsın mı?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu ağlar, cihazın konumunu izlemek için kullanılabilecek bir SIM kimliği alır"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Bağlan"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Bağlanma"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Bağlantı onaylansın mı?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Bağlanırsanız <xliff:g id="CARRIERNAME">%s</xliff:g> kablosuz ağları SIM\'inizle ilişkilendirilmiş benzersiz kimliğe erişebilir veya bunları paylaşabilir. Bu, cihazınızın konumunun izlenmesine olanak sağlayabilir."</string>
diff --git a/service/res/values-uk/strings.xml b/service/res/values-uk/strings.xml
index 6624d01..e2b9e51 100644
--- a/service/res/values-uk/strings.xml
+++ b/service/res/values-uk/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Мережі, пропоновані додатком <xliff:g id="NAME">%s</xliff:g>. Пристрій може підключитися автоматично."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Дозволити"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Ні, дякую"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"Оператор \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" хоче підключатися автоматично"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Ці мережі отримують унікальний ідентифікатор, за допомогою якого можна відстежити місцезнаходження пристрою"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Усе одно підключитися"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Підключитися до мережі Wi‑Fi <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Ці мережі отримують ідентифікатор SIM-карти, за допомогою якого можна відстежити місцезнаходження пристрою"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Підключитися"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Не підключатися"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Підтвердити підключення?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Якщо ви під\'єднаєтеся, мережі Wi‑Fi оператора \"<xliff:g id="CARRIERNAME">%s</xliff:g>\" зможуть розкрити унікальний ідентифікатор вашої SIM-карти й відстежити місцезнаходження вашого пристрою."</string>
diff --git a/service/res/values-ur/strings.xml b/service/res/values-ur/strings.xml
index 668abaa..0d50643 100644
--- a/service/res/values-ur/strings.xml
+++ b/service/res/values-ur/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> تجویز کردہ نیٹ ورکس۔ آلہ خودکار طور پر منسلک ہو سکتا ہے۔"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"اجازت ہیں"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"نہیں شکریہ"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> خود کار طور پر منسلک ہونا چاہتا ہے"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"‏یہ نیٹ ورکس ایک منفرد ID موصول کرتے ہیں جسے آلہ کا مقام ٹریک کرنے کے لیے استعمال کیا جا سکتا ہے"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"بہرحال منسلک کریں"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"‏<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi سے منسلک ہوں؟"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"‏یہ نیٹ ورکس ایک منفرد SIM ID موصول کرتے ہیں جسے آلہ کا مقام ٹریک کرنے کے لیے استعمال کیا جا سکتا ہے"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"منسلک کریں"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"منسلک نہ کریں"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"کنکشن کی تصدیق کریں؟"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"‏اگر آب منسلک ہیں، Wi-Fi <xliff:g id="CARRIERNAME">%s</xliff:g> نیٹ ورکس آپ کے SIM سے وابستہ ایک منفرد ID تک رسائی حاصل یا اشتراک کر سکتے ہیں۔ یہ آپ کے آلہ کے مقام کو ٹریک کیے جانے کی اجازت دے سکتا ہے۔"</string>
diff --git a/service/res/values-uz/strings.xml b/service/res/values-uz/strings.xml
index 9ba9778..be52bd2 100644
--- a/service/res/values-uz/strings.xml
+++ b/service/res/values-uz/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> tavsiya qilgan tarmoqlar. Qurilma avtomatik ulanishi mumkin."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Ruxsat"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Kerak emas"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> avtomatik ulanmoqchi"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Bu tarmoqlar unikal identifikator oladi, bu orqali qurilma joylashuvini kuzatish mumkin"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Baribir ulansin"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"<xliff:g id="CARRIERNAME">%s</xliff:g> Wi-Fi tarmoqqa ulaning"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Bu tarmoqlar SIM identifikator oladi, bu orqali qurilma joylashuvini kuzatish mumkin"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Ulash"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ulanmasin"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Ulanish tasdiqlansinmi?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Agar ulansangiz, <xliff:g id="CARRIERNAME">%s</xliff:g> Wi‑Fi tarmoqlari SIM kartangizga aloqador unikal identifikatordan foydalanishi yoki ulashishi mumkin. Bu qurilmangiz joylashuvi kuzatilishiga ruxsat berishi mumkin."</string>
diff --git a/service/res/values-vi/strings.xml b/service/res/values-vi/strings.xml
index fafdd68..d6e1ea3 100644
--- a/service/res/values-vi/strings.xml
+++ b/service/res/values-vi/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"Các mạng do <xliff:g id="NAME">%s</xliff:g> đề xuất. Thiết bị có thể kết nối tự động."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Cho phép"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Không, cảm ơn"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g> muốn kết nối tự động"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Các mạng này nhận được một mã nhận dạng duy nhất dùng để theo dõi vị trí của thiết bị"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Vẫn kết nối"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Kết nối với Wi-Fi của <xliff:g id="CARRIERNAME">%s</xliff:g>?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Các mạng này nhận được một mã nhận dạng SIM có thể dùng để theo dõi vị trí của thiết bị"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Kết nối"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Không kết nối"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Xác nhận kết nối?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Nếu bạn kết nối, các mạng Wi-Fi của <xliff:g id="CARRIERNAME">%s</xliff:g> có thể truy cập hoặc chia sẻ mã nhận dạng duy nhất liên kết với SIM của bạn. Từ đó, các mạng này có thể theo dõi vị trí thiết bị của bạn."</string>
diff --git a/service/res/values-zh-rCN/strings.xml b/service/res/values-zh-rCN/strings.xml
index 1c9aa1e..bf1eff8 100644
--- a/service/res/values-zh-rCN/strings.xml
+++ b/service/res/values-zh-rCN/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g>建议的网络。设备可能会自动连接到这些网络。"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允许"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"<xliff:g id="CARRIERNAME">%s</xliff:g>想要自动连接"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"这些网络会收到可用于跟踪设备位置的唯一 ID"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"仍然连接"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要连接到<xliff:g id="CARRIERNAME">%s</xliff:g>的 WLAN 吗?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"这些网络会收到可用于跟踪设备位置的 SIM 卡 ID"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"连接"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不连接"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"确认连接?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"如果您确认连接,<xliff:g id="CARRIERNAME">%s</xliff:g> WLAN 网络可获取或共享与您的 SIM 卡关联的唯一 ID。他人或许可以借此跟踪您的设备位置。"</string>
diff --git a/service/res/values-zh-rHK/strings.xml b/service/res/values-zh-rHK/strings.xml
index c66b2b5..d41d74e 100644
--- a/service/res/values-zh-rHK/strings.xml
+++ b/service/res/values-zh-rHK/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"「<xliff:g id="NAME">%s</xliff:g>」已建議網絡連線,裝置可能會自動連接網絡。"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允許"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了,謝謝"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"「<xliff:g id="CARRIERNAME">%s</xliff:g>」要求自動連線"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"這些網絡會收到可追蹤裝置位置的獨有 ID"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"仍要連線"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要連線至「<xliff:g id="CARRIERNAME">%s</xliff:g>」Wi-Fi 嗎?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"這些網絡會收到可追蹤裝置位置的 SIM 卡 ID"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"連接"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不要連線"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"確定要連線嗎?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"連線後,「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi‑Fi 網絡就能存取或分享與 SIM 卡相關的獨有 ID,有心人或許可藉此追蹤您裝置的位置。"</string>
diff --git a/service/res/values-zh-rTW/strings.xml b/service/res/values-zh-rTW/strings.xml
index ede75b4..3bc93f1 100644
--- a/service/res/values-zh-rTW/strings.xml
+++ b/service/res/values-zh-rTW/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"「<xliff:g id="NAME">%s</xliff:g>」建議的網路。裝置可能會自動連線到這些網路。"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"允許"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"不用了,謝謝"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"「<xliff:g id="CARRIERNAME">%s</xliff:g>」要求自動連線"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"這些網路會收到可用於追蹤裝置位置資訊的唯一 ID"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"繼續連線"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"要連線至「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi-Fi 網路嗎?"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"這些網路會收到可用於追蹤裝置位置的 SIM 卡 ID"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"連線"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"不要連線"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"確定要連線嗎?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"連線後,「<xliff:g id="CARRIERNAME">%s</xliff:g>」的 Wi‑Fi 網路可能會存取或分享與 SIM 卡相關的唯一 ID,有心人士或許可藉此追蹤你的裝置所在位置。"</string>
diff --git a/service/res/values-zu/strings.xml b/service/res/values-zu/strings.xml
index ce14f92..ecc4a25 100644
--- a/service/res/values-zu/strings.xml
+++ b/service/res/values-zu/strings.xml
@@ -31,9 +31,9 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"<xliff:g id="NAME">%s</xliff:g> amanethiwekhi aphakanyisiwe. Idivayisi ingaxhumeka ngokuzenzakalela."</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"Vumela"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"Cha ngiyabonga"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"I-<xliff:g id="CARRIERNAME">%s</xliff:g> ifuna ukuxhuma ngokuzenzekelayo"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"Lama nethiwekhi athola i-ID ehlukile engasetshenziselwa ukulandelela indawo yedivayisi"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"Xhuma noma kunjalo"</string>
+    <string name="wifi_suggestion_imsi_privacy_title" msgid="442867569519352918">"Xhuma ku-Wi-Fi ye-<xliff:g id="CARRIERNAME">%s</xliff:g>"</string>
+    <string name="wifi_suggestion_imsi_privacy_content" msgid="6631744859477949328">"Lama nethiwekhi athola i-SIM ID engasetshenziselwa ukulandelela indawo yedivayisi"</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="6445286383390779291">"Xhuma"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"Ungaxhumi"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"Qinisekisa ukuxhuma?"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"Uma uxhuma, amanethiwekhi we-Wi-Fi ye-<xliff:g id="CARRIERNAME">%s</xliff:g> angase akwazi ukufinyelela ku-ID yakho ehlukile ehlobene ne-SIM yakho. Lokhu kungase kuvumele ukuthi indawo yedivayisi yakho ilandelelwe."</string>
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index cc80f60..61b6304 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -188,6 +188,12 @@
          scan in minutes -->
     <integer translatable="false" name="config_wifiInitialPartialScanChannelCacheAgeMins">14400</integer>
 
+    <!-- Boolean indicating enable or disable quick connect -->
+    <bool translatable="false" name="config_wifi_framework_enable_quick_connect">false</bool>
+
+    <!-- Integer for Wifi Partial scan results fetching period(in ms) -->
+    <integer translatable="false" name="config_wifi_partial_scan_results_fetching_period_ms">0</integer>
+
     <!-- Boolean indicating whether single radio chain scan results are to be used for network selection -->
     <bool translatable="false" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection">true</bool>
 
@@ -207,9 +213,21 @@
     <!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
     <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
 
+    <!-- Wifi driver Automatic channel selection (ACS) for softap to include dfs channels -->
+    <bool translatable="false" name="config_wifi_softap_acs_include_dfs">false</bool>
+
     <!-- Wifi driver supports WPA3 Simultaneous Authentication of Equals (WPA3-SAE) for softap -->
     <bool translatable="false" name="config_wifi_softap_sae_supported">false</bool>
 
+    <!-- Wifi driver supports WPA3 Simultaneous Authentication of Equals (WPA3-OWE) for softap -->
+    <bool translatable="false" name="config_vendor_wifi_softap_owe_supported">false</bool>
+
+    <!-- Wifi driver supports Beacon Protection for SoftAp -->
+    <bool translatable="false" name="config_vendor_softap_beacon_protection_supported">false</bool>
+
+    <!-- Wifi driver supports Ocv for SoftAp -->
+    <bool translatable="false" name="config_vendor_softap_ocv_supported">false</bool>
+
     <!-- Wifi driver supports IEEE80211AC for softap -->
     <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
 
@@ -355,20 +373,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 +479,13 @@
 
     <!-- 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>
+
+    <!-- Do not translate. Default bridge interface name for Dual SAP tethering -->
+    <string name="config_vendor_wifi_tether_bridge_interface_name" translatable="false">wifi_br0</string>
+
+    <!-- Boolean to provide support to keep wifi5 symbol for 8SS supported device and 11ax AP -->
+    <bool translatable="false" name="config_vendorWifi11axReadySupport">true</bool>
 </resources>
diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml
index a4b7011..65af153 100644
--- a/service/res/values/overlayable.xml
+++ b/service/res/values/overlayable.xml
@@ -73,12 +73,18 @@
           <item type="integer" name="config_wifiInitialPartialScanChannelMaxCount" />
           <item type="integer" name="config_wifiInitialPartialScanChannelCacheAgeMins" />
           <item type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" />
+          <item type="bool" name="config_wifi_framework_enable_quick_connect" />
+          <item type="integer" name="config_wifi_partial_scan_results_fetching_period_ms" />
           <item type="bool" name="config_wifi_only_link_same_credential_configurations" />
           <item type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" />
           <item type="bool" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit" />
           <item type="bool" name="config_wifiSofapClientForceDisconnectSupported" />
           <item type="bool" name="config_wifi_softap_acs_supported" />
+          <item type="bool" name="config_wifi_softap_acs_include_dfs" />
           <item type="bool" name="config_wifi_softap_sae_supported" />
+          <item type="bool" name="config_vendor_wifi_softap_owe_supported" />
+          <item type="bool" name="config_vendor_softap_beacon_protection_supported" />
+          <item type="bool" name="config_vendor_softap_ocv_supported" />
           <item type="bool" name="config_wifi_softap_ieee80211ac_supported" />
           <item type="bool" name="config_wifiSoftapIeee80211axSupported" />
           <item type="bool" name="config_wifiSoftap6ghzSupported" />
@@ -114,7 +120,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 +150,8 @@
           <item type="integer" name="config_wifiMovingPnoScanIntervalMillis" />
           <item type="integer" name="config_wifiStationaryPnoScanIntervalMillis" />
           <item type="integer" name="config_wifiDelayDisconnectOnImsLostMs" />
+          <item type="bool" name="config_wifiMinConfirmationDurationSendNetworkScoreEnabled" />
+          <item type="bool" name="config_vendorWifi11axReadySupport" />
           <!-- Params from config.xml that can be overlayed -->
 
           <!-- Params from strings.xml that can be overlayed -->
@@ -209,6 +217,7 @@
           <item type="string" name="wifi_softap_auto_shutdown_timeout_expired_summary" />
           <item type="string" name="wifi_sim_required_title" />
           <item type="string" name="wifi_sim_required_message" />
+          <item type="string" name="config_vendor_wifi_tether_bridge_interface_name" />
           <!-- Params from strings.xml that can be overlayed -->
 
           <!-- Params from styles.xml that can be overlayed -->
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 441ecca..ae3f197 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -49,11 +49,11 @@
     <string name="wifi_suggestion_action_disallow_app">No thanks</string>
 
     <!-- Notification title for a connection to a SIM-based carrier network without IMSI privacy protection. -->
-    <string name="wifi_suggestion_imsi_privacy_title"><xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> wants to auto\u2011connect</string>
+    <string name="wifi_suggestion_imsi_privacy_title">Connect to <xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> Wi\u2011Fi?</string>
     <!-- Notification content for a connection to a SIM-based carrier network without IMSI privacy protection.-->
-    <string name="wifi_suggestion_imsi_privacy_content">These networks receive a unique ID that can be used to track device location</string>
+    <string name="wifi_suggestion_imsi_privacy_content">These networks receive a SIM ID that can be used to track device location</string>
     <!-- Notification action for allowing carrier specified in the notification body.-->
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier">Connect anyway</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier">Connect</string>
     <!-- Notification action for disallowing carrier specified in the notification body.-->
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier">Don\u0027t connect</string>
     <!-- Confirmation dialog title for a connection to a SIM-based carrier network without IMSI privacy protection. -->
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..e2aeb91 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,
@@ -2856,8 +2874,8 @@
                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
 
         WifiConfiguration config = new WifiConfiguration();
-        config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
 
         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
@@ -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/ClientModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
index 92f3d9b..ae5ece3 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
@@ -455,7 +455,22 @@
     }
 
     /**
-     * ClientMode stop properly cleans up state
+     * ClientMode stop before start has been processed properly cleans up state & invokes the
+     * onStopped callback.
+     */
+    @Test
+    public void clientModeStopBeforeStartCleansUpState() throws Exception {
+        // Invoke stop before the inernal start is processed by the state machine.
+        mClientModeManager.stop();
+        mLooper.dispatchAll();
+        verify(mListener).onStopped();
+
+        // Don't initiate wifi native setup.
+        verifyNoMoreInteractions(mListener, mWifiNative);
+    }
+
+    /**
+     * ClientMode stop properly cleans up state & invokes the onStopped callback.
      */
     @Test
     public void clientModeStopCleansUpState() throws Exception {
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..63a6300 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));
     }
 
     /**
@@ -1541,8 +1579,19 @@
     @Test
     public void testTerminateV1_0() throws Exception {
         executeAndValidateInitializationSequence();
+
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public boolean answer(IHwBinder.DeathRecipient cb, long cookie) throws RemoteException {
+                mHandler.post(() -> cb.serviceDied(cookie));
+                return true;
+            }
+        }).when(mISupplicantMock).linkToDeath(any(IHwBinder.DeathRecipient.class), any(long.class));
         mDut.terminate();
+        mLooper.dispatchAll();
         verify(mFrameworkFacade).stopSupplicant();
+
+        // Check that terminate cleared all internal state.
+        assertFalse(mDut.isInitializationComplete());
     }
 
     /**
@@ -1553,9 +1602,21 @@
         setupMocksForHalV1_1();
 
         executeAndValidateInitializationSequenceV1_1(false, false);
+
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public boolean answer(IHwBinder.DeathRecipient cb, long cookie) throws RemoteException {
+                mHandler.post(() -> cb.serviceDied(cookie));
+                return true;
+            }
+        }).when(mISupplicantMock).linkToDeath(any(IHwBinder.DeathRecipient.class), any(long.class));
+
         mDut.terminate();
+        mLooper.dispatchAll();
         verify(mFrameworkFacade, never()).stopSupplicant();
         verify(mISupplicantMockV1_1).terminate();
+
+        // Check that terminate cleared all internal state.
+        assertFalse(mDut.isInitializationComplete());
     }
 
     private class GetKeyMgmtCapabilitiesAnswer extends MockAnswerUtil.AnswerWithArguments {
@@ -2786,7 +2847,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 +2927,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/WifiCarrierInfoManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
index 2c1c2ec..750e8d4 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
@@ -19,6 +19,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION;
+import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_CLICKED_INTENT_ACTION;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION;
 
@@ -166,6 +167,7 @@
         when(mNotificationBuilder.setTicker(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setContentTitle(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setStyle(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setContentIntent(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setDeleteIntent(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setShowWhen(anyBoolean())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setLocalOnly(anyBoolean())).thenReturn(mNotificationBuilder);
@@ -1538,26 +1540,13 @@
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
                 WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
-        validateUserApprovalDialog(CARRIER_NAME);
-
-        // Simulate user clicking on allow in the dialog.
-        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
-                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
-        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
-                any(), clickListenerCaptor.capture());
-        assertNotNull(clickListenerCaptor.getValue());
-        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
-        mLooper.dispatchAll();
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext).sendBroadcast(intentCaptor.capture());
-        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
         verify(mWifiConfigManager).saveToStore(true);
         assertTrue(mImsiDataSource.hasNewDataToSerialize());
         assertTrue(mWifiCarrierInfoManager
                 .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
         verify(mListener).onUserAllowed(DATA_CARRIER_ID);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
+                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
     }
 
     @Test
@@ -1607,7 +1596,7 @@
         validateImsiProtectionNotification(CARRIER_NAME);
         //Simulate user dismissal the notification
         sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
                 WifiCarrierInfoManager.ACTION_USER_DISMISS, false);
         reset(mNotificationManger);
@@ -1618,7 +1607,7 @@
 
         // As there is notification is active, should not send notification again.
         sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+                CARRIER_NAME, DATA_CARRIER_ID);
         verifyNoMoreInteractions(mNotificationManger);
         verify(mWifiConfigManager, never()).saveToStore(true);
         assertFalse(mImsiDataSource.hasNewDataToSerialize());
@@ -1642,12 +1631,10 @@
 
         mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
         validateImsiProtectionNotification(CARRIER_NAME);
-        // Simulate user clicking on allow in the notification.
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
         validateUserApprovalDialog(CARRIER_NAME);
 
         // Simulate user clicking on disallow in the dialog.
@@ -1685,11 +1672,10 @@
 
         mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
         validateImsiProtectionNotification(CARRIER_NAME);
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
         validateUserApprovalDialog(CARRIER_NAME);
 
         // Simulate user clicking on dismissal in the dialog.
@@ -1718,6 +1704,45 @@
     }
 
     @Test
+    public void testSendImsiProtectionExemptionDialogWithUserAllowed() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        validateUserApprovalDialog(CARRIER_NAME);
+
+        // Simulate user clicking on allow in the dialog.
+        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
+                any(), clickListenerCaptor.capture());
+        assertNotNull(clickListenerCaptor.getValue());
+        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
+        mLooper.dispatchAll();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendBroadcast(intentCaptor.capture());
+        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
+        verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        verify(mListener).onUserAllowed(DATA_CARRIER_ID);
+        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
+                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
+    }
+
+    @Test
     public void testUserDataStoreIsNotLoadedNotificationWillNotBeSent() {
         // reset data source to unloaded state.
         mImsiDataSource.reset();
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 484c32e..d11a9d2 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -622,7 +622,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);
@@ -650,7 +650,8 @@
         assertTrue(oldConfig.trusted);
         assertNull(oldConfig.BSSID);
 
-        assertEquals(0, mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(openNetwork.SSID));
+        assertEquals(0, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(
+                openNetwork.SSID));
     }
 
     /**
@@ -1376,7 +1377,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;
@@ -1387,7 +1388,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);
@@ -1405,7 +1406,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()));
@@ -2918,6 +2919,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>() {
@@ -2936,6 +2938,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 d1000fe..853918a 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;
@@ -1022,4 +1025,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 c7d0d0c..164c0f9 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;
@@ -240,6 +241,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(
@@ -266,6 +269,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(
@@ -286,4 +291,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 4e895e4..b69b302 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..b85f223 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,6 +38,7 @@
 
 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;
@@ -50,6 +51,7 @@
 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 +62,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 +104,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 {
@@ -174,6 +180,9 @@
         when(resources.getInteger(
                 R.integer.config_wifiFrameworkMinPacketPerSecondHighTraffic))
             .thenReturn(100);
+        when(resources.getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled))
+            .thenReturn(false);
     }
 
     /**
@@ -196,9 +205,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 +781,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 +801,8 @@
         mLooper.dispatchAll();
         mWifiScoreReport.stopConnectedNetworkScorer();
         mLooper.dispatchAll();
-        verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(any(), any(), anyLong());
+        verify(mBssidBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(),
+                anyInt(), anyInt());
     }
 
     /**
@@ -805,11 +826,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 +853,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 cae3c7b..a18f784 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -127,6 +127,7 @@
 import android.net.wifi.hotspot2.pps.HomeSp;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -573,7 +574,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));
     }
 
@@ -853,6 +855,9 @@
      */
     @Test
     public void testSetWifiEnabledNoToggle() throws Exception {
+        // Set false because setWifiEnabled() avoids being called in checkAndStartWifi().
+        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+        mWifiServiceImpl.checkAndStartWifi();
         when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false);
         when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
                 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
@@ -1054,9 +1059,6 @@
      */
     @Test
     public void testSetSoftApConfigurationNotSavedWithoutPermission() throws Exception {
-        doThrow(new SecurityException()).when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
         SoftApConfiguration apConfig = createValidSoftApConfiguration();
         try {
             mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME);
@@ -1068,18 +1070,30 @@
      * Ensure softap config is written when the caller has the correct permission.
      */
     @Test
-    public void testSetSoftApConfigurationSuccess() throws Exception {
-        doNothing().when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
+    public void testSetSoftApConfigurationSuccessWithSettingPermission() throws Exception {
+        when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
         SoftApConfiguration apConfig = createValidSoftApConfiguration();
 
         assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME));
         mLooper.dispatchAll();
         verify(mWifiApConfigStore).setApConfiguration(eq(apConfig));
         verify(mActiveModeWarden).updateSoftApConfiguration(apConfig);
-        verify(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService"));
+        verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt());
+    }
+
+    /**
+     * Ensure softap config is written when the caller has the correct permission.
+     */
+    @Test
+    public void testSetSoftApConfigurationSuccessWithOverridePermission() throws Exception {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        SoftApConfiguration apConfig = createValidSoftApConfiguration();
+
+        assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME));
+        mLooper.dispatchAll();
+        verify(mWifiApConfigStore).setApConfiguration(eq(apConfig));
+        verify(mActiveModeWarden).updateSoftApConfiguration(apConfig);
+        verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
     }
 
     /**
@@ -1087,14 +1101,11 @@
      */
     @Test
     public void testSetSoftApConfigurationNullConfigNotSaved() throws Exception {
-        doNothing().when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
         assertFalse(mWifiServiceImpl.setSoftApConfiguration(null, TEST_PACKAGE_NAME));
         verify(mWifiApConfigStore, never()).setApConfiguration(isNull(SoftApConfiguration.class));
         verify(mActiveModeWarden, never()).updateSoftApConfiguration(any());
-        verify(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService"));
+        verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
     }
 
     /**
@@ -1102,14 +1113,11 @@
      */
     @Test
     public void testSetSoftApConfigurationWithInvalidConfigNotSaved() throws Exception {
-        doNothing().when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
         assertFalse(mWifiServiceImpl.setSoftApConfiguration(
                 new SoftApConfiguration.Builder().build(), TEST_PACKAGE_NAME));
         verify(mWifiApConfigStore, never()).setApConfiguration(any());
-        verify(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService"));
+        verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt());
     }
 
     /**
@@ -1117,9 +1125,6 @@
      */
     @Test
     public void testGetSoftApConfigurationNotReturnedWithoutPermission() throws Exception {
-        doThrow(new SecurityException()).when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
         try {
             mWifiServiceImpl.getSoftApConfiguration();
             fail("Expected a SecurityException");
@@ -1133,9 +1138,7 @@
     @Test
     public void testGetSoftApConfigurationSuccess() throws Exception {
         when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
-        doNothing().when(mContext)
-                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
-                        eq("WifiService"));
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
         SoftApConfiguration apConfig = createValidSoftApConfiguration();
         when(mWifiApConfigStore.getApConfiguration()).thenReturn(apConfig);
 
@@ -3623,7 +3626,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());
     }
 
     /**
@@ -3634,8 +3638,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 5ce4739..856056f 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;
 
@@ -51,6 +52,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;
@@ -79,6 +81,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;
@@ -190,6 +193,7 @@
     @Mock TelephonyManager mTelephonyManager;
     @Mock SubscriptionManager mSubscriptionManager;
     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
+    @Mock MacAddressUtil mMacAddressUtil;
     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
     @Mock ActivityManager mActivityManager;
 
@@ -229,7 +233,8 @@
         mHandler = new Handler(mLooper.getLooper());
         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mWifiPermissionsUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil,
+                mWifiPermissionsUtil);
         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
         verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class),
@@ -783,7 +788,8 @@
                 .thenReturn(true);
         PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, spyFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mWifiPermissionsUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil,
+                mWifiPermissionsUtil);
 
         assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -1265,6 +1271,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/InformationElementUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
index 77c99a9..a0d1da8 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);
     }
 
     /**
diff --git a/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java
index 566a94b..f900623 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java
@@ -130,18 +130,6 @@
     }
 
     /**
-     * Test that conversion of SSID string with len > 32 to bytes fail.
-     */
-    @Test
-    public void testLargeSsidDecodeFails() throws Exception {
-        try {
-            NativeUtil.decodeSsid("\"asdrewqdfgyuiopldsqwertyuiolhdergcv\"");
-            fail("Expected ssid decode to fail");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    /**
      * Test that conversion of ssid bytes to hex string ssid works.
      */
     @Test
@@ -192,25 +180,6 @@
     }
 
     /**
-     * Test that conversion of SSID bytes with len > 32 to string fail.
-     */
-    @Test
-    public void testLargeSsidEncodeFails() throws Exception {
-        try {
-            NativeUtil.encodeSsid(new ArrayList<>(
-                    Arrays.asList((byte) 0xf5, (byte) 0xe4, (byte) 0xab, (byte) 0x78, (byte) 0x78,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a,
-                            (byte) 0xab, (byte) 0x34, (byte) 0x32, (byte) 0x43, (byte) 0x9a)));
-            fail("Expected ssid encode to fail");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    /**
      * Test that parsing of quoted SSID to byte array and vice versa works.
      */
     @Test
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,