Merge "Create an ImsEnablementTraker class to handle the enable, disable, reset Ims commands."
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 8a8e208..6781a2a 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -627,7 +627,7 @@
     <string name="ota_progress" msgid="8837259285255700132">"ስልክዎን ፕሮግራም በማድረግ ላይ…"</string>
     <string name="ota_failure" msgid="5674217489921481576">"ስልክዎን ፕሮግራም ማድረግ አልተቻለም"</string>
     <string name="ota_successful" msgid="1106825981548107774">"አሁን ስልክዎ አግብሯል።አገልግሎቱ ለመጀመር እስከ 15 ደቂቃዎች ሊፈጅ ይችላል።"</string>
-    <string name="ota_unsuccessful" msgid="8531037653803955754">"ስልክህ አላገበረም።\n ጥሩ ሽፋን ያለበት አካባቢ ማግኘት ያስፈልግሃል (መስኮት፣ ወይም ውጪ አካባቢ)።ለበለጠ አማራጮች የደንበኞች አገልግሎት ደውል ወይም \n\nእንደገና ሞክር።"</string>
+    <string name="ota_unsuccessful" msgid="8531037653803955754">"ስልክህ አላገበረም።\n ጥሩ ሽፋን ያለበት አካባቢ ማግኘት ያስፈልግሃል (መስኮት፣ ወይም ውጭ አካባቢ)።ለበለጠ አማራጮች የደንበኞች አገልግሎት ደውል ወይም \n\nእንደገና ሞክር።"</string>
     <string name="ota_spc_failure" msgid="904092035241370080">"ከልክ ያለፈ የSPC  መታወክ"</string>
     <string name="ota_call_end" msgid="8657746378290737034">"ተመለስ"</string>
     <string name="ota_try_again" msgid="6914781945599998550">"በድጋሚ ሞክር"</string>
@@ -848,7 +848,7 @@
     <string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"አይገኝም"</string>
     <string name="radio_info_ims_reg_status" msgid="25582845222446390">"የIMS ምዝገባ፦ <xliff:g id="STATUS">%1$s</xliff:g>\n የድምጽ ቅጂ LTE፡ <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nየድምጽ ቅጂ WiFi፡ <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nየቪድዮ ጥሪ፦ <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT በይነገጽ፡ <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
     <string name="radioInfo_service_in" msgid="45753418231446400">"በአገልግሎት ውስጥ"</string>
-    <string name="radioInfo_service_out" msgid="287972405416142312">"ከአገልግሎት ውጪ"</string>
+    <string name="radioInfo_service_out" msgid="287972405416142312">"ከአገልግሎት ውጭ"</string>
     <string name="radioInfo_service_emergency" msgid="4763879891415016848">"የአደጋ ጊዜ ጥሪዎች ብቻ"</string>
     <string name="radioInfo_service_off" msgid="3456583511226783064">"ሬዲዮ ጠፍቷል"</string>
     <string name="radioInfo_roaming_in" msgid="3156335577793145965">"በማዘዋወር ላይ"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 76795dc..3d25a4d 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -20,7 +20,7 @@
     <string name="phoneAppLabel" product="default" msgid="130465039375347763">"Тэлефонныя службы"</string>
     <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Экстраныя выклікі"</string>
     <string name="phoneIconLabel" msgid="3015941229249651419">"Тэлефон"</string>
-    <string name="fdnListLabel" msgid="4119121875004244097">"Спіс FDN"</string>
+    <string name="fdnListLabel" msgid="4119121875004244097">"Спіс дазволеных нумароў"</string>
     <string name="unknown" msgid="8279698889921830815">"Невядомы"</string>
     <string name="private_num" msgid="4487990167889159992">"Прыватны нумар"</string>
     <string name="payphone" msgid="7936735771836716941">"Таксафон"</string>
@@ -438,18 +438,18 @@
     <string name="carrier_settings_title" msgid="6292869148169850220">"Налады аператара"</string>
     <string name="fdn" msgid="2545904344666098749">"Фіксаваныя нумары"</string>
     <string name="fdn_with_label" msgid="6412087553365709494">"Нумары закрытай абаненцкай групы (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
-    <string name="manage_fdn_list" msgid="3341716430375195441">"Спіс FDN"</string>
-    <string name="fdn_list_with_label" msgid="1409655283510382556">"Спіс закрытай абаненцкай групы (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
-    <string name="fdn_activation" msgid="2178637004710435895">"Актывацыя FDN"</string>
+    <string name="manage_fdn_list" msgid="3341716430375195441">"Спіс дазволеных нумароў"</string>
+    <string name="fdn_list_with_label" msgid="1409655283510382556">"Спіс дазволеных нумароў (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+    <string name="fdn_activation" msgid="2178637004710435895">"Актывацыя дазволеных нумароў"</string>
     <string name="fdn_enabled" msgid="7017355494808056447">"Фіксаваныя нумары ўключаны"</string>
     <string name="fdn_disabled" msgid="6696468878037736600">"Фіксаваныя нумары адключаны"</string>
-    <string name="enable_fdn" msgid="4830555730418033723">"Уключыць FDN"</string>
-    <string name="disable_fdn" msgid="3918794950264647541">"Адключыць FDN"</string>
+    <string name="enable_fdn" msgid="4830555730418033723">"Уключыць дазволеныя нумары"</string>
+    <string name="disable_fdn" msgid="3918794950264647541">"Адключыць дазволеныя нумары"</string>
     <string name="change_pin2" msgid="3110844547237754871">"Змяніць PIN2"</string>
-    <string name="enable_fdn_ok" msgid="5080925177369329827">"Адключыць FDN"</string>
-    <string name="disable_fdn_ok" msgid="3745475926874838676">"Уключыць FDN"</string>
+    <string name="enable_fdn_ok" msgid="5080925177369329827">"Адключыць дазволеныя нумары"</string>
+    <string name="disable_fdn_ok" msgid="3745475926874838676">"Уключыць дазволеныя нумары"</string>
     <string name="sum_fdn" msgid="6152246141642323582">"Кіраванне зафіксаванымі нумарамі"</string>
-    <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Змяніць PIN-код для доступу FDN"</string>
+    <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Змяніць PIN-код для доступу да дазволеных нумароў"</string>
     <string name="sum_fdn_manage_list" msgid="3311397063233992907">"Кіраванне спісам тэлефонных нумароў"</string>
     <string name="voice_privacy" msgid="7346935172372181951">"Палiтыка прыватнасцi Voice"</string>
     <string name="voice_privacy_summary" msgid="3556460926168473346">"Уключыць пашыраны рэжым прыватнасці"</string>
@@ -475,10 +475,10 @@
     <string name="delete_fdn_contact" msgid="7027405651994507077">"Выдаліць дазволены нумар"</string>
     <string name="deleting_fdn_contact" msgid="6872320570844460428">"Выдаленне дазволенага нумару..."</string>
     <string name="fdn_contact_deleted" msgid="1680714996763848838">"Дазволены нумар выдалены."</string>
-    <string name="pin2_invalid" msgid="2313954262684494442">"FDN не быў абноўлены, таму што вы набралі няправільны PIN-код."</string>
-    <string name="fdn_invalid_number" msgid="9067189814657840439">"Фіксаваны нумар не абноўлены, бо не можа складацца больш чым з <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> лічбаў."</string>
+    <string name="pin2_invalid" msgid="2313954262684494442">"Дазволены нумар не быў абноўлены, таму што вы набралі няправільны PIN-код."</string>
+    <string name="fdn_invalid_number" msgid="9067189814657840439">"Дазволены нумар не абноўлены, бо не можа складацца больш чым з <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> лічбаў."</string>
     <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"Cпiс дазволеных нумароў не адноўлены. PIN2 ўведзены няправiльна, або нумар быў адхiлены."</string>
-    <string name="fdn_failed" msgid="216592346853420250">"Аперацыя ў закрытай абаненцкай групе не ўдалася."</string>
+    <string name="fdn_failed" msgid="216592346853420250">"Аперацыя з дазволеным нумарам не ўдалася."</string>
     <string name="simContacts_emptyLoading" msgid="4989040293858675483">"Чытанне з SIM-карты..."</string>
     <string name="simContacts_empty" msgid="1135632055473689521">"На вашай SIM-карце няма кантактаў."</string>
     <string name="simContacts_title" msgid="2714029230160136647">"Выберыце кантакты для імпарту"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index d12f9c0..5c5deba 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -575,7 +575,7 @@
     <string name="fire_type_description" msgid="6565200468934914930">"Bomberos"</string>
     <string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
     <string name="dialerKeyboardHintText" msgid="1115266533703764049">"Utilizar teclado para marcar"</string>
-    <string name="onscreenHoldText" msgid="4025348842151665191">"Retener"</string>
+    <string name="onscreenHoldText" msgid="4025348842151665191">"Pausar"</string>
     <string name="onscreenEndCallText" msgid="6138725377654842757">"Finalizar"</string>
     <string name="onscreenShowDialpadText" msgid="658465753816164079">"Teclado telefónico"</string>
     <string name="onscreenMuteText" msgid="5470306116733843621">"Silenciar"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index da4d2d0..75d461a 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -92,7 +92,7 @@
     <string name="additional_cdma_call_settings" msgid="2178016561980611304">"CDMA deien ezarpen gehigarriak"</string>
     <string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA soilik motako deietarako ezarpen gehigarriak"</string>
     <string name="labelNwService" msgid="6015891883487125120">"Sareko zerbitzuen ezarpenak"</string>
-    <string name="labelCallerId" msgid="2090540744550903172">"Deitzailearen IDa"</string>
+    <string name="labelCallerId" msgid="2090540744550903172">"Deitzailearen identitatea"</string>
     <string name="sum_loading_settings" msgid="434063780286688775">"Ezarpenak kargatzen…"</string>
     <string name="sum_hide_caller_id" msgid="131100328602371933">"Ezkutatu zenbakia irteerako deietan"</string>
     <string name="sum_show_caller_id" msgid="3571854755324664591">"Erakutsi zenbakia irteerako deietan"</string>
@@ -534,7 +534,7 @@
     <string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"Erantzungailuaren zenbakia ezezaguna da"</string>
     <string name="notification_network_selection_title" msgid="255595526707809121">"Ez dago zerbitzurik"</string>
     <string name="notification_network_selection_text" msgid="553288408722427659">"Hautatutako sarea (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) ez dago erabilgarri"</string>
-    <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Deitzeko, aktibatu sare mugikorra, desaktibatu hegaldi modua edo desaktibatu bateria-aurrezlea."</string>
+    <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Deitzeko, aktibatu sare mugikorra, desaktibatu hegaldi modua edo desaktibatu bateria-aurreztailea."</string>
     <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Deia egiteko, desaktibatu hegaldi modua."</string>
     <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Deia egiteko, desaktibatu hegaldi modua edo konektatu haririk gabeko sare batera."</string>
     <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonoa beroegi dago"</b>\n\n"Ezin da egin deia. Saiatu berriro telefonoa hozten denean.\n\nHala ere, larrialdi-deiak egin ditzakezu."</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index c59cdbe..7c1f1f0 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -893,8 +893,8 @@
     <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Ohita verkon tyyppi:"</string>
     <string name="phone_index_label" msgid="6222406512768964268">"Valitse puhelimen hakemisto"</string>
     <string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Aseta ensisijainen verkon tyyppi:"</string>
-    <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping-kutsu isäntänimelle (www.google.com), IPv4:"</string>
-    <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping-kutsu isäntänimelle (www.google.com), IPv6:"</string>
+    <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping isäntänimelle (www.google.com), IPv4:"</string>
+    <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping isäntänimelle (www.google.com), IPv6:"</string>
     <string name="radio_info_http_client_test" msgid="1329583721088428238">"HTTP-asiakastesti:"</string>
     <string name="ping_test_label" msgid="448617502935719694">"Suorita ping-testi"</string>
     <string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index a20486f..02b298f 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -674,7 +674,7 @@
     <string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Aksesibilitas"</string>
     <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Panggilan Wi-Fi dari"</string>
     <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Panggilan Wi-Fi"</string>
-    <string name="message_decode_error" msgid="1061856591500290887">"Terjadi kesalahan saat mendekode pesan."</string>
+    <string name="message_decode_error" msgid="1061856591500290887">"Terjadi error saat mendekode pesan."</string>
     <string name="callFailed_cdma_activation" msgid="5392057031552253550">"Kartu SIM telah mengaktifkan layanan dan memperbarui kemampuan roaming ponsel."</string>
     <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Ada terlalu banyak panggilan aktif. Akhiri atau gabungkan panggilan yang ada sebelum melakukan panggilan baru."</string>
     <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Tidak dapat terhubung, masukkan kartu SIM yang valid."</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index e11daad..7d8ba9d 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"Dati cellulare"</string>
-    <string name="phoneAppLabel" product="default" msgid="130465039375347763">"Phone Services"</string>
+    <string name="phoneAppLabel" product="default" msgid="130465039375347763">"Servizi telefonici"</string>
     <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Chiamata di emergenza"</string>
     <string name="phoneIconLabel" msgid="3015941229249651419">"Telefono"</string>
     <string name="fdnListLabel" msgid="4119121875004244097">"Elenco numeri consentiti"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index af5a8ea..a5050d2 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -545,7 +545,7 @@
     <string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"कॉल करण्यासाठी, एक वैध नंबर एंटर करा."</string>
     <string name="incall_error_call_failed" msgid="393508653582682539">"कॉल अयशस्वी झाला."</string>
     <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"या वेळी कॉल जोडू शकत नाही. तुम्ही मेसेज पाठवून संपर्क करण्याचा प्रयत्न करू शकता."</string>
-    <string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"सेवा समर्थित नाही"</string>
+    <string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"सेवेला सपोर्ट नाही"</string>
     <string name="incall_error_supp_service_switch" msgid="5272822448189448479">"कॉल स्विच करू शकत नाही."</string>
     <string name="incall_error_supp_service_resume" msgid="1276861499306817035">"कॉल पुन्‍हा सुरू करू शकत नाही."</string>
     <string name="incall_error_supp_service_separate" msgid="8932660028965274353">"कॉल विभक्त करू शकत नाही."</string>
@@ -655,7 +655,7 @@
     <string name="contactPhoto" msgid="7885089213135154834">"संपर्क फोटो"</string>
     <string name="goPrivate" msgid="4645108311382209551">"खाजगी जा"</string>
     <string name="selectContact" msgid="1527612842599767382">"संपर्क निवडा"</string>
-    <string name="not_voice_capable" msgid="2819996734252084253">"व्‍हॉइस कॉलिंंग समर्थित नाही"</string>
+    <string name="not_voice_capable" msgid="2819996734252084253">"व्‍हॉइस कॉलिंंग याला सपोर्ट नाही"</string>
     <string name="description_dial_button" msgid="8614631902795087259">"डायल करा"</string>
     <string name="description_dialpad_button" msgid="7395114120463883623">"डायलपॅड दाखवा"</string>
     <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"आणीबाणी डायलपॅड"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index b8de8d7..36fd00f 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -156,8 +156,8 @@
     <item msgid="9150034130629852635">"ସଂଖ୍ୟାକୁ ଦେଖାନ୍ତୁ"</item>
   </string-array>
     <string name="vm_changed" msgid="4739599044379692505">"ଭଏସମେଲ୍ ନମ୍ବର୍ ବଦଳିଗଲା।"</string>
-    <string name="vm_change_failed" msgid="7877733929455763566">"ଭଏସମେଲ୍ ନମ୍ବର୍ ବଦଳାଯାଇପାରିଲା ନାହିଁ। \nଯଦି ଏହି ସମସ୍ୟା ଜାରିରୁହେ ତେବେ ନିଜର କେରିଅର୍‌ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
-    <string name="fw_change_failed" msgid="9179241823460192148">"ଫଏ‌ୱାର୍ଡିଙ୍ଗ ନମ୍ବର୍‌କୁ ବଦଳାଇହେଲା ନାହିଁ। \n ଯଦି ଏହି ସମସ୍ୟା ଜାରିରୁହେ ତେବେ ନିଜର କେରିଅର୍‌ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
+    <string name="vm_change_failed" msgid="7877733929455763566">"ଭଏସମେଲ ନମ୍ବର ବଦଳାଯାଇପାରିଲା ନାହିଁ। \nଯଦି ଏହି ସମସ୍ୟା ଜାରି ରୁହେ ତେବେ ନିଜର କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+    <string name="fw_change_failed" msgid="9179241823460192148">"ଫରୱାର୍ଡିଙ୍ଗ ନମ୍ବରକୁ ବଦଳାଯାଇପାରିଲା ନାହିଁ। \n ଯଦି ଏହି ସମସ୍ୟା ଜାରି ରୁହେ ତେବେ ନିଜର କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <string name="fw_get_in_vm_failed" msgid="2432678237218183844">"ବର୍ତ୍ତମାନର ଫରୱାର୍ଡିଂ ନମ୍ବର ସେଟିଂସକୁ ପୁନରୁଦ୍ଧାର ଓ ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। \nନୂଆ ପ୍ରଦାନକାରୀକୁ ଯେ କୌଣସି ମତେ ସ୍ଵିଚ କରିବେ?"</string>
     <string name="no_change" msgid="3737264882821031892">"କୌଣସି ପରିବର୍ତ୍ତନ କରାଯାଇନାହିଁ|"</string>
     <string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"ଭଏସ୍‌ମେଲ୍ ସେବାକୁ ଚୟନ କରନ୍ତୁ"</string>
@@ -419,7 +419,7 @@
     <string name="cdma_system_select_summary" msgid="3840420390242060407">"CDMAର ରୋମିଙ୍ଗ ମୋଡ୍‌କୁ ବଦଳାନ୍ତୁ"</string>
     <string name="cdma_system_select_dialogtitle" msgid="5524639510676501802">"ସିଷ୍ଟମ୍‌ ଚୟନ କରନ୍ତୁ"</string>
   <string-array name="cdma_system_select_choices">
-    <item msgid="462340042928284921">"କେବଳ ହୋମ୍"</item>
+    <item msgid="462340042928284921">"କେବଳ ହୋମ"</item>
     <item msgid="6058010046783562674">"ସ୍ଵଚାଳିତ"</item>
   </string-array>
     <string name="cdma_subscription_title" msgid="3449527179325589434">"CDMA ସବସ୍କ୍ରିପଶନ୍"</string>
@@ -458,10 +458,10 @@
     <string name="auto_retry_mode_title" msgid="2985801935424422340">"ଅଟୋ-ରିଟ୍ରାଏ କରନ୍ତୁ"</string>
     <string name="auto_retry_mode_summary" msgid="2863919925349511402">"ଅଟୋ-ରିଟ୍ରାଏ ମୋଡ୍‌କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"ଭିଡିଓ କଲ୍ କରିବା ସମୟରେ TTY ମୋଡ୍‌କୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଅନୁମତି ନାହିଁ"</string>
-    <string name="menu_add" msgid="5616487894975773141">"ଯୋଗାଯୋଗକୁ ଯୋଗ କରନ୍ତୁ"</string>
-    <string name="menu_edit" msgid="3593856941552460706">"ଯୋଗାଯୋଗ ଏଡିଟ କରନ୍ତୁ"</string>
-    <string name="menu_delete" msgid="6326861853830546488">"ଯୋଗାଯୋଗକୁ ଡିଲିଟ୍ କରନ୍ତୁ"</string>
-    <string name="menu_dial" msgid="4178537318419450012">"ଯୋଗାଯୋଗକୁ ଡାଏଲ୍ କରନ୍ତୁ"</string>
+    <string name="menu_add" msgid="5616487894975773141">"କଣ୍ଟାକ୍ଟ ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="menu_edit" msgid="3593856941552460706">"କଣ୍ଟାକ୍ଟ ଏଡିଟ କରନ୍ତୁ"</string>
+    <string name="menu_delete" msgid="6326861853830546488">"କଣ୍ଟାକ୍ଟ ଡିଲିଟ କରନ୍ତୁ"</string>
+    <string name="menu_dial" msgid="4178537318419450012">"କଣ୍ଟାକ୍ଟ ଡାଏଲ କରନ୍ତୁ"</string>
     <string name="get_pin2" msgid="4221654606863196332">"PIN2 ଟାଇପ୍ କରନ୍ତୁ"</string>
     <string name="name" msgid="1347432469852527784">"ନାମ"</string>
     <string name="number" msgid="1564053487748491000">"ନମ୍ବର୍‌"</string>
@@ -515,7 +515,7 @@
     <string name="puk2_requested" msgid="6992374450720307514">"ଭୁଲ୍ ପାସ୍‌ୱର୍ଡ। ବର୍ତ୍ତମାନ SIM ଲକ୍ ହୋ‌ଇଗଲା। PUK2କୁ ପ୍ରବେଶ କରନ୍ତୁ।"</string>
     <string name="puk2_blocked" msgid="3131139031779319911">"PUK2କୁ ସ୍ଥାୟୀରୂପେ ଅବରୋଧ କରାଯାଇଛି।"</string>
     <string name="pin2_attempts" msgid="5625178102026453023">\n"ଆପଣଙ୍କର <xliff:g id="NUMBER">%d</xliff:g>ଟି ସୁଯୋଗ ବଳକା ଅଛି।"</string>
-    <string name="puk2_locked" msgid="6497760825455461057">"PUK2 ଲକ୍ କରାଯାଇଛି। ଅନଲକ୍ କରିବାକୁ ସେବା ପ୍ରଦାନକାରୀ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+    <string name="puk2_locked" msgid="6497760825455461057">"PUK2 ଲକ କରାଯାଇଛି। ଅନଲକ କରିବାକୁ ସେବା ପ୍ରଦାନକାରୀ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <string name="pin2_unblocked" msgid="4481107908727789303">"PIN2କୁ ଆଉ ଅବରୋଧ କରାଯାଇନାହିଁ"</string>
     <string name="pin2_error_exception" msgid="8116103864600823641">"ନେଟ୍‌ୱର୍କ କିମ୍ବା SIM କାର୍ଡ ତ୍ରୁଟି"</string>
     <string name="doneButton" msgid="7371209609238460207">"ହୋଇଗଲା"</string>
@@ -590,8 +590,8 @@
     <string name="importAllSimEntries" msgid="2628391505643564007">"ସମସ୍ତ ଇମ୍ପୋର୍ଟ କରନ୍ତୁ"</string>
     <string name="importingSimContacts" msgid="4995457122107888932">"SIMରେ ଥିବା ଯୋଗାଯୋଗକୁ ଇମ୍ପୋର୍ଟ କରାଯାଉଛି"</string>
     <string name="importToFDNfromContacts" msgid="5068664870738407341">"ଯୋଗଯୋଗରୁ ଇମ୍ପୋର୍ଟ କରନ୍ତୁ"</string>
-    <string name="singleContactImportedMsg" msgid="3619804066300998934">"ଇମ୍ପୋର୍ଟ କରାଯାଇଥିବା ଯୋଗାଯୋଗ"</string>
-    <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"ଯୋଗଯୋଗକୁ ଇମ୍ପୋର୍ଟ କରିବାରେ ବିଫଳ ହେଲା"</string>
+    <string name="singleContactImportedMsg" msgid="3619804066300998934">"ଇମ୍ପୋର୍ଟ କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ"</string>
+    <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"କଣ୍ଟାକ୍ଟକୁ ଇମ୍ପୋର୍ଟ କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
     <string name="hac_mode_title" msgid="4127986689621125468">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
     <string name="hac_mode_summary" msgid="7774989500136009881">"ଶ୍ରବଣ ଯନ୍ତ୍ର କମ୍ପ୍ୟାଟିବିଲିଟୀକୁ ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="rtt_mode_title" msgid="3075948111362818043">"ରିଅଲ୍-ଟାଇମ୍ ଟେକ୍ସଟ୍ (RTT) କଲ୍"</string>
@@ -652,9 +652,9 @@
     <string name="voicemail_number_not_set" msgid="8831561283386938155">"&lt;ସେଟ୍ ହୋ‌ଇନାହିଁ&gt;"</string>
     <string name="other_settings" msgid="8895088007393598447">"ଅନ୍ୟାନ୍ୟ କଲ୍‌ ସେଟିଙ୍ଗ"</string>
     <string name="calling_via_template" msgid="1791323450703751750">"<xliff:g id="PROVIDER_NAME">%s</xliff:g> ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
-    <string name="contactPhoto" msgid="7885089213135154834">"ଯୋଗାଯୋଗ ଫଟୋ"</string>
+    <string name="contactPhoto" msgid="7885089213135154834">"କଣ୍ଟାକ୍ଟ ଫଟୋ"</string>
     <string name="goPrivate" msgid="4645108311382209551">"ବ୍ୟକ୍ତିଗତ ହୁଅନ୍ତୁ"</string>
-    <string name="selectContact" msgid="1527612842599767382">"ଯୋଗାଯୋଗକୁ ଚୟନ କରନ୍ତୁ"</string>
+    <string name="selectContact" msgid="1527612842599767382">"କଣ୍ଟାକ୍ଟ ଚୟନ କରନ୍ତୁ"</string>
     <string name="not_voice_capable" msgid="2819996734252084253">"ଭଏସ୍ କଲ୍ ସପୋର୍ଟ କରୁନାହିଁ"</string>
     <string name="description_dial_button" msgid="8614631902795087259">"ଡାଏଲ୍ କରନ୍ତୁ"</string>
     <string name="description_dialpad_button" msgid="7395114120463883623">"ଡାୟଲ୍‍ପ୍ୟାଡ୍‍ ଦେଖାନ୍ତୁ"</string>
@@ -795,7 +795,7 @@
     <string name="messageCallBarring" msgid="5537730400652466912">"ପାସ୍‌ୱର୍ଡ ପ୍ରବେଶ କରନ୍ତୁ"</string>
     <string name="call_barring_settings" msgid="4616607285790258919">"କଲ୍ ରୋକିବା ସେଟିଙ୍ଗ"</string>
     <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"ନେଟ୍‌ୱର୍କ ବ୍ୟସ୍ତ ଅଛି। ଦୟାକରି ଆପଣ ପରେ ପୁଣି କଲ୍‌ ଚେଷ୍ଟା କରିବା ପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"ନେଟ୍‌ୱର୍କ ବ୍ୟସ୍ତ ଅଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କର ମୋବାଇଲ୍ ଅପରେଟର୍‍ଙ୍କୁ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+    <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"ନେଟୱାର୍କ ବ୍ୟସ୍ତ ଅଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କର ମୋବାଇଲ ଅପରେଟରଙ୍କୁ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"କଲ୍ ଅନ୍ୟ ପାଖକୁ ଯିବା ବଦଳରେ ନିଜ ପାଖକୁ ଆସିଯାଇଛି।"</string>
     <string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"କଲ୍‌କୁ ଫରୱାର୍ଡ କରାଯାଇଛି।"</string>
     <string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"କଲ୍ ଅପେକ୍ଷାରେ ଅଛି।"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index edc71b3..581b586 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -47,7 +47,7 @@
     <string name="no_vm_number" msgid="6623853880546176930">"వాయిస్ మెయిల్ నంబర్ లేదు"</string>
     <string name="no_vm_number_msg" msgid="5165161462411372504">"సిమ్ కార్డులో వాయిస్ మెయిల్ నంబర్ ఏదీ నిల్వ చేయబడలేదు."</string>
     <string name="add_vm_number_str" msgid="7368168964435881637">"నంబర్‌ను జోడించు"</string>
-    <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"వాయిస్ మెయిల్ సెట్టింగ్‌లను ప్రాథమిక వినియోగదారు మాత్రమే సవరించగలరు."</string>
+    <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"వాయిస్ మెయిల్ సెట్టింగ్‌లను ప్రాథమిక వినియోగదారు మాత్రమే ఎడిట్ చేయగలరు."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"మీ SIM కార్డు అన్‌బ్లాక్ చేయబడింది. మీ ఫోన్ అన్‌లాక్ చేయబడుతోంది…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM నెట్‌వర్క్ అన్‌లాక్ పిన్‌"</string>
     <string name="label_phoneid" msgid="8775611434123577808">"ఈ ఆపరేటర్‌కు సంబంధించి SIM లాక్ చేయబడింది"</string>
@@ -105,23 +105,23 @@
     <string name="labelCF" msgid="3578719437928476078">"కాల్ ఫార్వార్డింగ్"</string>
     <string name="labelCFU" msgid="8870170873036279706">"ఎల్లప్పుడూ ఫార్వర్డ్ చేయి"</string>
     <string name="messageCFU" msgid="1361806450979589744">"ఎల్లప్పుడూ ఈ నంబర్‌ను ఉపయోగించు"</string>
-    <string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"అన్ని కాల్స్‌ను ఫార్వార్డ్ చేస్తోంది"</string>
-    <string name="sum_cfu_enabled" msgid="5806923046528144526">"అన్ని కాల్స్‌ను <xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+    <string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"అన్ని కాల్స్‌ను ఫార్వర్డ్ చేస్తోంది"</string>
+    <string name="sum_cfu_enabled" msgid="5806923046528144526">"అన్ని కాల్స్‌ను <xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
     <string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"నంబర్ అందుబాటులో లేదు"</string>
     <string name="sum_cfu_disabled" msgid="5010617134210809853">"ఆఫ్‌లో ఉంది"</string>
     <string name="labelCFB" msgid="615265213360512768">"బిజీగా ఉన్నప్పుడు"</string>
     <string name="messageCFB" msgid="1958017270393563388">"బిజీగా ఉన్నప్పుడు ఫార్వర్డ్ చేయాల్సిన నంబర్"</string>
-    <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+    <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
     <string name="sum_cfb_disabled" msgid="3589913334164866035">"ఆఫ్‌లో ఉంది"</string>
     <string name="disable_cfb_forbidden" msgid="4831494744351633961">"మీ ఫోన్ బిజీగా ఉన్నప్పుడు కాల్ ఫార్వర్డింగ్‌ను నిలిపివేయడానికి మీ ఆపరేటర్ మద్దతు ఇవ్వరు."</string>
     <string name="labelCFNRy" msgid="3403533792248457946">"సమాధానం ఇవ్వనప్పుడు"</string>
     <string name="messageCFNRy" msgid="7644434155765359009">"సమాధానం ఇవ్వనప్పుడు నంబర్"</string>
-    <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+    <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
     <string name="sum_cfnry_disabled" msgid="1990563512406017880">"ఆఫ్‌లో ఉంది"</string>
     <string name="disable_cfnry_forbidden" msgid="3174731413216550689">"మీ ఫోన్ సమాధానం ఇవ్వలేనప్పుడు కాల్ ఫార్వర్డింగ్‌ను నిలిపివేయడానికి మీ ఆపరేటర్ మద్దతు ఇవ్వరు."</string>
     <string name="labelCFNRc" msgid="4163399350778066013">"చేరుకోలేనప్పుడు"</string>
     <string name="messageCFNRc" msgid="6980340731313007250">"చేరుకోవడం సాధ్యపడనప్పుడు నంబర్"</string>
-    <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+    <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"ఆఫ్‌లో ఉంది"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"మీ ఫోన్‌ను చేరుకోవడం సాధ్యపడనప్పుడు కాల్ ఫార్వర్డింగ్‌ను నిలిపివేయడానికి మీ క్యారియర్ మద్దతు ఇవ్వదు."</string>
     <string name="registration_cf_forbidden" msgid="4386482610771190420">"కాల్ ఫార్వర్డింగ్‌ను మీ క్యారియర్ సపోర్ట్ చేయదు."</string>
@@ -145,7 +145,7 @@
     <string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"కొత్త SS రిక్వెస్ట్‌కు మార్చబడింది"</string>
     <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS రిక్వెస్ట్‌ వీడియో కాల్‌కి మార్చబడింది"</string>
     <string name="fdn_check_failure" msgid="1833769746374185247">"మీ ఫోన్ యాప్‌ యొక్క ఫిక్స్‌డ్ డయలింగ్ నంబర్‌ల సెట్టింగ్ ప్రారంభించబడింది. తత్ఫలితంగా, కాల్ సంబంధిత లక్షణాల్లో కొన్ని పని చేయడం లేదు."</string>
-    <string name="radio_off_error" msgid="8321564164914232181">"ఈ సెట్టింగ్‌లను వీక్షించడానికి ముందు రేడియోను ప్రారంభించండి."</string>
+    <string name="radio_off_error" msgid="8321564164914232181">"ఈ సెట్టింగ్‌లను చూడటానికి ముందు రేడియోను ప్రారంభించండి."</string>
     <string name="close_dialog" msgid="1074977476136119408">"సరే"</string>
     <string name="enable" msgid="2636552299455477603">"ఆన్ చేయి"</string>
     <string name="disable" msgid="1122698860799462116">"ఆఫ్ చేయి"</string>
@@ -471,13 +471,13 @@
     <string name="fdn_contact_added" msgid="2840016151693394596">"ఫిక్స్‌డ్ డయలింగ్ నంబర్ జోడించబడింది."</string>
     <string name="edit_fdn_contact" msgid="6030829994819587408">"ఫిక్స్‌డ్ డయలింగ్ నంబర్‌ను ఎడిట్ చేయండి"</string>
     <string name="updating_fdn_contact" msgid="6989341376868227150">"ఫిక్స్‌డ్ డయలింగ్ నంబర్‌ను అప్‌డేట్ చేస్తోంది..."</string>
-    <string name="fdn_contact_updated" msgid="6876330243323118937">"ఫిక్స్‌డ్ డయలింగ్ నంబర్ నవీకరించబడింది."</string>
+    <string name="fdn_contact_updated" msgid="6876330243323118937">"ఫిక్స్‌డ్ డయలింగ్ నంబర్ అప్‌డేట్ చేయబడింది."</string>
     <string name="delete_fdn_contact" msgid="7027405651994507077">"ఫిక్స్‌డ్ డయలింగ్ నంబర్‌ను తొలగించండి"</string>
     <string name="deleting_fdn_contact" msgid="6872320570844460428">"ఫిక్స్‌డ్ డయలింగ్ నంబర్‌ను తొలగిస్తోంది..."</string>
     <string name="fdn_contact_deleted" msgid="1680714996763848838">"ఫిక్స్‌డ్ డయలింగ్ నంబర్ తొలగించబడింది."</string>
-    <string name="pin2_invalid" msgid="2313954262684494442">"మీరు చెల్లని PINను టైప్ చేసినందున FDN నవీకరించబడలేదు."</string>
+    <string name="pin2_invalid" msgid="2313954262684494442">"మీరు చెల్లని PINను టైప్ చేసినందున FDN అప్‌డేట్ చేయబడలేదు."</string>
     <string name="fdn_invalid_number" msgid="9067189814657840439">"నంబర్ <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> అంకెలను మించినందున FDN అప్‌డేట్ చేయబడలేదు."</string>
-    <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN నవీకరించబడలేదు. PIN2 చెల్లదు లేదా ఫోన్ నంబర్ తిరస్కరించబడింది."</string>
+    <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN అప్‌డేట్ చేయబడలేదు. PIN2 చెల్లదు లేదా ఫోన్ నంబర్ తిరస్కరించబడింది."</string>
     <string name="fdn_failed" msgid="216592346853420250">"FDN చర్య విఫలమైంది."</string>
     <string name="simContacts_emptyLoading" msgid="4989040293858675483">"SIM కార్డు నుండి చదువుతోంది…"</string>
     <string name="simContacts_empty" msgid="1135632055473689521">"మీ SIM కార్డులో కాంటాక్ట్‌లు ఏవీ లేవు."</string>
@@ -498,7 +498,7 @@
     <string name="enable_pin_ok" msgid="2877428038280804256">"PIN సెట్ చేయబడింది"</string>
     <string name="disable_pin_ok" msgid="888505244389647754">"PIN తీసివేయబడింది"</string>
     <string name="pin_failed" msgid="4527347792881939652">"PIN చెల్లదు"</string>
-    <string name="pin_changed" msgid="7291153750090452808">"PIN నవీకరించబడింది"</string>
+    <string name="pin_changed" msgid="7291153750090452808">"PIN అప్‌డేట్ చేయబడింది"</string>
     <string name="puk_requested" msgid="2061337960609806851">"పాస్‌వర్డ్ చెల్లదు. PIN ఇప్పుడు బ్లాక్ చేయబడింది. PUK రిక్వెస్ట్ చేయబడింది."</string>
     <string name="enter_pin2_text" msgid="7266379426804295979">"PIN2"</string>
     <string name="oldPin2Label" msgid="4648543187859997203">"పాత PIN2"</string>
@@ -509,7 +509,7 @@
     <string name="mismatchPin2" msgid="4952718725266700631">"PIN2లు సరిపోలలేదు. మళ్లీ ప్రయత్నించండి."</string>
     <string name="invalidPin2" msgid="6467957903056379343">"4 నుండి 8 సంఖ్యలు ఉండే PIN2ని నమోదు చేయండి."</string>
     <string name="invalidPuk2" msgid="713729511903849544">"8 సంఖ్యలు ఉండే PUK2ను నమోదు చేయండి."</string>
-    <string name="pin2_changed" msgid="5710551850481287821">"PIN2 నవీకరించబడింది"</string>
+    <string name="pin2_changed" msgid="5710551850481287821">"PIN2 అప్‌డేట్ చేయబడింది"</string>
     <string name="label_puk2_code" msgid="2852217004288085562">"PUK2 కోడ్‌ను నమోదు చేయండి"</string>
     <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"పాస్‌వర్డ్ చెల్లదు. PIN2 ఇప్పుడు బ్లాక్ చేయబడింది. మళ్లీ ప్రయత్నించడానికి, PIN 2ను మార్చండి."</string>
     <string name="puk2_requested" msgid="6992374450720307514">"పాస్‌వర్డ్ చెల్లదు. SIM ఇప్పుడు లాక్ చేయబడింది. PUK2ని నమోదు చేయండి."</string>
@@ -675,7 +675,7 @@
     <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"వీరి నుండి Wi-Fi కాల్"</string>
     <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi కాల్"</string>
     <string name="message_decode_error" msgid="1061856591500290887">"మెసేజ్‌ను డీకోడ్ చేస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది."</string>
-    <string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM కార్డ్ మీ సేవను సక్రియం చేసింది మరియు మీ ఫోన్ రోమింగ్ సామర్థ్యాలను నవీకరించింది."</string>
+    <string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM కార్డ్ మీ సేవను సక్రియం చేసింది మరియు మీ ఫోన్ రోమింగ్ సామర్థ్యాలను అప్‌డేట్ చేసింది."</string>
     <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"చాలా ఎక్కువ కాల్స్‌ యాక్టివ్‌గా ఉన్నాయి. దయచేసి మరొక కొత్త కాల్ చేసే ముందు ఇప్పటికే ఉన్న కాల్స్‌ను ముగించండి లేదా విలీనం చేయండి."</string>
     <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"కనెక్ట్ చేయడం సాధ్యపడలేదు, దయచేసి చెల్లుబాటు అయ్యే SIM కార్డ్‌ను చొప్పించండి."</string>
     <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi కనెక్షన్ పోయింది. కాల్ ముగిసింది."</string>
@@ -693,7 +693,7 @@
     <string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"PIN తప్పనిసరిగా <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> అంకెల మధ్య ఉండాలి."</string>
     <string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"మీ PINని నిర్ధారించండి"</string>
     <string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"PINలు సరిపోలలేదు"</string>
-    <string name="change_pin_succeeded" msgid="2504705600693014403">"వాయిస్ మెయిల్ PIN నవీకరించబడింది"</string>
+    <string name="change_pin_succeeded" msgid="2504705600693014403">"వాయిస్ మెయిల్ PIN అప్‌డేట్ చేయబడింది"</string>
     <string name="change_pin_system_error" msgid="7772788809875146873">"PINని సెట్ చేయడం సాధ్యపడలేదు"</string>
     <string name="mobile_data_status_roaming_turned_off_subtext" msgid="6840673347416227054">"డేటా రోమింగ్ ఆఫ్ చేయబడింది"</string>
     <string name="mobile_data_status_roaming_turned_on_subtext" msgid="5615757897768777865">"డేటా రోమింగ్ ఆన్ చేయబడింది"</string>
@@ -797,20 +797,20 @@
     <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"నెట్‌వర్క్ బిజీగా ఉంది. దయచేసి తిరిగి తర్వాత కాల్ చేయండి."</string>
     <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"నెట్‌వర్క్‌లో అంతరాయం ఏర్పడింది. సహాయం కోసం మీ మొబైల్ ఆపరేటర్‌ను సంప్రదించండి."</string>
     <string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"కాల్ మళ్లించబడింది."</string>
-    <string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+    <string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"కాల్ ఫార్వర్డ్ చేయబడింది."</string>
     <string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"కాల్ నిరీక్షణలో ఉంది."</string>
     <string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"నంబర్ బ్లాకింగ్ తిరస్కరించబడింది."</string>
     <string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"దగ్గరి వినియోగదారు సమూహ కాల్."</string>
     <string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"ఇన్‌కమింగ్ కాల్స్‌ నిరోధించబడ్డాయి"</string>
     <string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"అవుట్‌గోయింగ్ కాల్స్‌ నిరోధించబడ్డాయి."</string>
     <string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"కాల్ ఫార్వర్డింగ్ యాక్టివ్‌గా ఉంది."</string>
-    <string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"అదనపు కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+    <string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"అదనపు కాల్ ఫార్వర్డ్ చేయబడింది."</string>
     <string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"అభ్యంతరకరమైన కాల్ బదిలీ పూర్తయింది."</string>
     <string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"అభ్యంతరకరమైన కాల్ బదిలీ ప్రోగ్రెస్‌లో ఉంది."</string>
     <string name="supp_service_call_on_hold" msgid="2836811319594503059">"కాల్ హోల్డ్‌లో ఉంది."</string>
     <string name="supp_service_call_resumed" msgid="3786864005920743546">"కాల్ మళ్లీ ప్రారంభించబడింది."</string>
     <string name="supp_service_deflected_call" msgid="7565979024562921707">"కాల్ మళ్లించబడింది."</string>
-    <string name="supp_service_forwarded_call" msgid="6475776013771821457">"కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+    <string name="supp_service_forwarded_call" msgid="6475776013771821457">"కాల్ ఫార్వర్డ్ చేయబడింది."</string>
     <string name="supp_service_conference_call" msgid="4004193534408317148">"కాన్ఫరెన్స్ కాల్‌లో చేరుతున్నారు"</string>
     <string name="supp_service_held_call_released" msgid="2847835124639112410">"హోల్డ్‌లో ఉంచిన కాల్ ప్రారంభించబడింది."</string>
     <string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"వినియోగదారుకు ప్రస్తుతం ఏ సేవలు అందుబాటులో ఉన్నాయనే విచారణ పనిలో పరికరం ఉన్నందున కాల్ చేయడం సాధ్యం కాదు."</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 7f374a2..ef93cd6 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -585,7 +585,7 @@
     <string name="onscreenManageCallsText" msgid="1162047856081836469">"จัดการการโทร"</string>
     <string name="onscreenManageConferenceText" msgid="4700574060601755137">"จัดการการประชุม"</string>
     <string name="onscreenAudioText" msgid="7224226735052019986">"เสียง"</string>
-    <string name="onscreenVideoCallText" msgid="1743992456126258698">" Hangouts วิดีโอ"</string>
+    <string name="onscreenVideoCallText" msgid="1743992456126258698">"วิดีโอคอล"</string>
     <string name="importSimEntry" msgid="3892354284082689894">"นำเข้า"</string>
     <string name="importAllSimEntries" msgid="2628391505643564007">"นำเข้าทั้งหมด"</string>
     <string name="importingSimContacts" msgid="4995457122107888932">"กำลังนำเข้าสมุดโทรศัพท์ในซิม"</string>
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index fdd610e..7bff98a 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -456,7 +456,11 @@
                     CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
                     false);
         boolean isDataEnabled;
-        isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled();
+        if (mPhone.isUsingNewDataStack()) {
+            isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled();
+        } else {
+            isDataEnabled = mPhone.getDataEnabledSettings().isDataEnabled();
+        }
         if (mImsMgr.isVtEnabledByPlatform() && mImsMgr.isVtProvisionedOnDevice()
                 && (carrierConfig.getBoolean(
                         CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index cb774c7..5d9928e 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -1170,12 +1170,24 @@
         });
         if (packageFiles == null || packageFiles.length < 1) return false;
         for (File f : packageFiles) {
-            logd("Deleting " + f.getName());
+            logd("Deleting " + getFilePathForLogging(f.getName()));
             f.delete();
         }
         return true;
     }
 
+    private String getFilePathForLogging(String filePath) {
+        if (!TextUtils.isEmpty(filePath)) {
+            String[] fileTokens = filePath.split("-");
+            if (fileTokens != null && fileTokens.length > 2) {
+                String iccid = fileTokens[fileTokens.length -2];
+                return getFilePathForLogging(filePath, iccid);
+            }
+            return filePath;
+        }
+        return filePath;
+    }
+
     /** Builds a canonical file name for a config file. */
     @NonNull
     private static String getFilenameForConfig(
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index 696f567..6a6b155 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -41,6 +41,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.os.AsyncResult;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -55,6 +56,7 @@
 import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
 import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
 import android.telephony.ims.stub.ImsConfigImplBase;
@@ -89,6 +91,7 @@
     private static final int EVENT_PROVISIONING_CAPABILITY_CHANGED = 2;
     @VisibleForTesting
     protected static final int EVENT_MULTI_SIM_CONFIGURATION_CHANGE = 3;
+    private static final int EVENT_PROVISIONING_VALUE_CHANGED = 4;
 
     // Provisioning Keys that are handled via AOSP cache and not sent to the ImsService
     private static final int[] LOCAL_IMS_CONFIG_KEYS = {
@@ -245,6 +248,11 @@
                     int activeModemCount = (int) ((AsyncResult) msg.obj).result;
                     onMultiSimConfigChanged(activeModemCount);
                     break;
+                case EVENT_PROVISIONING_VALUE_CHANGED:
+                    log("subId " + msg.arg1 + " changed provisioning value item : " + msg.arg2
+                            + " value : " + (int) msg.obj);
+                    updateCapabilityTechFromKey(msg.arg1, msg.arg2, (int) msg.obj);
+                    break;
                 default:
                     log("unknown message " + msg);
                     break;
@@ -366,12 +374,15 @@
         private boolean mRequiredNotify = false;
         private int mSubId;
         private int mSlotId;
+        private ConfigCallback mConfigCallback;
 
         MmTelFeatureListener(int slotId) {
             log(LOG_PREFIX, slotId, "created");
 
             mSlotId = slotId;
             mSubId = getSubId(slotId);
+            mConfigCallback = new ConfigCallback(mSubId);
+
             mConnector = mMmTelFeatureConnector.create(
                     mApp, slotId, TAG, this, new HandlerExecutor(mHandler));
             mConnector.connect();
@@ -389,10 +400,22 @@
 
             mSubId = subId;
             mSlotId = getSlotId(subId);
+            mConfigCallback.setSubId(subId);
         }
 
         public void destroy() {
             log("destroy");
+            if (mImsManager != null) {
+                try {
+                    ImsConfig imsConfig = getImsConfig(mImsManager);
+                    if (imsConfig != null) {
+                        imsConfig.removeConfigCallback(mConfigCallback);
+                    }
+                } catch (ImsException e) {
+                    logw(LOG_PREFIX, mSlotId, "destroy : " + e.getMessage());
+                }
+            }
+            mConfigCallback = null;
             mConnector.disconnect();
             mConnector = null;
             mReady = false;
@@ -409,6 +432,17 @@
             mReady = true;
             mImsManager = manager;
 
+            if (mImsManager != null) {
+                try {
+                    ImsConfig imsConfig = getImsConfig(mImsManager);
+                    if (imsConfig != null) {
+                        imsConfig.addConfigCallback(mConfigCallback);
+                    }
+                } catch (ImsException e) {
+                    logw(LOG_PREFIX, mSlotId, "addConfigCallback : " + e.getMessage());
+                }
+            }
+
             onMmTelAvailable();
         }
 
@@ -572,12 +606,15 @@
         private boolean mRequiredNotify = false;
         private int mSubId;
         private int mSlotId;
+        private ConfigCallback mConfigCallback;
 
         RcsFeatureListener(int slotId) {
             log(LOG_PREFIX, slotId, "created");
 
             mSlotId = slotId;
             mSubId = getSubId(slotId);
+            mConfigCallback = new ConfigCallback(mSubId);
+
             mConnector = mRcsFeatureConnector.create(
                     mApp, slotId, this, new HandlerExecutor(mHandler), TAG);
             mConnector.connect();
@@ -595,10 +632,22 @@
 
             mSubId = subId;
             mSlotId = getSlotId(subId);
+            mConfigCallback.setSubId(subId);
         }
 
         public void destroy() {
             log(LOG_PREFIX, mSlotId, "destroy");
+            if (mRcsFeatureManager != null) {
+                try {
+                    ImsConfig imsConfig = getImsConfig(mRcsFeatureManager.getConfig());
+                    if (imsConfig != null) {
+                        imsConfig.removeConfigCallback(mConfigCallback);
+                    }
+                } catch (ImsException e) {
+                    logw(LOG_PREFIX, mSlotId, "destroy :" + e.getMessage());
+                }
+            }
+            mConfigCallback = null;
             mConnector.disconnect();
             mConnector = null;
             mReady = false;
@@ -611,6 +660,17 @@
             mReady = true;
             mRcsFeatureManager = manager;
 
+            if (mRcsFeatureManager != null) {
+                try {
+                    ImsConfig imsConfig = getImsConfig(mRcsFeatureManager.getConfig());
+                    if (imsConfig != null) {
+                        imsConfig.addConfigCallback(mConfigCallback);
+                    }
+                } catch (ImsException e) {
+                    logw(LOG_PREFIX, mSlotId, "addConfigCallback :" + e.getMessage());
+                }
+            }
+
             onRcsAvailable();
         }
 
@@ -726,6 +786,42 @@
         }
     }
 
+    // When vendor ImsService changed provisioning data, which should be updated in AOSP.
+    // Catch the event using IImsConfigCallback.
+    private final class ConfigCallback extends IImsConfigCallback.Stub {
+        private int mSubId;
+
+        ConfigCallback(int subId) {
+            mSubId = subId;
+        }
+
+        public void setSubId(int subId) {
+            mSubId = subId;
+        }
+
+        @Override
+        public void onIntConfigChanged(int item, int value) throws RemoteException {
+            if (!Arrays.stream(LOCAL_IMS_CONFIG_KEYS).anyMatch(keyValue -> keyValue == item)) {
+                return;
+            }
+
+            final long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                if (mHandler != null) {
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            EVENT_PROVISIONING_VALUE_CHANGED, mSubId, item, (Object) value));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @Override
+        public void onStringConfigChanged(int item, String value) throws RemoteException {
+            // Ignore this callback.
+        }
+    }
+
     /**
      * Do NOT use this directly, instead use {@link #getInstance()}.
      */
diff --git a/src/com/android/phone/ImsStateCallbackController.java b/src/com/android/phone/ImsStateCallbackController.java
index 57c1787..edad754 100644
--- a/src/com/android/phone/ImsStateCallbackController.java
+++ b/src/com/android/phone/ImsStateCallbackController.java
@@ -68,6 +68,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 
 /**
@@ -143,6 +144,10 @@
     private final SparseArray<MmTelFeatureListener> mMmTelFeatureListeners = new SparseArray<>();
     private final SparseArray<RcsFeatureListener> mRcsFeatureListeners = new SparseArray<>();
 
+    // Container to store ImsManager instance by subId
+    private final ConcurrentHashMap<Integer, ImsManager> mSubIdToImsManagerCache =
+            new ConcurrentHashMap<>();
+
     private final SubscriptionManager mSubscriptionManager;
     private final TelephonyRegistryManager mTelephonyRegistryManager;
     private MmTelFeatureConnectorFactory mMmTelFeatureFactory;
@@ -282,6 +287,13 @@
             if (mSubId == subId) return;
             logd(mLogPrefix + "setSubId changed subId=" + subId);
 
+            // subId changed from valid to invalid
+            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                if (VDBG) logv(mLogPrefix + "setSubId remove ImsManager " + mSubId);
+                // remove ImsManager reference associated with subId
+                mSubIdToImsManagerCache.remove(mSubId);
+            }
+
             mSubId = subId;
         }
 
@@ -298,6 +310,12 @@
             mSubId = subId;
             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return;
 
+            // store ImsManager reference associated with subId
+            if (manager != null) {
+                if (VDBG) logv(mLogPrefix + "connectionReady add ImsManager " + subId);
+                mSubIdToImsManagerCache.put(subId, manager);
+            }
+
             mState = STATE_READY;
             mReason = AVAILABLE;
             mHasConfig = true;
@@ -311,6 +329,10 @@
             reason = convertReasonType(reason);
             if (mReason == reason) return;
 
+            // remove ImsManager reference associated with subId
+            if (VDBG) logv(mLogPrefix + "connectionUnavailable remove ImsManager " + mSubId);
+            mSubIdToImsManagerCache.remove(mSubId);
+
             connectionUnavailableInternal(reason);
         }
 
@@ -319,7 +341,7 @@
             mReason = reason;
 
             /* If having no IMS package for MMTEL,
-             * dicard the reason except REASON_NO_IMS_SERVICE_CONFIGURED. */
+             * discard the reason except REASON_NO_IMS_SERVICE_CONFIGURED. */
             if (!mHasConfig && reason != REASON_NO_IMS_SERVICE_CONFIGURED) return;
 
             onFeatureStateChange(mSubId, FEATURE_MMTEL, mState, mReason);
@@ -973,6 +995,19 @@
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_CALLBACK, cb));
     }
 
+    /**
+     * Get ImsManager reference associated with subId
+     *
+     * @param subId subscribe ID
+     * @return instance of ImsManager associated with subId, but if ImsService is not
+     * available return null
+     */
+    public ImsManager getImsManager(int subId) {
+        if (VDBG) logv("getImsManager subId = " + subId);
+
+        return mSubIdToImsManagerCache.get(subId);
+    }
+
     private void removeInactiveCallbacks(
             ArrayList<IBinder> inactiveCallbacks, String message) {
         if (inactiveCallbacks == null || inactiveCallbacks.size() == 0) return;
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index f2641a1..27e1606 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
 import android.app.Notification;
@@ -47,6 +48,7 @@
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -57,8 +59,10 @@
 import android.util.SparseArray;
 import android.widget.Toast;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.TelephonyCapabilities;
 import com.android.internal.telephony.util.NotificationChannelController;
 import com.android.phone.settings.VoicemailSettingsActivity;
@@ -163,7 +167,8 @@
      * Private constructor (this is a singleton).
      * @see #init(PhoneGlobals)
      */
-    private NotificationMgr(PhoneGlobals app) {
+    @VisibleForTesting
+    /* package */ NotificationMgr(PhoneGlobals app) {
         mApp = app;
         mContext = app;
         mStatusBarManager =
@@ -895,15 +900,22 @@
         Log.i(LOG_TAG, msg);
     }
 
-    /**
-     * In case network selection notification shows up repeatedly under
-     * unstable network condition. The logic is to check whether or not
-     * the service state keeps in no service condition for at least
-     * {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS}.
-     * And checking {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIMES} times.
-     * To avoid the notification showing up for the momentary state.
-     */
     private void shouldShowNotification(int serviceState, int subId) {
+        // "Network selection unavailable" notification should only show when network selection is
+        // visible to the end user. Some CC items e.g. KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL
+        // can be overridden to hide the network selection to the end user. In this case, the
+        // notification is not shown to avoid confusion to the end user.
+        if (!shouldDisplayNetworkSelectOptions(subId)) {
+            logi("Carrier configs refuse to show network selection not available notification");
+            return;
+        }
+
+        // In case network selection notification shows up repeatedly under
+        // unstable network condition. The logic is to check whether or not
+        // the service state keeps in no service condition for at least
+        // {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS}.
+        // And checking {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIMES} times.
+        // To avoid the notification showing up for the momentary state.
         if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
             if (mPreviousServiceState.get(subId, STATE_UNKNOWN_SERVICE)
                     != ServiceState.STATE_OUT_OF_SERVICE) {
@@ -930,6 +942,113 @@
         }
     }
 
+    // TODO(b/243010310): merge methods below with Settings#MobileNetworkUtils and optimize them.
+    // The methods below are copied from com.android.settings.network.telephony.MobileNetworkUtils
+    // to make sure the network selection unavailable notification should not show when Network
+    // Selection menu is not present in Settings app.
+    private boolean shouldDisplayNetworkSelectOptions(int subId) {
+        final TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(subId);
+        final CarrierConfigManager carrierConfigManager = mContext.getSystemService(
+                CarrierConfigManager.class);
+        final PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
+
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                || carrierConfig == null
+                || !carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL)
+                || carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
+                || (carrierConfig.getBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL)
+                && !telephonyManager.isManualNetworkSelectionAllowed())) {
+            return false;
+        }
+
+        if (isWorldMode(carrierConfig)) {
+            final int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
+                    (int) telephonyManager.getAllowedNetworkTypesForReason(
+                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
+            if (networkMode == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO) {
+                return false;
+            }
+            if (shouldSpeciallyUpdateGsmCdma(telephonyManager, carrierConfig)) {
+                return false;
+            }
+            if (networkMode == RILConstants.NETWORK_MODE_LTE_GSM_WCDMA) {
+                return true;
+            }
+        }
+
+        return isGsmBasicOptions(telephonyManager, carrierConfig);
+    }
+
+    private static boolean isWorldMode(@NonNull PersistableBundle carrierConfig) {
+        return carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL);
+    }
+
+    private static boolean shouldSpeciallyUpdateGsmCdma(@NonNull TelephonyManager telephonyManager,
+            @NonNull PersistableBundle carrierConfig) {
+        if (!isWorldMode(carrierConfig)) {
+            return false;
+        }
+
+        final int networkMode = RadioAccessFamily.getNetworkTypeFromRaf(
+                (int) telephonyManager.getAllowedNetworkTypesForReason(
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
+        if (networkMode == RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM
+                || networkMode == RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA
+                || networkMode == RILConstants.NETWORK_MODE_LTE_TDSCDMA
+                || networkMode == RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA
+                || networkMode
+                == RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+                || networkMode == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) {
+            if (!isTdscdmaSupported(telephonyManager, carrierConfig)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean isTdscdmaSupported(@NonNull TelephonyManager telephonyManager,
+            @NonNull PersistableBundle carrierConfig) {
+        if (carrierConfig.getBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL)) {
+            return true;
+        }
+        final String[] numericArray = carrierConfig.getStringArray(
+                CarrierConfigManager.KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY);
+        if (numericArray == null) {
+            return false;
+        }
+        final ServiceState serviceState = telephonyManager.getServiceState();
+        final String operatorNumeric =
+                (serviceState != null) ? serviceState.getOperatorNumeric() : null;
+        if (operatorNumeric == null) {
+            return false;
+        }
+        for (String numeric : numericArray) {
+            if (operatorNumeric.equals(numeric)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isGsmBasicOptions(@NonNull TelephonyManager telephonyManager,
+            @NonNull PersistableBundle carrierConfig) {
+        if (!carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
+                && carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
+            return true;
+        }
+
+        if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
+            return true;
+        }
+
+        return false;
+    }
+    // END of TODO:(b/243010310): merge methods above with Settings#MobileNetworkUtils and optimize.
+
     private void startPendingNetworkSelectionNotification(int subId) {
         if (!mHandler.hasMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId)) {
             if (DBG) {
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index abbd816..f6ec75d 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -49,6 +49,7 @@
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyLocalConnection;
 import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
 import android.util.LocalLog;
 import android.util.Log;
 import android.widget.Toast;
@@ -67,6 +68,8 @@
 import com.android.internal.telephony.TelephonyComponentFactory;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.data.DataEvaluation.DataDisallowedReason;
+import com.android.internal.telephony.dataconnection.DataConnectionReasons;
+import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
 import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
@@ -888,13 +891,22 @@
 
         boolean dataAllowed;
         boolean notAllowedDueToRoamingOff;
-        List<DataDisallowedReason> reasons = phone.getDataNetworkController()
-                .getInternetDataDisallowedReasons();
-        dataAllowed = reasons.isEmpty();
-        notAllowedDueToRoamingOff = (reasons.size() == 1
-                && reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
-        mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
-        if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+        if (phone.isUsingNewDataStack()) {
+            List<DataDisallowedReason> reasons = phone.getDataNetworkController()
+                    .getInternetDataDisallowedReasons();
+            dataAllowed = reasons.isEmpty();
+            notAllowedDueToRoamingOff = (reasons.size() == 1
+                    && reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
+            mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+            if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+        } else {
+            DataConnectionReasons reasons = new DataConnectionReasons();
+            dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons);
+            notAllowedDueToRoamingOff = reasons.containsOnly(
+                    DataDisallowedReasonType.ROAMING_DISABLED);
+            mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+            if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+        }
 
         if (!dataAllowed && notAllowedDueToRoamingOff) {
             // No need to show it again if we never cancelled it explicitly.
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 83eafd5..058251f 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -184,6 +184,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.data.DataUtils;
+import com.android.internal.telephony.dataconnection.ApnSettingUtils;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.euicc.EuiccConnector;
 import com.android.internal.telephony.ims.ImsResolver;
@@ -2850,6 +2851,95 @@
         }
     }
 
+    /**
+     * Vote on powering off the radio for a reason. The radio will be turned on only when there is
+     * no reason to power it off. When any of the voters want to power it off, it will be turned
+     * off. In case of emergency, the radio will be turned on even if there are some reasons for
+     * powering it off, and these radio off votes will be cleared.
+     * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
+     * responsible for its vote. A powering-off vote of a reason will be maintained until it is
+     * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
+     * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
+     * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
+     * check its vote.
+     *
+     * @param subId The subscription ID.
+     * @param reason The reason for powering off radio.
+     * @return true on success and false on failure.
+     */
+    public boolean requestRadioPowerOffForReason(int subId,
+            @TelephonyManager.RadioPowerReason int reason) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final Phone phone = getPhone(subId);
+            if (phone != null) {
+                phone.setRadioPowerForReason(false, reason);
+                return true;
+            } else {
+                return false;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Remove the vote on powering off the radio for a reason, as requested by
+     * {@link requestRadioPowerOffForReason}.
+     *
+     * @param subId The subscription ID.
+     * @param reason The reason for powering off radio.
+     * @return true on success and false on failure.
+     */
+    public boolean clearRadioPowerOffForReason(int subId,
+            @TelephonyManager.RadioPowerReason int reason) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final Phone phone = getPhone(subId);
+            if (phone != null) {
+                phone.setRadioPowerForReason(true, reason);
+                return true;
+            } else {
+                return false;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
+     *
+     * @param subId The subscription ID.
+     * @param callingPackage The package making the call.
+     * @param callingFeatureId The feature in the package.
+     * @return List of reasons for powering off radio.
+     */
+    public List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId) {
+        enforceReadPrivilegedPermission("getRadioPowerOffReasons");
+
+        final long identity = Binder.clearCallingIdentity();
+        List result = new ArrayList();
+        try {
+            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId,
+                    callingPackage, callingFeatureId, "getRadioPowerOffReasons")) {
+                return result;
+            }
+
+            final Phone phone = getPhone(subId);
+            if (phone != null) {
+                result.addAll(phone.getRadioPowerOffReasons());
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return result;
+    }
+
     // FIXME: subId version needed
     @Override
     public boolean enableDataConnectivity(String callingPackage) {
@@ -2860,8 +2950,13 @@
             int subId = mSubscriptionController.getDefaultDataSubId();
             final Phone phone = getPhone(subId);
             if (phone != null) {
-                phone.getDataSettingsManager().setDataEnabled(
-                        TelephonyManager.DATA_ENABLED_REASON_USER, true, callingPackage);
+                if (phone.isUsingNewDataStack()) {
+                    phone.getDataSettingsManager().setDataEnabled(
+                            TelephonyManager.DATA_ENABLED_REASON_USER, true, callingPackage);
+                } else {
+                    phone.getDataEnabledSettings().setDataEnabled(
+                            TelephonyManager.DATA_ENABLED_REASON_USER, true);
+                }
                 return true;
             } else {
                 return false;
@@ -2881,8 +2976,13 @@
             int subId = mSubscriptionController.getDefaultDataSubId();
             final Phone phone = getPhone(subId);
             if (phone != null) {
-                phone.getDataSettingsManager().setDataEnabled(
-                        TelephonyManager.DATA_ENABLED_REASON_USER, false, callingPackage);
+                if (phone.isUsingNewDataStack()) {
+                    phone.getDataSettingsManager().setDataEnabled(
+                            TelephonyManager.DATA_ENABLED_REASON_USER, false, callingPackage);
+                } else {
+                    phone.getDataEnabledSettings().setDataEnabled(
+                            TelephonyManager.DATA_ENABLED_REASON_USER, false);
+                }
                 return true;
             } else {
                 return false;
@@ -2998,7 +3098,10 @@
         try {
             final Phone phone = getPhone(subId);
             if (phone != null) {
-                return phone.getDataNetworkController().getInternetDataNetworkState();
+                if (phone.isUsingNewDataStack()) {
+                    return phone.getDataNetworkController().getInternetDataNetworkState();
+                }
+                return PhoneConstantConversions.convertDataState(phone.getDataConnectionState());
             } else {
                 return PhoneConstantConversions.convertDataState(
                         PhoneConstants.DataState.DISCONNECTED);
@@ -3264,13 +3367,18 @@
     }
 
     @Override
-    public void setCellInfoListRate(int rateInMillis) {
+    public void setCellInfoListRate(int rateInMillis, int subId) {
         enforceModifyPermission();
         WorkSource workSource = getWorkSource(Binder.getCallingUid());
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
+            Phone phone = getPhone(subId);
+            if (phone == null) {
+                getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
+            } else {
+                phone.setCellInfoListRate(rateInMillis, workSource);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4032,7 +4140,18 @@
         try {
             int slotId = getSlotIndexOrException(subId);
             verifyImsMmTelConfiguredOrThrow(slotId);
-            ImsManager.getInstance(mApp, slotId).addRegistrationCallbackForSubscription(c, subId);
+
+            ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+            if (controller != null) {
+                ImsManager imsManager = controller.getImsManager(subId);
+                if (imsManager != null) {
+                    imsManager.addRegistrationCallbackForSubscription(c, subId);
+                } else {
+                    throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+                }
+            } else {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+            }
         } catch (ImsException e) {
             throw new ServiceSpecificException(e.getCode());
         } finally {
@@ -4053,14 +4172,20 @@
             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
         }
         final long token = Binder.clearCallingIdentity();
+
         try {
-            ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
-                    .removeRegistrationCallbackForSubscription(c, subId);
-        } catch (ImsException e) {
-            Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
-                    + "is inactive, ignoring unregister.");
-            // If the subscription is no longer active, just return, since the callback
-            // will already have been removed internally.
+            ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+            if (controller != null) {
+                ImsManager imsManager = controller.getImsManager(subId);
+                if (imsManager != null) {
+                    imsManager.removeRegistrationCallbackForSubscription(c, subId);
+                } else {
+                    Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
+                            + "is inactive, ignoring unregister.");
+                    // If the ImsManager is not valid, just return, since the callback
+                    // will already have been removed internally.
+                }
+            }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -6571,10 +6696,10 @@
             try {
                 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
                         functionName);
-            } catch (Exception e) {
+            } catch (SecurityException e) {
                 mApp.enforceCallingOrSelfPermission(permission.ACCESS_NETWORK_STATE, functionName);
             }
-        } catch (Exception e) {
+        } catch (SecurityException e) {
             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                     mApp, subId, functionName);
 
@@ -6613,17 +6738,17 @@
                 mApp.enforceCallingOrSelfPermission(
                         android.Manifest.permission.ACCESS_NETWORK_STATE,
                         functionName);
-            } catch (Exception e) {
+            } catch (SecurityException e) {
                 try {
                     mApp.enforceCallingOrSelfPermission(
                             android.Manifest.permission.READ_PHONE_STATE,
                             functionName);
-                } catch (Exception e2) {
+                } catch (SecurityException e2) {
                     mApp.enforceCallingOrSelfPermission(
                             permission.READ_BASIC_PHONE_STATE, functionName);
                 }
             }
-        } catch (Exception e) {
+        } catch (SecurityException e) {
             enforceReadPrivilegedPermission(functionName);
         }
 
@@ -6633,7 +6758,11 @@
             Phone phone = PhoneFactory.getPhone(phoneId);
             if (phone != null) {
                 boolean retVal;
-                retVal = phone.getDataSettingsManager().isDataEnabled();
+                if (phone.isUsingNewDataStack()) {
+                    retVal = phone.getDataSettingsManager().isDataEnabled();
+                } else {
+                    retVal = phone.getDataEnabledSettings().isDataEnabled();
+                }
                 if (DBG) log("isDataEnabled: " + retVal + ", subId=" + subId);
                 return retVal;
             } else {
@@ -6660,15 +6789,15 @@
                 mApp.enforceCallingOrSelfPermission(
                         android.Manifest.permission.ACCESS_NETWORK_STATE,
                         functionName);
-            } catch (Exception e) {
+            } catch (SecurityException e) {
                 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
                         functionName);
             }
-        } catch (Exception e) {
+        } catch (SecurityException e) {
             try {
                 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
                         functionName);
-            } catch (Exception e2) {
+            } catch (SecurityException e2) {
                 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                         mApp, subId, functionName);
             }
@@ -6685,7 +6814,15 @@
             Phone phone = PhoneFactory.getPhone(phoneId);
             if (phone != null) {
                 boolean retVal;
-                retVal = phone.getDataSettingsManager().isDataEnabledForReason(reason);
+                if (phone.isUsingNewDataStack()) {
+                    retVal = phone.getDataSettingsManager().isDataEnabledForReason(reason);
+                } else {
+                    if (reason == TelephonyManager.DATA_ENABLED_REASON_USER) {
+                        retVal = phone.isUserDataEnabled();
+                    } else {
+                        retVal = phone.getDataEnabledSettings().isDataEnabledForReason(reason);
+                    }
+                }
                 if (DBG) log("isDataEnabledForReason: retVal=" + retVal);
                 return retVal;
             } else {
@@ -8068,8 +8205,7 @@
             }
             String vvmPackage = componentName.getPackageName();
             if (!callingPackage.equals(vvmPackage)) {
-                throw new SecurityException("Caller not current active visual voicemail package["
-                        + vvmPackage + "]");
+                throw new SecurityException("Caller not current active visual voicemail package");
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -8424,8 +8560,12 @@
                 if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
                     phone.carrierActionSetMeteredApnsEnabled(enabled);
                 } else {
-                    phone.getDataSettingsManager().setDataEnabled(
-                            reason, enabled, callingPackage);
+                    if (phone.isUsingNewDataStack()) {
+                        phone.getDataSettingsManager().setDataEnabled(
+                                reason, enabled, callingPackage);
+                    } else {
+                        phone.getDataEnabledSettings().setDataEnabled(reason, enabled);
+                    }
                 }
             }
         } finally {
@@ -8636,11 +8776,11 @@
                 mApp.enforceCallingOrSelfPermission(
                         android.Manifest.permission.ACCESS_NETWORK_STATE,
                         functionName);
-            } catch (Exception e) {
+            } catch (SecurityException e) {
                 mApp.enforceCallingOrSelfPermission(
                         permission.READ_BASIC_PHONE_STATE, functionName);
             }
-        } catch (Exception e) {
+        } catch (SecurityException e) {
             TelephonyPermissions.enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
                     mApp, subId, functionName);
         }
@@ -9202,9 +9342,11 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             for (Phone phone: PhoneFactory.getPhones()) {
+                //Note: we ignore passed in param exactMatch. We can remove it once
+                // TelephonyManager#isPotentialEmergencyNumber is removed completely
                 if (phone.getEmergencyNumberTracker() != null
                         && phone.getEmergencyNumberTracker()
-                                .isEmergencyNumber(number, exactMatch)) {
+                                .isEmergencyNumber(number)) {
                     return true;
                 }
             }
@@ -9635,10 +9777,15 @@
 
             boolean isMetered;
             boolean isDataEnabled;
-            isMetered = phone.getDataNetworkController().getDataConfigManager()
-                    .isMeteredCapability(DataUtils.apnTypeToNetworkCapability(apnType),
-                            phone.getServiceState().getDataRoaming());
-            isDataEnabled = phone.getDataSettingsManager().isDataEnabled(apnType);
+            if (phone.isUsingNewDataStack()) {
+                isMetered = phone.getDataNetworkController().getDataConfigManager()
+                        .isMeteredCapability(DataUtils.apnTypeToNetworkCapability(apnType),
+                                phone.getServiceState().getDataRoaming());
+                isDataEnabled = phone.getDataSettingsManager().isDataEnabled(apnType);
+            } else {
+                isMetered = ApnSettingUtils.isMeteredApnType(apnType, phone);
+                isDataEnabled = phone.getDataEnabledSettings().isDataEnabled(apnType);
+            }
             return !isMetered || isDataEnabled;
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -9654,9 +9801,13 @@
         try {
             Phone phone = getPhone(subId);
             if (phone == null) return true; // By default return true.
-            return phone.getDataNetworkController().getDataConfigManager().isMeteredCapability(
-                    DataUtils.apnTypeToNetworkCapability(apnType),
-                    phone.getServiceState().getDataRoaming());
+            if (phone.isUsingNewDataStack()) {
+                return phone.getDataNetworkController().getDataConfigManager().isMeteredCapability(
+                        DataUtils.apnTypeToNetworkCapability(apnType),
+                        phone.getServiceState().getDataRoaming());
+            }
+
+            return ApnSettingUtils.isMeteredApnType(apnType, phone);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -9788,9 +9939,17 @@
 
             switch (policy) {
                 case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
-                    return phone.getDataSettingsManager().isDataAllowedInVoiceCall();
+                    if (phone.isUsingNewDataStack()) {
+                        return phone.getDataSettingsManager().isDataAllowedInVoiceCall();
+                    } else {
+                        return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
+                    }
                 case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
-                    return phone.getDataSettingsManager().isMmsAlwaysAllowed();
+                    if (phone.isUsingNewDataStack()) {
+                        return phone.getDataSettingsManager().isMmsAlwaysAllowed();
+                    } else {
+                        return phone.getDataEnabledSettings().isMmsAlwaysAllowed();
+                    }
                 default:
                     throw new IllegalArgumentException(policy + " is not a valid policy");
             }
@@ -9811,10 +9970,18 @@
 
             switch (policy) {
                 case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
-                    phone.getDataSettingsManager().setAllowDataDuringVoiceCall(enabled);
+                    if (phone.isUsingNewDataStack()) {
+                        phone.getDataSettingsManager().setAllowDataDuringVoiceCall(enabled);
+                    } else {
+                        phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(enabled);
+                    }
                     break;
                 case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
-                    phone.getDataSettingsManager().setAlwaysAllowMmsData(enabled);
+                    if (phone.isUsingNewDataStack()) {
+                        phone.getDataSettingsManager().setAlwaysAllowMmsData(enabled);
+                    } else {
+                        phone.getDataEnabledSettings().setAlwaysAllowMmsData(enabled);
+                    }
                     break;
                 default:
                     throw new IllegalArgumentException(policy + " is not a valid policy");
@@ -10094,7 +10261,7 @@
         for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
             Phone phone = PhoneFactory.getPhone(i);
             if (phone != null) {
-                phone.setRadioPowerForReason(enable, Phone.RADIO_POWER_REASON_THERMAL);
+                phone.setRadioPowerForReason(enable, TelephonyManager.RADIO_POWER_REASON_THERMAL);
                 isPhoneAvailable = true;
             }
         }
@@ -11191,6 +11358,12 @@
         }
     }
 
+    @Override
+    public boolean isUsingNewDataStack() {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "isUsingNewDataStack");
+        return getDefaultPhone().isUsingNewDataStack();
+    }
+
     /**
      * Sets the modem service class Name that Telephony will bind to.
      *
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 1ed0d72..a948d08 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -828,7 +828,7 @@
 
     private void onConfigReceived(int subId, byte[] config, boolean isCompressed) {
         logv("onConfigReceived, subId:" + subId + ", config:"
-                + config + ", isCompressed:" + isCompressed);
+                + Arrays.toString(config) + ", isCompressed:" + isCompressed);
         RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
         if (info == null) {
             logd("sub[" + subId + "] has been removed");
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index d19cf67..2c13060 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -63,6 +63,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
@@ -167,10 +168,19 @@
     private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
     private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
 
+    private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
+            + "'*', '#' or '+') needs to be specified after -a in the command ";
+
+    private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
+            EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
+            EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
+
     private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
             "get-allowed-network-types-for-users";
     private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
             "set-allowed-network-types-for-users";
+    // Check if telephony new data stack is enabled.
+    private static final String GET_DATA_MODE = "get-data-mode";
     private static final String GET_IMEI = "get-imei";
     private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
     // Take advantage of existing methods that already contain permissions checks when possible.
@@ -327,6 +337,8 @@
             case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
             case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
                 return handleAllowedNetworkTypesCommand(cmd);
+            case GET_DATA_MODE:
+                return handleGetDataMode();
             case GET_IMEI:
                 return handleGetImei();
             case GET_SIM_SLOTS_MAPPING:
@@ -785,6 +797,24 @@
         return 0;
     }
 
+    private void removeEmergencyNumberTestMode(String emergencyNumber) {
+        PrintWriter errPw = getErrPrintWriter();
+        for (int routingType : ROUTING_TYPES) {
+            try {
+                mInterface.updateEmergencyNumberListTestMode(
+                        EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
+                        new EmergencyNumber(emergencyNumber, "", "",
+                                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+                                new ArrayList<String>(),
+                                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+                                routingType));
+            } catch (RemoteException ex) {
+                Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
+                errPw.println("Exception: " + ex.getMessage());
+            }
+        }
+    }
+
     private int handleEmergencyNumberTestModeCommand() {
         PrintWriter errPw = getErrPrintWriter();
         String opt = getNextOption();
@@ -792,26 +822,52 @@
             onHelpEmergencyNumber();
             return 0;
         }
-
         switch (opt) {
             case "-a": {
                 String emergencyNumberCmd = getNextArgRequired();
-                if (emergencyNumberCmd == null
-                        || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
-                    errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
-                            + " to be specified after -a in the command ");
+                if (emergencyNumberCmd == null){
+                    errPw.println(INVALID_ENTRY_ERROR);
                     return -1;
                 }
+                String[] params = emergencyNumberCmd.split(":");
+                String emergencyNumber;
+                if (params[0] == null ||
+                        !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
+                    errPw.println(INVALID_ENTRY_ERROR);
+                    return -1;
+                } else {
+                    emergencyNumber = params[0];
+                }
+                removeEmergencyNumberTestMode(emergencyNumber);
+                int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
+                if (params.length > 1) {
+                    switch (params[1].toLowerCase(Locale.ROOT)) {
+                        case "emergency":
+                            emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
+                            break;
+                        case "normal":
+                            emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
+                            break;
+                        case "unknown":
+                            break;
+                        default:
+                            errPw.println("\"" + params[1] + "\" is not a valid specification for "
+                                    + "emergency call routing. Please enter either \"normal\", "
+                                    + "\"unknown\", or \"emergency\" for call routing. "
+                                    + "(-a 1234:normal)");
+                            return -1;
+                    }
+                }
                 try {
                     mInterface.updateEmergencyNumberListTestMode(
                             EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
-                            new EmergencyNumber(emergencyNumberCmd, "", "",
+                            new EmergencyNumber(emergencyNumber, "", "",
                                     EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
                                     new ArrayList<String>(),
                                     EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
-                                    EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+                                    emergencyCallRouting));
                 } catch (RemoteException ex) {
-                    Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
+                    Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
                             + ", error " + ex.getMessage());
                     errPw.println("Exception: " + ex.getMessage());
                     return -1;
@@ -837,20 +893,7 @@
                             + " to be specified after -r in the command ");
                     return -1;
                 }
-                try {
-                    mInterface.updateEmergencyNumberListTestMode(
-                            EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
-                            new EmergencyNumber(emergencyNumberCmd, "", "",
-                                    EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
-                                    new ArrayList<String>(),
-                                    EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
-                                    EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
-                } catch (RemoteException ex) {
-                    Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
-                            + ", error " + ex.getMessage());
-                    errPw.println("Exception: " + ex.getMessage());
-                    return -1;
-                }
+                removeEmergencyNumberTestMode(emergencyNumberCmd);
                 break;
             }
             case "-p": {
@@ -2909,6 +2952,24 @@
         }
     }
 
+    private int handleGetDataMode() {
+        if (!checkShellUid()) {
+            return -1;
+        }
+
+        boolean newDataStackEnabled = false;
+        try {
+            newDataStackEnabled = mInterface.isUsingNewDataStack();
+        } catch (RemoteException e) {
+            getOutPrintWriter().println("Something went wrong. " + e);
+            return -1;
+        }
+
+        getOutPrintWriter().println("Telephony is running with the "
+                + (newDataStackEnabled ? "new" : "old") + " data stack.");
+        return 0;
+    }
+
     private int handleRadioSetModemServiceCommand() {
         PrintWriter errPw = getErrPrintWriter();
         String serviceName = null;
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index d4367ca..288d543 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -410,7 +410,7 @@
     private void updatePhoneIndex(int phoneIndex, int subId) {
         // unregister listeners on the old subId
         unregisterPhoneStateListener();
-        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
 
         // update the subId
         mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
@@ -675,7 +675,8 @@
         //set selection after registering listener to force update
         mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
         // Request cell information update from RIL.
-        mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex]);
+        mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex],
+                mPhone.getSubId());
 
         //set selection before registering to prevent update
         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
@@ -720,7 +721,7 @@
         log("onPause: unregister phone & data intents");
 
         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
-        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+        mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
 
     }
@@ -1880,7 +1881,7 @@
 
         public void onItemSelected(AdapterView parent, View v, int pos, long id) {
             mCellInfoRefreshRateIndex = pos;
-            mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos]);
+            mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos], mPhone.getSubId());
             updateAllCellInfo();
         }
 
diff --git a/src/com/android/phone/settings/VoicemailProviderSettings.java b/src/com/android/phone/settings/VoicemailProviderSettings.java
index fc2e7f8..10f0ddb 100644
--- a/src/com/android/phone/settings/VoicemailProviderSettings.java
+++ b/src/com/android/phone/settings/VoicemailProviderSettings.java
@@ -21,6 +21,8 @@
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CommandsInterface;
 
+import java.util.Arrays;
+
 /**
  * Settings for a voicemail provider, including any conditional forwarding information.
  */
@@ -88,7 +90,7 @@
     @Override
     public String toString() {
         return mVoicemailNumber + ((mForwardingSettings == null) ? ""
-                : ", " + mForwardingSettings.toString());
+                : ", " + Arrays.toString(mForwardingSettings));
     }
 
     public String getVoicemailNumber() {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index f1c0383..e369d37 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1144,6 +1144,11 @@
                             "Invalid phone type",
                             phone.getPhoneId()));
         }
+        if (!Objects.equals(request.getAccountHandle(), accountHandle)) {
+            Log.i(this, "onCreateOutgoingConnection, update phoneAccountHandle, accountHandle = "
+                    + accountHandle);
+            connection.setPhoneAccountHandle(accountHandle);
+        }
         connection.setAddress(handle, PhoneConstants.PRESENTATION_ALLOWED);
         connection.setTelephonyConnectionInitializing();
         connection.setTelephonyVideoState(request.getVideoState());
@@ -2105,7 +2110,7 @@
         for (Phone phone : mPhoneFactoryProxy.getPhones()) {
             if (phone.getEmergencyNumberTracker() != null) {
                 if (phone.getEmergencyNumberTracker().isEmergencyNumber(
-                        emergencyNumberAddress, true)) {
+                        emergencyNumberAddress)) {
                     if (isAvailableForEmergencyCalls(phone)) {
                         // a)
                         if (phone.getPhoneId() == defaultVoicePhoneId) {
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index 2094e20..db83cca 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -63,6 +63,7 @@
 import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
 import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
 import android.telephony.ims.stub.ImsConfigImplBase;
@@ -159,6 +160,9 @@
     @Mock
     IFeatureProvisioningCallback mIFeatureProvisioningCallback1;
 
+    @Captor
+    ArgumentCaptor<IImsConfigCallback> mIImsConfigCallback;
+
     @Mock
     IBinder mIbinder0;
     @Mock
@@ -347,6 +351,8 @@
         mSubChangedListener.onSubscriptionsChanged();
         processAllMessages();
 
+        verify(mImsConfig, times(1)).addConfigCallback((IImsConfigCallback) any());
+
         int[] keys = {
                 ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE,
                 ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS,
@@ -390,6 +396,8 @@
         mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
         processAllMessages();
 
+        verify(mImsConfig, times(1)).addConfigCallback((IImsConfigCallback) any());
+
         // verify # of read data times from storage : # of Rcs storage length
         verify(mImsProvisioningLoader, times(1))
                 .getProvisioningStatus(eq(mSubId0), eq(FEATURE_RCS), anyInt(), anyInt());
@@ -1736,6 +1744,110 @@
         verifyNoMoreInteractions(mImsProvisioningLoader);
     }
 
+    @Test
+    @SmallTest
+    public void changedProvisioningValue_withMmTel() throws Exception {
+        createImsProvisioningController();
+
+        // provisioning required capability
+        // voice, all tech
+        // video, all tech
+        setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+                RADIO_TECHS);
+        setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+                RADIO_TECHS);
+
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId0, mIFeatureProvisioningCallback0);
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+
+        mMmTelConnectorListener0.getValue().connectionReady(mImsManager, mSubId0);
+
+        // clear interactions
+        clearInvocations(mIFeatureProvisioningCallback0);
+        clearInvocations(mImsConfig);
+        clearInvocations(mImsProvisioningLoader);
+
+        // MmTel valid
+        int[] keys = {
+                ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS,
+                ProvisioningManager.KEY_VT_PROVISIONING_STATUS,
+                ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE
+        };
+        int[] capas = {
+                MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+                MmTelCapabilities.CAPABILITY_TYPE_VOICE
+        };
+        int[] techs = {
+                ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+        };
+
+        for (int index = 0; index < keys.length; index++) {
+            mIImsConfigCallback.getValue().onIntConfigChanged(keys[index],
+                    PROVISIONING_VALUE_DISABLED);
+            processAllMessages();
+
+            // verify # of read data times from storage : # of MmTel storage length
+            verify(mImsProvisioningLoader, times(1))
+                    .setProvisioningStatus(eq(mSubId0), eq(FEATURE_MMTEL), eq(capas[index]),
+                            eq(techs[index]), eq(false));
+
+            verify(mIFeatureProvisioningCallback0, times(1))
+                    .onFeatureProvisioningChanged(eq(capas[index]), eq(techs[index]), eq(false));
+        }
+
+        verifyNoMoreInteractions(mImsProvisioningLoader);
+        verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+        verifyNoMoreInteractions(mImsConfig);
+    }
+
+    @Test
+    @SmallTest
+    public void changedProvisioningValue_withRcs() throws Exception {
+        createImsProvisioningController();
+
+        // provisioning required capability : PRESENCE, tech : all
+        setCarrierConfig(mSubId0,
+                CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId0, mIFeatureProvisioningCallback0);
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+
+        mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
+
+        // clear interactions
+        clearInvocations(mIFeatureProvisioningCallback0);
+        clearInvocations(mImsConfig);
+        clearInvocations(mImsProvisioningLoader);
+
+        mIImsConfigCallback.getValue().onIntConfigChanged(KEY_EAB_PROVISIONING_STATUS,
+                PROVISIONING_VALUE_DISABLED);
+        processAllMessages();
+
+        // verify # of read data times from storage : # of MmTel storage length
+        verify(mImsProvisioningLoader, times(RADIO_TECHS.length))
+                .setProvisioningStatus(eq(mSubId0), eq(FEATURE_RCS),
+                        eq(CAPABILITY_TYPE_PRESENCE_UCE), anyInt(), eq(false));
+
+        verify(mIFeatureProvisioningCallback0, times(RADIO_TECHS.length))
+                .onRcsFeatureProvisioningChanged(eq(CAPABILITY_TYPE_PRESENCE_UCE), anyInt(),
+                        eq(false));
+
+        verifyNoMoreInteractions(mImsProvisioningLoader);
+        verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+        verifyNoMoreInteractions(mImsConfig);
+    }
+
     private void createImsProvisioningController() throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -1755,6 +1867,9 @@
                 .create(any(), eq(1), mRcsConnectorListener1.capture(), any(), any()))
                 .thenReturn(mRcsFeatureConnector1);
 
+        doNothing().when(mImsConfig).addConfigCallback(mIImsConfigCallback.capture());
+        doNothing().when(mImsConfig).removeConfigCallback(any());
+
         when(mImsConfig.getConfigInt(anyInt()))
                 .thenAnswer(invocation -> {
                     int i = (Integer) (invocation.getArguments()[0]);
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index cb4321c..60374bc 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -28,6 +28,8 @@
 import static com.android.ims.FeatureConnector.UNAVAILABLE_REASON_NOT_READY;
 
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.Matchers.any;
@@ -874,6 +876,36 @@
         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
     }
 
+    @Test
+    @SmallTest
+    public void testImsManagerInstance() throws Exception {
+        createController(1);
+
+        // MmTelConnection not ready
+        // check ImsManager instance
+        ImsManager imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+        assertNull(imsManager);
+
+        // MmTelConnection ready
+        mMmTelConnectorListenerSlot0.getValue()
+                .connectionReady(mMmTelFeatureManager, SLOT_0_SUB_ID);
+        processAllMessages();
+
+        // check ImsManager instance
+        imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+        assertNotNull(imsManager);
+
+        // MmTelConnection unavailable
+        mMmTelConnectorListenerSlot0.getValue()
+                .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
+        processAllMessages();
+
+        // MmTelConnection unavailable
+        // check ImsManager instance
+        imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+        assertNull(imsManager);
+    }
+
     private void createController(int slotCount) throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();
diff --git a/tests/src/com/android/phone/NotificationMgrTest.java b/tests/src/com/android/phone/NotificationMgrTest.java
new file mode 100644
index 0000000..a6ee276
--- /dev/null
+++ b/tests/src/com/android/phone/NotificationMgrTest.java
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2022 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.phone;
+
+import static android.telephony.RadioAccessFamily.RAF_1xRTT;
+import static android.telephony.RadioAccessFamily.RAF_EDGE;
+import static android.telephony.RadioAccessFamily.RAF_EHRPD;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_0;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_A;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_B;
+import static android.telephony.RadioAccessFamily.RAF_GPRS;
+import static android.telephony.RadioAccessFamily.RAF_GSM;
+import static android.telephony.RadioAccessFamily.RAF_HSDPA;
+import static android.telephony.RadioAccessFamily.RAF_HSPA;
+import static android.telephony.RadioAccessFamily.RAF_HSPAP;
+import static android.telephony.RadioAccessFamily.RAF_HSUPA;
+import static android.telephony.RadioAccessFamily.RAF_IS95A;
+import static android.telephony.RadioAccessFamily.RAF_IS95B;
+import static android.telephony.RadioAccessFamily.RAF_LTE;
+import static android.telephony.RadioAccessFamily.RAF_LTE_CA;
+import static android.telephony.RadioAccessFamily.RAF_TD_SCDMA;
+import static android.telephony.RadioAccessFamily.RAF_UMTS;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static com.android.phone.NotificationMgr.DATA_ROAMING_NOTIFICATION;
+import static com.android.phone.NotificationMgr.LIMITED_SIM_FUNCTION_NOTIFICATION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.util.NotificationChannelController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.Field;
+
+/**
+ * Unit Test for NotificationMgr
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationMgrTest {
+
+    private static final int TEST_SUB_ID = 1;
+    private static final long SERIAL_NUMBER_OF_USER = 1234567L;
+    private static final String TEST_LABEL_CF = "test_call_forwarding";
+    private static final String TEST_SUB_INFO_DISPLAY_NAME = "display_name";
+    private static final String TEST_PACKAGE_NAME = "com.android.phone";
+    private static final String TEST_SELECTED_NETWORK_OPERATOR_NAME = "TheOperator";
+    private static final String MOBILE_NETWORK_SELECTION_PACKAGE = "com.android.phone";
+    private static final String MOBILE_NETWORK_SELECTION_CLASS = ".testClass";
+    private static final String CARRIER_NAME = "CoolCarrier";
+
+    @Mock PhoneGlobals mApp;
+    @Mock StatusBarManager mStatusBarManager;
+    @Mock UserManager mUserManager;
+    @Mock SubscriptionManager mSubscriptionManager;
+    @Mock TelecomManager mTelecomManager;
+    @Mock TelephonyManager mTelephonyManager;
+    @Mock Phone mPhone;
+    @Mock SharedPreferences mSharedPreferences;
+    @Mock NotificationManager mNotificationManager;
+    @Mock SubscriptionInfo mSubscriptionInfo;
+    @Mock Resources mResources;
+    @Mock ServiceState mServiceState;
+    @Mock CarrierConfigManager mCarrierConfigManager;
+
+    private Phone[] mPhones;
+    private NotificationMgr mNotificationMgr;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mPhones = new Phone[]{mPhone};
+        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+        when(mApp.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences);
+
+        when(mApp.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(mApp.getSystemService(Context.STATUS_BAR_SERVICE)).thenReturn(mStatusBarManager);
+        when(mApp.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mApp.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(
+                mSubscriptionManager);
+        when(mApp.getSystemServiceName(TelecomManager.class)).thenReturn(Context.TELECOM_SERVICE);
+        when(mApp.getSystemService(TelecomManager.class)).thenReturn(mTelecomManager);
+        when(mApp.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        when(mApp.getSystemServiceName(CarrierConfigManager.class)).thenReturn(
+                Context.CARRIER_CONFIG_SERVICE);
+        when(mApp.getSystemService(CarrierConfigManager.class)).thenReturn(mCarrierConfigManager);
+        when(mApp.getSystemServiceName(CarrierConfigManager.class)).thenReturn(
+                Context.CARRIER_CONFIG_SERVICE);
+        when(mApp.getSystemService(CarrierConfigManager.class)).thenReturn(mCarrierConfigManager);
+
+        when(mApp.createPackageContextAsUser(any(), eq(0), any())).thenReturn(mApp);
+        when(mApp.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(mNotificationManager);
+        when(mUserManager.getSerialNumbersOfUsers(true)).thenReturn(
+                new long[]{SERIAL_NUMBER_OF_USER});
+        when(mUserManager.getUserForSerialNumber(eq(SERIAL_NUMBER_OF_USER))).thenReturn(
+                UserHandle.SYSTEM);
+        when(mApp.getResources()).thenReturn(mResources);
+        when(mResources.getString(R.string.labelCF)).thenReturn(TEST_LABEL_CF);
+        ApplicationInfo appWithSdkS = buildApplicationInfo(Build.VERSION_CODES.S);
+        when(mApp.getApplicationInfo()).thenReturn(appWithSdkS);
+        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+        when(mTelephonyManager.getServiceState()).thenReturn(mServiceState);
+
+        mNotificationMgr = new NotificationMgr(mApp);
+    }
+
+    @Test
+    public void testUpdateCfi_visible_noActiveSubscription_notificationNeverSent()
+            throws Exception {
+        // Given no active subscription available
+        when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(null);
+
+        // When updateCfi method is called
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+        // Then the notification should never be sent
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateCfi_visible_hasActiveSub_singleSIM_notificationSent() throws Exception {
+        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
+        when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+                mSubscriptionInfo);
+
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+    }
+
+    @Test
+    public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithoutDisplayName()
+            throws Exception {
+        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+        when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+                mSubscriptionInfo);
+        when(mSubscriptionInfo.getDisplayName()).thenReturn(null);
+
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+    }
+
+    @Test
+    public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithDisplayName()
+            throws Exception {
+        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+        when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+                mSubscriptionInfo);
+        when(mSubscriptionInfo.getDisplayName()).thenReturn(TEST_SUB_INFO_DISPLAY_NAME);
+
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+    }
+
+    @Test
+    public void testUpdateCfi_invisible_hasUnmanagedProfile_notificationCanceled()
+            throws Exception {
+        when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
+
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
+
+        verify(mNotificationManager).cancel(any(), anyInt());
+    }
+
+    @Test
+    public void testUpdateCfi_invisible_allProfilesAreManaged_notificationNeverCanceled()
+            throws Exception {
+        when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
+
+        mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
+
+        verify(mNotificationManager, never()).cancel(any(), anyInt());
+    }
+
+    @Test
+    public void testShowDataRoamingNotification_roamingOn() throws Exception {
+        mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/true);
+
+        verifyNotificationSentWithChannelId(
+                NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS);
+    }
+
+    @Test
+    public void testShowDataRoamingNotification_roamingOff() throws Exception {
+        mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/false);
+
+        verifyNotificationSentWithChannelId(
+                NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS);
+    }
+
+    @Test
+    public void testHideDataRoamingNotification() {
+        mNotificationMgr.hideDataRoamingNotification();
+
+        verify(mNotificationManager).cancel(any(), eq(DATA_ROAMING_NOTIFICATION));
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_justOutOfService_notificationNeverSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(2000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_oosEnoughTime_selectionVisibleToUser_notificationSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+        when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        // TODO: use effective TestLooper time eclipse instead of sleeping
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_invalidSubscription_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+        when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE,
+                INVALID_SUBSCRIPTION_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE,
+                INVALID_SUBSCRIPTION_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_nullCarrierConfig_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(null);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_userNotAllowedToChooseOperator_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        // User is NOT allowed to choose operator
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_OverrideHideCarrierNetworkSelection_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        // Hide network selection menu
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_simPreventManualSelection_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        // SIM card can prevent manual network selection which is forbidden
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, true);
+        when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_worldMode_userSetLTE_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+        // World mode is on
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+        // User set Network mode as LTE
+        when(mTelephonyManager.getAllowedNetworkTypesForReason(
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+                (long) (RAF_LTE | RAF_LTE_CA | RAF_IS95A | RAF_IS95B | RAF_1xRTT | RAF_EVDO_0
+                        | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD));
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_worldMode_userSetTDSCDMA_notSupported_notifNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+        // World mode is on
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+        // User set Network mode as NETWORK_MODE_LTE_TDSCDMA_GSM
+        when(mTelephonyManager.getAllowedNetworkTypesForReason(
+                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+                (long) (RAF_LTE | RAF_LTE_CA | RAF_TD_SCDMA | RAF_GSM | RAF_GPRS | RAF_EDGE));
+        // But TDSCDMA is NOT supported
+        config.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_worldMode_userSetWCDMA_notificationSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+        // World mode is on
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+        // User set Network mode as NETWORK_MODE_LTE_TDSCDMA_GSM
+        when(mTelephonyManager.getAllowedNetworkTypesForReason(
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+                (long) (RAF_LTE | RAF_LTE_CA | RAF_GSM | RAF_GPRS | RAF_EDGE | RAF_HSUPA | RAF_HSDPA
+                        | RAF_HSPA | RAF_HSPAP | RAF_UMTS));
+        // But TDSCDMA is NOT supported
+        config.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_worldPhone_networkSelectionNotHide_notificationSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        // World mode is off
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+        // World phone is on
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_gsmBasicOptionOn_notificationSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        // World phone is on
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+        // World mode is off
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+        when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+    }
+
+    @Test
+    public void testUpdateNetworkSelection_gsmBasicOptionOff_notificationNotSent()
+            throws Exception {
+        prepareResourcesForNetworkSelection();
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+        config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+        // World mode is off
+        config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+        when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+        when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
+
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException ignored) {
+        }
+        mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+    }
+
+    @Test
+    public void testShowLimitedSimFunctionWarningNotification_forTheFirstTime_notificationSent()
+            throws Exception {
+        when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+                CARRIER_NAME);
+        when(mResources.getText(
+                R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+                "123");
+
+        mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+        verifyNotificationSentWithChannelId(
+                NotificationChannelController.CHANNEL_ID_SIM_HIGH_PRIORITY);
+    }
+
+    @Test
+    public void testShowLimitedSimFunctionWarningNotification_consecutiveCall_notificationSentOnce()
+            throws Exception {
+        when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+                CARRIER_NAME);
+        when(mResources.getText(
+                R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+                "123");
+
+        // Call the method TWICE with the same subscription
+        mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+        mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+        // Verify the notification is only sent ONCE
+        verifyNotificationSentWithChannelId(
+                NotificationChannelController.CHANNEL_ID_SIM_HIGH_PRIORITY);
+    }
+
+    @Test
+    public void testDismissLimitedSimFunctionWarningNotification_noShowCalledBefore_noCancelSent()
+            throws Exception {
+        // showLimitedSimFunctionWarningNotification was never called before
+
+        mNotificationMgr.dismissLimitedSimFunctionWarningNotification(TEST_SUB_ID);
+
+        verify(mNotificationManager, never()).cancel(any(), anyInt());
+    }
+
+    @Test
+    public void testDismissLimitedSimFunctionWarningNotification_showCalledBefore_cancelSent()
+            throws Exception {
+        when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+                CARRIER_NAME);
+        when(mResources.getText(
+                R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+                "123");
+        mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+        mNotificationMgr.dismissLimitedSimFunctionWarningNotification(TEST_SUB_ID);
+
+        verify(mNotificationManager).cancel(any(), eq(LIMITED_SIM_FUNCTION_NOTIFICATION));
+    }
+
+    private ApplicationInfo buildApplicationInfo(int targetSdkVersion) {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.targetSdkVersion = targetSdkVersion;
+        return applicationInfo;
+    }
+
+    private void verifyNotificationSentWithChannelId(String expectedNotificationChannelId) {
+        ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(
+                Notification.class);
+        verify(mNotificationManager).notify(any(), anyInt(), notificationArgumentCaptor.capture());
+        Notification capturedNotification = notificationArgumentCaptor.getAllValues().get(0);
+        assertThat(capturedNotification.getChannelId()).isEqualTo(expectedNotificationChannelId);
+    }
+
+    private void prepareResourcesForNetworkSelection() {
+        when(mSharedPreferences.getString(Phone.NETWORK_SELECTION_NAME_KEY + TEST_SUB_ID,
+                "")).thenReturn(TEST_SELECTED_NETWORK_OPERATOR_NAME);
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.skip_restoring_network_selection)).thenReturn(false);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mApp.getString(R.string.mobile_network_settings_package)).thenReturn(
+                MOBILE_NETWORK_SELECTION_PACKAGE);
+        when(mApp.getString(R.string.mobile_network_settings_class)).thenReturn(
+                MOBILE_NETWORK_SELECTION_CLASS);
+    }
+
+    private static void replaceInstance(final Class c,
+            final String instanceName, final Object obj, final Object newValue) throws Exception {
+        Field field = c.getDeclaredField(instanceName);
+        field.setAccessible(true);
+        field.set(obj, newValue);
+    }
+}