[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 7067d75ade -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/13445069

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I20bd38ee6755881250ebfe38e3ba42cf65df5bb2
diff --git a/Android.bp b/Android.bp
index 1887a8a..6f97d86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,7 @@
         "ims-common",
         "libprotobuf-java-lite",
         "unsupportedappusage",
+        "org.apache.http.legacy",
     ],
 
     static_libs: [
@@ -35,6 +36,8 @@
         "com.android.phone.common-lib",
         "guava",
         "PlatformProperties",
+        "modules-utils-os",
+        "nist-sip",
     ],
 
     srcs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 425440a..a34c52e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -24,7 +24,6 @@
 
     <original-package android:name="com.android.phone" />
 
-    <protected-broadcast android:name="android.telecom.action.TTY_PREFERRED_MODE_CHANGED" />
     <protected-broadcast android:name="android.telecom.action.CURRENT_TTY_MODE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.SERVICE_STATE" />
     <protected-broadcast android:name="android.intent.action.RADIO_TECHNOLOGY" />
@@ -41,6 +40,7 @@
     <protected-broadcast android:name="android.provider.Telephony.SIM_FULL" />
     <protected-broadcast android:name="com.android.internal.telephony.data-restart-trysetup" />
     <protected-broadcast android:name="com.android.internal.telephony.data-stall" />
+    <protected-broadcast android:name="com.android.internal.telephony.provisioning_apn_alarm" />
     <protected-broadcast android:name="android.intent.action.DATA_SMS_RECEIVED" />
     <protected-broadcast android:name="android.provider.Telephony.SMS_RECEIVED" />
     <protected-broadcast android:name="android.provider.Telephony.SMS_DELIVER" />
@@ -60,6 +60,7 @@
     <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE" />
     <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
     <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+    <protected-broadcast android:name= "com.android.internal.telephony.PROVISION" />
     <protected-broadcast android:name= "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED" />
     <protected-broadcast android:name= "com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED" />
     <protected-broadcast android:name= "com.android.intent.isim_refresh" />
@@ -82,12 +83,15 @@
     <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
     <protected-broadcast android:name= "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
     <protected-broadcast android:name= "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" />
+    <protected-broadcast android:name= "com.android.internal.telephony.action.COUNTRY_OVERRIDE" />
     <protected-broadcast android:name= "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" />
+    <protected-broadcast android:name= "com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID" />
     <protected-broadcast android:name= "android.telephony.action.SIM_CARD_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED" />
+    <protected-broadcast android:name= "android.telephony.action.TOGGLE_PROVISION" />
     <protected-broadcast android:name= "android.telephony.action.NETWORK_COUNTRY_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.MULTI_SIM_CONFIG_CHANGED" />
@@ -95,6 +99,9 @@
     <!-- For Vendor Debugging in Telephony -->
     <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
 
+    <protected-broadcast android:name= "android.intent.action.SUBSCRIPTION_INFO_RECORD_ADDED" />
+    <protected-broadcast android:name= "android.intent.action.ACTION_MANAGED_ROAMING_IND" />
+
     <!-- Allows granting runtime permissions to telephony related components. -->
     <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS" />
 
@@ -210,11 +217,17 @@
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
-    <!-- Allows us to whitelist receivers of the
+    <!-- Allows us to allow list receivers of the
          ACTION_SIM_SLOT_STATUS_CHANGED broadcast to start activities
          from the background.  -->
     <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
     <uses-permission android:name="android.permission.NETWORK_STATS_PROVIDER" />
+    <uses-permission android:name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
+    <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"/>
+    <uses-permission android:name="android.permission.BIND_GBA_SERVICE"/>
+
+    <!-- Needed to listen to changes in projection state. -->
+    <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>
 
     <application android:name="PhoneApp"
             android:persistent="true"
@@ -233,11 +246,23 @@
                 android:readPermission="android.permission.READ_CONTACTS"
                 android:writePermission="android.permission.WRITE_CONTACTS" />
 
+        <provider android:name=".SimPhonebookProvider"
+            android:authorities="com.android.simphonebook"
+            android:multiprocess="true"
+            android:exported="true"
+            android:readPermission="android.permission.READ_CONTACTS"
+            android:writePermission="android.permission.WRITE_CONTACTS" />
+
+        <provider android:name="com.android.ims.rcs.uce.eab.EabProvider"
+                android:authorities="eab"
+                android:exported="false"/>
+
         <!-- Dialer UI that only allows emergency calls -->
         <activity android:name="EmergencyDialer"
             android:label="@string/emergencyDialerIconLabel"
             android:theme="@style/EmergencyDialerTheme"
             android:screenOrientation="portrait"
+            android:exported="true"
             android:resizeableActivity="false">
             <intent-filter>
                 <action android:name="com.android.phone.EmergencyDialer.DIAL" />
@@ -265,6 +290,7 @@
             android:label="@string/simContacts_title"
             android:theme="@style/SimImportTheme"
             android:screenOrientation="portrait"
+            android:exported="true"
             android:icon="@mipmap/ic_launcher_contacts">
 
             <intent-filter>
@@ -276,6 +302,7 @@
 
         <activity android:name="com.android.phone.settings.fdn.FdnList"
                 android:label="@string/fdnListLabel"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
@@ -290,6 +317,7 @@
 
         <activity android:name="GsmUmtsCallOptions"
                 android:label="@string/gsm_umts_options"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -298,6 +326,7 @@
 
         <activity android:name="CdmaCallOptions"
                 android:label="@string/cdma_options"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -307,6 +336,17 @@
         <activity android:name="GsmUmtsCallForwardOptions"
                 android:label="@string/labelCF"
                 android:configChanges="orientation|screenSize|keyboardHidden"
+                android:exported="true"
+                android:theme="@style/DialerSettingsLight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="CdmaCallForwardOptions"
+                android:label="@string/labelCF"
+                android:configChanges="orientation|screenSize|keyboardHidden"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -316,6 +356,7 @@
         <activity android:name="GsmUmtsCallBarringOptions"
                 android:label="@string/labelCallBarring"
                 android:configChanges="orientation|screenSize|keyboardHidden"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -325,6 +366,7 @@
         <activity android:name="GsmUmtsAdditionalCallOptions"
                 android:label="@string/labelGSMMore"
                 android:configChanges="orientation|screenSize|keyboardHidden"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -334,6 +376,7 @@
         <!-- fdn setting -->
         <activity android:name="com.android.phone.settings.fdn.FdnSetting"
                 android:label="@string/fdn"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -343,6 +386,7 @@
         <!-- SIM PIN setting -->
         <activity android:name="EnableIccPinScreen"
                 android:label="@string/enable_pin"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -352,6 +396,7 @@
 
         <activity android:name="ChangeIccPinScreen"
                 android:label="@string/change_pin"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -379,6 +424,7 @@
         <activity android:name="CallFeaturesSetting"
                 android:label="@string/call_settings"
                 android:configChanges="orientation|screenSize|keyboardHidden"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
@@ -391,6 +437,7 @@
         <!-- Activation service that trigger OTASP sim provisioning -->
         <service android:name=".otasp.OtaspActivationService" android:launchMode="singleInstance"
             androidprv:systemUserOnly="true"
+            android:exported="true"
             android:permission="android.permission.MODIFY_PHONE_STATE">
             <intent-filter>
                 <action android:name="android.service.simActivation.SimActivationService" />
@@ -407,6 +454,7 @@
         <!-- "Accessibility" settings UI. Referenced by Dialer application. -->
         <activity android:name="com.android.phone.settings.AccessibilitySettingsActivity"
                 android:label="@string/accessibility_settings_activity_title"
+                android:exported="true"
                 android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -421,6 +469,7 @@
 
         <!-- service to dump telephony information -->
         <service android:name="com.android.phone.TelephonyDebugService"
+                android:exported="true"
                  android:permission="android.permission.DUMP">
             <intent-filter>
                 <action android:name="com.android.phone.TelephonyDebugService" />
@@ -430,6 +479,7 @@
         <!-- Handler for EuiccManager's public-facing intents. -->
         <activity android:name=".euicc.EuiccUiDispatcherActivity"
             android:theme="@android:style/Theme.NoDisplay"
+            android:exported="true"
             android:permission="android.permission.MODIFY_PHONE_STATE">
             <!-- Max out priority to ensure nobody else will handle these intents. -->
             <intent-filter android:priority="1000">
@@ -450,6 +500,7 @@
             EuiccController#RESOLUTION_ACTIVITY_CLASS_NAME
         -->
         <activity android:name=".euicc.EuiccResolutionUiDispatcherActivity"
+            android:exported="true"
             android:permission="android.permission.CALL_PRIVILEGED">
             <!-- Max out priority to ensure nobody else will handle these intents. -->
             <intent-filter android:priority="1000">
@@ -465,6 +516,7 @@
         -->
         <activity android:name=".euicc.EuiccPrivilegedActionUiDispatcherActivity"
                   android:theme="@android:style/Theme.NoDisplay"
+                  android:exported="true"
                   android:permission="android.permission.CALL_PRIVILEGED">
             <!-- Max out priority to ensure nobody else will handle these intents. -->
             <intent-filter android:priority="1000">
@@ -484,6 +536,7 @@
             whitelisted by the underlying eUICC service implementation (i.e. the LPA).
         -->
         <activity android:name=".euicc.EuiccPublicActionUiDispatcherActivity"
+            android:exported="true"
             android:theme="@android:style/Theme.NoDisplay">
             <!-- Max out priority to ensure nobody else will handle these intents. -->
             <intent-filter android:priority="1000">
@@ -497,6 +550,7 @@
             android:excludeFromRecents="true"
             android:label="@string/ecm_exit_dialog"
             android:launchMode="singleTop"
+            android:exported="true"
             android:theme="@android:style/Theme.Translucent.NoTitleBar">
             <intent-filter>
                 <action android:name="com.android.phone.action.ACTION_SHOW_ECM_EXIT_DIALOG" />
@@ -509,13 +563,15 @@
         <service android:name="com.android.services.telephony.sip.SipConnectionService"
                  android:label="@string/sip_connection_service_label"
                  android:singleUser="true"
+                 android:exported="true"
                  android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
             <intent-filter>
                 <action android:name="android.telecom.ConnectionService" />
             </intent-filter>
         </service>
 
-        <receiver android:name="com.android.services.telephony.sip.SipIncomingCallReceiver">
+        <receiver android:name="com.android.services.telephony.sip.SipIncomingCallReceiver"
+            android:exported="true">
             <intent-filter>
                 <action android:name="android.net.sip.action.SIP_INCOMING_CALL" />
             </intent-filter>
@@ -523,6 +579,7 @@
 
         <activity android:name="com.android.services.telephony.sip.SipPhoneAccountSettingsActivity"
                 android:theme="@android:style/Theme.NoDisplay"
+                android:exported="true"
                 android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.telecom.action.CONFIGURE_PHONE_ACCOUNT" />
@@ -536,6 +593,7 @@
                   android:launchMode="singleTop"
                   android:configChanges="orientation|screenSize|keyboardHidden"
                   android:uiOptions="splitActionBarWhenNarrow"
+                  android:exported="true"
                   android:parentActivityName="com.android.phone.CallFeaturesSetting" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -548,7 +606,8 @@
                 android:uiOptions="splitActionBarWhenNarrow">
         </activity>
 
-        <service android:name="com.android.services.telephony.sip.components.TelephonySipService">
+        <service android:name="com.android.services.telephony.sip.components.TelephonySipService"
+            android:exported="true">
             <intent-filter>
                 <action android:name="android.net.sip.action.START_SIP" />
             </intent-filter>
@@ -565,6 +624,7 @@
 
         <activity android:name="com.android.phone.settings.PhoneAccountSettingsActivity"
             android:label="@string/phone_accounts"
+            android:exported="true"
             android:theme="@style/DialerSettingsLight">
             <intent-filter>
                 <action android:name="android.telecom.action.CHANGE_PHONE_ACCOUNTS" />
@@ -576,6 +636,7 @@
             android:label="@string/voicemail"
             android:configChanges="orientation|screenSize|keyboardHidden|screenLayout"
             android:screenOrientation="portrait"
+            android:exported="true"
             android:theme="@style/DialerSettingsLight">
             <intent-filter >
                 <!-- DO NOT RENAME. There are existing apps which use this string. -->
@@ -593,6 +654,7 @@
                 android:singleUser="true"
                 android:name="com.android.services.telephony.TelephonyConnectionService"
                 android:label="@string/pstn_connection_service_label"
+                android:exported="true"
                 android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
             <intent-filter>
                 <action android:name="android.telecom.ConnectionService" />
@@ -635,12 +697,14 @@
             android:name="com.android.phone.vvm.RemoteVvmTaskManager"
             android:exported="false"/>
         <service android:name="com.android.internal.telephony.CellularNetworkService"
+            android:exported="true"
             android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" >
             <intent-filter>
                 <action android:name="android.telephony.NetworkService" />
             </intent-filter>
         </service>
         <service android:name="com.android.internal.telephony.dataconnection.CellularDataService"
+            android:exported="true"
             android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" >
             <intent-filter>
                 <action android:name="android.telephony.data.DataService" />
@@ -650,6 +714,7 @@
         <activity
             android:name=".settings.RadioInfo"
             android:label="@string/phone_info_label"
+            android:exported="true"
             android:theme="@style/Theme.AppCompat.DayNight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -659,6 +724,7 @@
 
         <activity android:name=".settings.BandMode"
                   android:label="@string/band_mode_title"
+                  android:exported="true"
                   android:theme="@style/Theme.AppCompat.DayNight">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/TEST_MAPPING b/TEST_MAPPING
index e75dcb0..75b9d49 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,6 +7,9 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "name": "CarrierAppIntegrationTestCases"
     }
   ]
 }
diff --git a/ecc/input/OWNERS b/ecc/input/OWNERS
new file mode 100644
index 0000000..d9ecbb7
--- /dev/null
+++ b/ecc/input/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+djkrause@google.com
+satk@google.com
+somakala@google.com
\ No newline at end of file
diff --git a/ecc/output/OWNERS b/ecc/output/OWNERS
new file mode 100644
index 0000000..d9ecbb7
--- /dev/null
+++ b/ecc/output/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+djkrause@google.com
+satk@google.com
+somakala@google.com
\ No newline at end of file
diff --git a/proguard.flags b/proguard.flags
index c707f76..8eafd30 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -7,4 +7,9 @@
 -keepclassmembers class * {
 @**.NeededForTesting *;
 }
+# TODO: remove this after call composer gets more integrated.
+# for the time being, this is here so that the tests don't fail when encountering dead code.
+-keep class com.android.phone.callcomposer.** {
+ *;
+}
 -verbose
\ No newline at end of file
diff --git a/res/drawable/cupcake.png b/res/drawable/cupcake.png
new file mode 100644
index 0000000..dcc74e5
--- /dev/null
+++ b/res/drawable/cupcake.png
Binary files differ
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 40c2e53..72627a3 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -122,6 +122,37 @@
             <TextView android:id="@+id/ul_kbps" style="@style/info_value" />
         </LinearLayout>
 
+
+        <!-- EN-DC Available -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/endc_available_label" android:text="@string/radio_info_endc_available" style="@style/info_label" />
+            <TextView android:id="@+id/endc_available" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- DCNR Restricted -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/dcnr_restricted_label" android:text="@string/radio_info_dcnr_restricted" style="@style/info_label" />
+            <TextView android:id="@+id/dcnr_restricted" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR Available -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_available_label" android:text="@string/radio_info_nr_available" style="@style/info_label" />
+            <TextView android:id="@+id/nr_available" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR State -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_state_label" android:text="@string/radio_info_nr_state" style="@style/info_label" />
+            <TextView android:id="@+id/nr_state" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR Frequency -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_frequency_label" android:text="@string/radio_info_nr_frequency" style="@style/info_label" />
+            <TextView android:id="@+id/nr_frequency" style="@style/info_value" />
+        </LinearLayout>
+
         <!-- Physical Channel Config -->
         <LinearLayout style="@style/RadioInfo_entry_layout">
             <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
@@ -303,11 +334,6 @@
             android:background="?android:attr/listDivider" />
 
         <!-- CellInfoListRate Selection -->
-        <!-- Location -->
-        <LinearLayout style="@style/RadioInfo_entry_layout">
-            <TextView android:text="@string/radio_info_signal_location_label" style="@style/info_label" />
-            <TextView android:id="@+id/location" style="@style/info_value" />
-        </LinearLayout>
 
         <TextView
                 android:layout_width="match_parent"
diff --git a/res/layout/sim_ndp.xml b/res/layout/sim_ndp.xml
index 5f03d7b..e16f99a 100644
--- a/res/layout/sim_ndp.xml
+++ b/res/layout/sim_ndp.xml
@@ -35,6 +35,13 @@
                 android:layout_height="wrap_content"
                 android:text="@string/label_ndp"/>
 
+        <TextView
+                android:id="@+id/perso_phoneid_text"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/label_phoneid"/>
+
         <EditText android:id="@+id/pin_entry"
                 android:inputType="textPassword"
                 android:imeOptions="actionDone"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 5260467..3c4d561 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Stemboodskapinstellings kan slegs deur die primêre gebruiker gewysig word."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Jou SIM-kaart is oopgesluit. Jou foon sluit tans oop…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM-netwerk ontsluit PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM gesluit vir operateur"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ontsluit"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Maak toe"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Versoek tans netwerkontsluiting…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Stuur aan na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Af"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Jou diensverskaffer ondersteun nie die deaktivering van oproepaanstuur wanneer jou foon onbereikbaar is nie."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Jou diensverskaffer ondersteun nie oproepaanstuur nie."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Skakel Oproep Wat Wag aan?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Jy sal tydens \'n oproep in kennis gestel word van inkomende oproepe"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Skakel aan"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Kanselleer"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA-Oproep Wat Wag onder IMS is Aan"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA-Oproep Wat Wag onder IMS is Af"</string>
     <string name="updating_title" msgid="6130548922615719689">"Belinstellings"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Oproepinstellings kan net deur die administrateur verander word."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Instellings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Sub-ID van verstekdata-SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Aflaaibandwydte (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Oplaaibandwydte (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Selligginginligting (opgeskort):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fisieke LTE-kanaalopstelling:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Herlaaikoers van selinligting:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle selmetingsinligting:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Herlaai"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Wissel DNS-kontrole"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-spesifieke inligting/instellings"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC is beskikbaar:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR is beperk:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR is beskikbaar:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-frekwensie:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Stel radiobandmodus"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Laai tans bandlys …"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Stel"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Fooninligting"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Diensverskaffervoorsiening-inligting"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger-diensverskaffervoorsiening"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Voorstel: Verbeter Bluetooth-konnektiwiteit"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Kennisgewing oor oproepgehalte"</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d402b04..e7324e6 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -50,6 +50,7 @@
     <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>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ክፈት"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"አሰናብት"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"አውታረመረብ ለማስከፈት በመጠየቅ ላይ..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"ጥሪ መጠበቂያ ይብራ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"በጥሪ ጊዜ፣ ስለ ገቢ ጥሪዎች እንዲያውቁት ይደረጋል"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"አብራ"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ይቅር"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"በIMS ስር ያለው የCDMA ጥሪ መጠበቂያ በርቷል"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"በIMS ስር ያለው የCDMA ጥሪ መጠበቂያ ጠፍቷል"</string>
     <string name="updating_title" msgid="6130548922615719689">"የጥሪ ቅንብሮች"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"የጥሪ ቅንብሮች በአስተዳዳሪ ተጠቃሚው ብቻ ነው ሊለወጡ የሚችሉት።"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ቅንብሮች (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"የነባሪ ውሂብ ሲም SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"የUL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"የሕዋስ የአካባቢ መረጃ (የተቋረጠ)፦"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"የLTE አካላዊ ሰርጥ ውቅረት:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"የሕዋስ መረጃ እድሳት ፍጥነት፡"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ሁሉም የሕዋስ መለኪያ መረጃ፡"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"አድስ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"የDNS ፍተሻን ቀያይር"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-የተወሰነ መረጃ/ቅንብሮች"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ይገኛል፦"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ተገድቧል፦"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ይገኛል፦"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR ሁኔታ፦"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ድግግሞሽ፦"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"የሬዲዮ ባንድ ሁነታን ያቀናጁ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"የባንድ ዝርዝርን በመጫን ላይ…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"አዋቅር"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"የስልክ መረጃ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"የአገልግሎት አቅራቢ አቅርቦት መረጃ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"የቀስቅሴ አገልግሎት አቅራቢ አቅርቦት"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"የአስተያየት ጥቆማ፦ የብሉቱዝን ግንኙነት ያሻሽሉ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"የጥሪ ጥራት ማሳወቂያ"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index fda3c77..3f120c8 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -50,6 +50,7 @@
     <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">"‏رمز PIN لإلغاء تأمين شبكة SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"‏شريحة SIM مقيدَّة إلى مشغّل الشبكة"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"فتح قفل"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"استبعاد"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"جارٍ طلب فتح قفل الشبكة..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"هل تريد تفعيل ميزة انتظار المكالمات؟"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"خلال إحدى المكالمات، سيتم إخطارك بشأن المكالمات الواردة."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"تفعيل"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"إلغاء"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"‏تفعيل ميزة انتظار مكالمات CDMA في ظل IMS"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"‏إيقاف ميزة انتظار مكالمات CDMA في ظل IMS"</string>
     <string name="updating_title" msgid="6130548922615719689">"إعدادات الاتصال"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"لا يمكن تغيير إعدادات المكالمات إلا بواسطة المستخدم الإداري."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"الإعدادات (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -879,7 +887,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"‏المعرّف الفرعي لشريحة SIM التلقائية للبيانات:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"‏معدّل نقل بيانات DL (كيلوبت في الثانية):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"‏معدّل نقل بيانات UL (كيلوبت في الثانية):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"معلومات الموقع الخلوية (تم الإيقاف):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"‏ضبط قناة LTE Physical:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"معدّل إعادة تحميل المعلومات الخلوية:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"جميع معلومات القياس الخلوية:"</string>
@@ -910,6 +917,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"إعادة التحميل"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"تبديل فحص نظام أسماء النطاقات"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"المعلومات/الإعدادات المتعلّقة بالمصنّع الأصلي للجهاز"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"‏EN-DC متوفر:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"‏تم حظر DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"‏NR متوفر:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"‏حالة NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"‏تردد NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"تحديد وضع النطاق اللاسلكي"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"جارٍ تحميل قائمة النطاقات…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ضبط"</string>
@@ -919,4 +931,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"معلومات الهاتف"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"معلومات توفير خدمة مشغّل شبكة الجوّال"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"توفير خدمة مشغّل شبكة الجوّال"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"اقتراح: تحسين نطاق اتصال البلوتوث"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"إشعار بشأن جودة المكالمة"</string>
 </resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 873030b..ca997de 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ভইচমেইল ছেটিংসমূহ কেৱল মুখ্য ব্যৱহাৰকাৰীয়ে হে সংশোধন কৰিব পাৰে।"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"আপোনাৰ ছিম কাৰ্ডখন অৱৰোধৰ পৰা আঁতৰোৱা হ’ল। আপোনাৰ ফ\'নটো আনলক কৰি থকা হৈছে…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"ছিম নেটৱৰ্ক আনলক পিন"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"অপাৰেটৰৰ বাবে ছিম লক কৰা হৈছে"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"আনলক"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"অগ্ৰাহ্য কৰক"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"নেটৱৰ্ক আনলক কৰিবলৈ অনুৰোধ কৰি থকা হৈছে…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"কল অপেক্ষাৰত সুবিধাটো অন কৰিবনে?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"এটা কল চলি থাকোঁতে আপোনাক অন্তৰ্গামী কলসমূহৰ বিষয়ে জনোৱা হ\'ব"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"অন কৰক"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"বাতিল কৰক"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMSত CDMA কল অপেক্ষাৰত সুবিধাটো অন আছে"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMSত CDMA কল অপেক্ষাৰত সুবিধাটো অফ আছে"</string>
     <string name="updating_title" msgid="6130548922615719689">"কল ছেটিংসমূহ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"কেৱল প্ৰশাসকে কল ছেটিংসমূহ সলনি কৰিব পাৰে।"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ছেটিংসমূহ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ডিফ’ল্ট ডেটা ছিমৰ ছাবআইডি:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL বেণ্ডৱিথ (কেবিপিএছ):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL বেণ্ডৱিথ (কেবিপিএছ):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"চেল অৱস্থানৰ তথ্য (অনুমোদিত নহয়):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিকেল চেনেলৰ কনফিগাৰেশ্বন:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"চেল তথ্য ৰিফ্ৰেশ্বৰ হাৰ:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সকলো চেল পৰিমাপৰ তথ্য:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ৰিফ্ৰেশ্ব কৰক"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS পৰীক্ষা ট’গল কৰক"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM বিশেষক তথ্য/ছেটিংসমূহ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC উপলব্ধ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR প্ৰতিবন্ধিত:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR উপলব্ধ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR স্থিতি:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ফ্ৰিকুৱেন্সী:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ৰেডিঅ’ৰ বেণ্ড ম’ড ছেট কৰক"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"বেণ্ড সূচীখন ল’ড কৰি থকা হৈছে…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ছেট কৰক"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ফ\'নৰ তথ্য"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"বাহকৰ প্ৰ’ভিজনিং তথ্য"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"বাহকৰ প্ৰ’ভিজনিং সূচনা কৰক"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"পৰামৰ্শ: ব্লুটুথ সংযোগ উন্নত কৰক"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"কলৰ গুণগত মানৰ জাননী"</string>
 </resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 86bb6bc..5376968 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Səsli E-məktub Ayarları yalnız Əsas İstifadəçi tərəfindən dəyişdirilə bilər."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM kartınızın kilidi açıldı. Telefonunuzun da kilidi açılır…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM şəbəkəni kiliddən çıxaran PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SİM operator üçün kilidlənib"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Kilidi aç"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Kənarlaşdır"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Şəbəkə kilidinin açılması tələbi göndərilir…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g> nömrəsinə yönləndirilir"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Deaktiv"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Sizin mobil daşıyıcı telefon əlçatmaz olduğu zaman zəng yönləndirməni deaktiv etməyi dəstəkləmir."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatorunuz zəngin yönləndirilməsini dəstəkləmir."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Zəng gözlətmə aktiv edilsin?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Zəng zamanı gələn zənglər haqqında bildiriş alacaqsınız"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktiv edin"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Ləğv edin"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS ilə CDMA zəng gözlətməsi aktivdir"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS ilə CDMA zəng gözlətməsi deaktivdir"</string>
     <string name="updating_title" msgid="6130548922615719689">"Zəng ayarları"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Zəng parametrləri yalnız admin olan istifadəçi tərəfindən dəyişdirilə bilər."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ayarlar ( <xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g> )"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Defolt data SIM üçün alt Id:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Buraxılışı (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Buraxılışı (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Xananın məkan məlumatı (ləğv edilib):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziki Kanal Konfiqurasiyası:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobil məlumatın yenilənmə göstəricisi:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Operatorun bütün mobil ölçü məlumatı:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Yeniləyin"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS Yoxlanışına keçin"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Orijinal Avadanlıq İstehsalçısının Məlumatı/Ayarlar"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC Əlçatandır:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR Məhdudlaşdırılıb:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR Əlçatandır:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR Statusu:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR Tezliyi:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Radio Diapazon Rejimini Quraşdırın"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Diapazon Siyahısı Yüklənir…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ayarlayın"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon məlumatı"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator Təchizat Məlumatı"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operator Təchizatlanmasını aktiv edin"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Təklif: Bluetooth bağlantısını təkmilləşdirin"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Zəng keyfiyyəti bildirişi"</string>
 </resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index b78259a..7ab9248 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Samo primarni korisnik može da menja podešavanja govorne pošte."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Vaša SIM kartica je odblokirana. Telefon se otključava..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN za otključavanje mreže na SIM kartici"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM kartica je zaključana za operatera"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Otključaj"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Odbaci"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Traženje otključavanja mreže"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Prosleđuje se na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Isključeno"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Mobilni operater ne podržava onemogućavanje preusmeravanja poziva kada je telefon nedostupan."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Vaš mobilni operater ne podržava preusmeravanje poziva."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Želite da uključite stavljanje poziva na čekanje?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Tokom poziva ćete dobijati obaveštenja o dolaznim pozivima"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Uključi"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Otkaži"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Stavljanje CDMA poziva na čekanje u IMS-u je uključeno"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Stavljanje CDMA poziva na čekanje u IMS-u je isključeno"</string>
     <string name="updating_title" msgid="6130548922615719689">"Podešavanja poziva"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Samo korisniku sa administratorskim pravima je dozvoljeno da menja podešavanja poziva."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Podešavanja (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubID podrazumevanog SIM-a za podatke:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusni opseg (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusni opseg (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji predajnika (zastarelo):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Učestalost osvežavanja informacija o predajniku:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o merenju za predajnik:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Osveži"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Uključi/isključi proveru DNS-a"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informacije/podešavanja specifična za proizvođača originalne opreme"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC dostupno:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ograničeno:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR dostupno:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR stanje:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR učestalost:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Podesite režim radijskog opsega"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Učitava se lista opsega…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Podesi"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informacije o dodeli mobilnog operatera"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Pokretanje dodele mobilnog operatera"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Predlog: poboljšajte Bluetooth vezu"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Obaveštenje o kvalitetu poziva"</string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index b59a092..ee1c068 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -50,6 +50,7 @@
     <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">"PIN-код разблакавання сеткі SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Можна выкарыстоўваць толькі SIM-карту аператара"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Разблакаваць"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Адхіліць"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Запыт разблакавання сеткі..."</string>
@@ -123,6 +124,13 @@
     <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">"Ваш аператар не падтрымлівае адключэнне пераадрасацыi выклікаў, калі тэлефон недаступны."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Ваш аператар не падтрымлівае пераадрасацыю выкліку."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Уключыць чаканне выкліку?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Вы будзеце атрымліваць апавяшчэнні аб уваходных выкліках падчас бягучых размоў"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Уключыць"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Скасаваць"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Чаканне выкліку па тэхналогіі CDMA (IMS) уключана"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Чаканне выкліку па тэхналогіі CDMA (IMS) выключана"</string>
     <string name="updating_title" msgid="6130548922615719689">"Налады выклікаў"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Налады выклікаў можа мяняць толькі адміністратар."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Налады (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubID стандартнай SIM-карты для перадачы даных:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Прапускная здольнасць канала спампоўвання (кбіт/с):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Прапускная здольнасць канала запампоўвання (кбіт/с):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Інфармацыя пра месцазнаходжанне сотавай ячэйкі (састарэлая):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Канфігурацыя фізічнага канала LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частата абнаўлення даных сотавай сеткі:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усе паказчыкі сотавай сеткі:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Абнавіць"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Уключыць/выключыць праверку DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Інфармацыя/налады пастаўшчыка"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Даступнасць EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Абмежаванне DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Даступнасць NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Стан NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Частата NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Задаць рэжым радыёдыяпазону"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Загружаецца спіс дыяпазонаў…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Задаць"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Звесткі аб тэлефоне"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Звесткі аб аператары"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запусціць сінхранізацыю з аператарам"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Прапанова: палепшыце якасць падключэння праз Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Апавяшчэнне пра якасць выкліку"</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 324ae82..d6eb65d 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -50,6 +50,7 @@
     <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">"PIN за отключване на SIM мрежа"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM картата е заключена към оператора"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Отключване"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Отхвърляне"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Изпраща се заявка за отключване на мрежата..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Да се включат ли изчакващите обаждания?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Ще получавате известие за входящи обаждания по време на обаждане"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Включване"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Отказ"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Изчакващите обаждания за CDMA с IMS са включени"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Изчакващите обаждания за CDMA с IMS са изключени"</string>
     <string name="updating_title" msgid="6130548922615719689">"Настройки за обаждане"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Само администраторът може да променя настройките за обаждане."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Настройки (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Идентификационен подномер на SIM картата за данни по подразбиране:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускателна способност при изтегляне (кб/сек):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускателна способност при качване (кб/сек):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информация за местоположението на клетката (оттеглено):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация на физическия канал на LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Честота на опресняване на информацията за клетките:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Цялата измервателна информация за клетките:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Опресняване"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Превключване на проверката на DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Информация/настройки, специфични за ОЕМ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Налично EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Ограничено DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Налично NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Състояние на NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Честота за NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Задаване на режима за радиодиапазона"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Списъкът с диапазони се зарежда…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Задаване"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Информация за телефона"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Информация за обезпечаването от оператора"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Задействане на обезпечаването от оператора"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Предложение: Подобрете връзката през Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Известия за качеството на обаждането"</string>
 </resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 0fb9e35..3cdc467 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ভয়েসমেল সেটিংস কেবলমাত্র প্রাথমিক ব্যবহারকারী দ্বারা পরিবর্তন করা যাবে।"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"আপনার সিম কার্ডকে অবরোধ মুক্ত করা হয়েছে৷ আপনার ফোন আনলক করা হচ্ছে..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"সিম নেটওয়ার্ক আনলক পিন"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"অপারেটরের জন্য সিম লক করা আছে"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"আনলক করুন"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"খারিজ করুন"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"নেটওয়ার্ক আনলকের অনুরোধ করা হচ্ছে..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"কল ওয়েটিং সুবিধা চালু করতে চান?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"কল চলার সময়ে ইনকামিং কল এলে আপনাকে জানানো হবে"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"চালু করুন"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"বাতিল করুন"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS-এ CDMA কল ওয়েটিং সুবিধা চালু আছে"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS-এ CDMA কল ওয়েটিং সুবিধা বন্ধ আছে"</string>
     <string name="updating_title" msgid="6130548922615719689">"কল সেটিংস"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"কেবলমাত্র প্রশাসক ব্যবহারকারী কল সেটিংস পরিবর্তন করতে পারবেন৷"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"সেটিংস (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ডিফল্ট ডেটা সিমের SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"ডিএল ব্যান্ডউইথ (কেবিপিএস):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"ইউএল ব্যান্ডউইথ (কেবিপিএস):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"সেল লোকেশন তথ্য (বন্ধ করা হয়েছে):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিক্যাল চ্যানেল কনফিগারেশন:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"সেল তথ্যে রিফ্রেশ রেট:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সমস্ত সেল পরিমাপ তথ্য:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"রিফ্রেশ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS চেক টগল করুন"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-নির্দিষ্ট তথ্য/সেটিংস"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC উপলভ্য:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR সীমাবদ্ধ করা আছে:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR উপলভ্য:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR স্ট্যাটাস:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ফ্রিকোয়েন্সি:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"রেডিও ব্যান্ড মোড সেট করুন"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ব্যান্ড তালিকা লোড হচ্ছে..."</string>
     <string name="band_mode_set" msgid="6657819412803771421">"সেট করুন"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ফোনের তথ্য"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"পরিষেবা প্রদানকারীর ব্যবস্থামূলক তথ্য"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ট্রিগার পরিষেবা প্রদানকারীর ব্যবস্থা"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"পরামর্শ: ব্লুটুথ কানেক্টিভিটি উন্নত করুন"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ফোন কলের কোয়ালিটি সংক্রান্ত বিজ্ঞপ্তি"</string>
 </resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 0f65b28..6b223e6 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Postavke govorne pošte može promijeniti samo Primarni korisnik."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Vaša SIM kartica je deblokirana. Telefon se otključava…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN za otključavanje mreže na SIM kartici"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM je zaključan za operatera"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Otključaj"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Odbaci"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Traži se otključavanje mreže…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Preusmjerava se na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Isključeno"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Vaš operater ne podržava onemogućavanje prosljeđivanja poziva kada ste nedostupni."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Vaš mobilni operater ne podržava prosljeđivanje poziva."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Uključiti poziv na čekanju?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Tokom poziva ćete primati obavještenja o dolaznim pozivima"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Uključi"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Otkaži"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA poziv na čekanju u okviru IMS-a je uključen"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA poziv na čekanju u okviru IMS-a je isključen"</string>
     <string name="updating_title" msgid="6130548922615719689">"Postavke poziva"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Postavke poziva može promijeniti samo administrator."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Postavke (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Pomoćni ID za zadani SIM za prijenos podataka:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji ćelije (zastarjele):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval osvježavanja informacija o ćeliji:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o mjerenju ćelije:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Osvježi"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Uključi/isključi provjeru DNS-a"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specifične informacije/postavke"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC dostupno:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ograničeno:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR dostupno:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR stanje:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR učestalost:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Postavite način radijskog opsega"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Učitavanje liste opsega…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Postavi"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operater koji pruža informacije"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktiviranje dodjele resursa operatera"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Prijedlog: poboljšajte Bluetooth povezivost"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Obavještenje o kvalitetu poziva"</string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 1f910eb..4beb631 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Només l\'usuari principal pot modificar la configuració dels missatges de veu."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"La targeta SIM s\'ha desbloquejat. El telèfon s\'està desbloquejant..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueig de xarxa SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloquejada per a l\'operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloqueja"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ignora"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"S\'està sol·licitant el desbloqueig de la xarxa..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"S\'està desviant a <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desactivat"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"El teu operador de telefonia mòbil no permet desactivar la desviació de trucades quan el telèfon estigui il·localitzable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"El teu operador no admet la desviació de trucades."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Vols activar l\'opció de trucada en espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durant una trucada, rebràs una notificació si tens cap trucada entrant"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activa"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel·la"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"L\'opció de trucada en espera de CDMA a IMS està activada"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"L\'opció de trucada en espera de CDMA a IMS està desactivada"</string>
     <string name="updating_title" msgid="6130548922615719689">"Configuració de trucada"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Només l\'administrador pot canviar la configuració de trucades."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Configuració (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Subidentificador de la SIM de dades predeterminada:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Amplada de banda de baixada (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Amplada de banda de pujada (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informació d\'ubicació del mòbil (obsoleta):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuració del canal físic de LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Freqüència d\'actualització de la informació del mòbil:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tota la informació de mesures del mòbil:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualitza"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activa o desactiva la comprovació de DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informació/configuració específica d\'OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponible:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR amb restriccions:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponible:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estat d\'NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Freqüència d\'NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Configura el mode de banda de senyal mòbil"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"S\'està carregant la llista de bandes…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Defineix"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informació del telèfon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informació de serveis de l\'operador"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activa els serveis de l\'operador"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggeriment: millora la connectivitat Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificació sobre la qualitat de la trucada"</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index c5d45ef..397c5ff 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Nastavení hlasové schránky může změnit pouze primární uživatel."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM karta byla odblokována. Telefon se odblokovává..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Kód PIN odblokování sítě pro SIM kartu"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Na kartě SIM je zámek operátora"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Odemknout"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Zavřít"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Žádost o odblokování sítě..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Hovory budou přesměrovány na číslo <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Vypnuto"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Váš operátor neumožňuje deaktivovat přesměrování hovorů, když je telefon nedostupný."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Váš operátor nepodporuje přesměrování hovorů."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Zapnout funkci Další hovor na lince?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"V průběhu hovoru budete dostávat upozornění na příchozí hovory."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Zap."</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Zrušit"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA – další hovor na lince ve službě IMS – zapnuto"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA – další hovor na lince ve službě IMS – vypnuto"</string>
     <string name="updating_title" msgid="6130548922615719689">"Nastavení hovorů"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Nastavení hovorů může změnit pouze uživatel s oprávněním administrátora."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Nastavení (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId výchozí datové SIM karty:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rychlost stahování (kB/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rychlost nahrávání (kB/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informace o poloze mobilní sítě (podpora ukončena):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurace fyzického kanálu LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval obnovení informací o mobilní síti:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všechny údaje o měření mobilní sítě:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Obnovit"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Přepnout kontrolu DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informace a nastavení specifické pro výrobce OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC k dispozici:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR zakázáno:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR k dispozici:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stav NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekvence NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Nastavit režim pásma bezdrátového modulu"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Načítání seznamu pásem…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Nastavit"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informace o telefonu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informace o zprovoznění služby u operátora"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Spustit zprovoznění služby u operátora"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Doporučení: Vylepšete připojení přes Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Oznámení o kvalitě hovoru"</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index da269e1..330998a 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Indstillingerne for telefonsvareren kan kun ændres af den primære bruger."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Blokeringen af dit SIM-kort er blevet ophævet. Din telefon låser op ..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Pinkode til oplåsning af SIM-netværket"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-kortet er låst for operatøren"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Lås op"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Luk"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Anmoder om oplåsning af netværk ..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Viderestiller til <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Fra"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Dit mobilselskab understøtter ikke deaktivering af viderestilling af opkald, når telefonen ikke er tilgængelig."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Dit mobilselskab understøtter ikke viderestilling af opkald."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Vil du aktivere ventende opkald?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Under et opkald får du en notifikation om indgående opkald."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktivér"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Annuller"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Ventende CDMA-opkald under IMS er aktiveret"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Ventende CDMA-opkald under IMS er deaktiveret"</string>
     <string name="updating_title" msgid="6130548922615719689">"Indstillinger for opkald"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Opkaldsindstillingerne kan kun ændres af administratorbrugeren."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Indstillinger (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Under-id for standard-SIM-kort til data:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde til download (kB/sek.):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde til upload (kB/sek.):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Oplysning om placering af celle (udfaset):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration for LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Opdateringsfrekvens for celleoplysninger:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle oplysninger om cellemåling:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Opdater"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Skift DNS-kontrol"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specifikke oplysninger/indstillinger"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Tilgængelig for EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Begrænset til DCNR"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Tilgængelig for NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Status for NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekvens for NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Konfigurer radiobåndstilstand"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Indlæser båndliste…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Angiv"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefonoplysninger"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Oplysninger om mobilselskab"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivér mobilselskab"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Forslag: Optimer Bluetooth-forbindelsen"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notifikation om opkaldskvalitet"</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 948c7cc..a9777db 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Mailboxeinstellungen können nur vom primären Nutzer geändert werden."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Deine SIM-Karte wurde entsperrt. Dein Telefon wird nun entsperrt..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Entsperr-PIN für netzgebundenes Gerät"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM für Anbieter gesperrt"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Entsperren"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Verwerfen"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Entsperrung des netzgebundenen Geräts wird angefordert..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Weiterleitung an <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Aus"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Dein Mobilfunkanbieter unterstützt die Deaktivierung der Anrufweiterleitung bei Nichterreichbarkeit nicht."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Dein Mobilfunkanbieter unterstützt die Anrufweiterleitung nicht."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Anklopfen aktivieren?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Du wirst während eines Anrufs über eingehende Anrufe benachrichtigt"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktivieren"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Abbrechen"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA-Anklopfen unter IMS aktiviert"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA-Anklopfen unter IMS deaktiviert"</string>
     <string name="updating_title" msgid="6130548922615719689">"Anrufeinstellungen"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Anrufeinstellungen können nur vom Administrator geändert werden."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Einstellungen (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Unter-ID der standardmäßigen Daten-SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-Bandbreite (kbit/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-Bandbreite (kbit/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Standortinformationen des Mobiltelefons (eingestellt):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguration des physischen LTE-Kanals:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Aktualisierungsrate der Mobiltelefoninformationen:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle Informationen zu Zellenmesswerten:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Aktualisieren"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS-Überprüfung ein-/ausschalten"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-spezifische Infos/Einstellungen"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC verfügbar:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR eingeschränkt:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR verfügbar:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-Status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-Frequenz:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Frequenzbereichmodus festlegen"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Frequenzliste wird geladen…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Festlegen"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Über das Telefon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informationen zur Nutzerverwaltung durch den Anbieter"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Nutzerverwaltung durch den Anbieter auslösen"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Vorschlag: Bluetooth-Verbindung optimieren"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Benachrichtigung zu Anrufqualität"</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 9b687c1..c7574d8 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -50,6 +50,7 @@
     <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">"Αριθμός PIN ξεκλειδώματος δικτύου κάρτας SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Η κάρτα SIM κλειδώθηκε για τον πάροχο"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ξεκλείδωμα"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Παράβλεψη"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Αίτηση ξεκλειδώματος δικτύου..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Ενεργοποίηση αναμονής κλήσης;"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Κατά τη διάρκεια μιας κλήσης θα ειδοποιείστε για εισερχόμενες κλήσεις"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Ενεργοποίηση"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Άκυρο"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Η αναμονή κλήσης σε λειτουργία άμεσων μηνυμάτων (ΙΜ) είναι απενεργοποιημένη"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Η αναμονή κλήσης σε λειτουργία άμεσων μηνυμάτων (ΙΜ) είναι απενεργοποιημένη"</string>
     <string name="updating_title" msgid="6130548922615719689">"Ρυθμίσεις κλήσης"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Οι ρυθμίσεις κλήσεων μπορούν να αλλάξουν μόνο από τον χρήστη που έχει ρόλο διαχειριστή."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ρυθμίσεις (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId προεπιλεγμένης SIM δεδομένων:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Εύρος ζώνης DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Εύρος ζώνης UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Πληροφορίες τοποθεσίας κινητής τηλεφωνίας (καταργήθηκε):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Διαμόρφωση φυσικού καναλιού LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ρυθμός ανανέωσης στοιχείων κινητής τηλεφωνίας:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Όλα τα στοιχεία μετρήσεων κινητής τηλεφωνίας:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Ανανέωση"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Εναλλαγή ελέγχου DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Πληροφορίες/ρυθμίσεις για OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC διαθέσιμο:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR με περιορισμό:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR διαθέσιμο:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Κατάσταση NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Συχνότητα NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Ρύθμιση λειτουργίας ζώνης συχνοτήτων πομπού"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Φόρτωση λίστας ζωνών…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ορισμός"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Πληροφορίες τηλεφώνου"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Πληροφορίες παροχής εταιρείας κινητής τηλεφωνίας"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Ενεργοποίηση παροχής εταιρείας κινητής τηλεφωνίας"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Πρόταση: Βελτιώστε τη συνδεσιμότητα Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Ειδοποίηση ποιότητας κλήσης"</string>
 </resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index d48a09c..f246913 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail settings can only be modified by the primary user."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Your SIM card has been unblocked. Your phone is unlocking…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM network unlock PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM locked for operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Unlock"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Dismiss"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Requesting network unlock…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Forwarding to <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Off"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your operator doesn\'t support disabling call forwarding when your phone is unreachable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your operator doesn\'t support call forwarding."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Turn on call waiting?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"During a call, you\'ll be notified about incoming calls"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Turn on"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA call waiting under IMS on"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA call waiting under IMS off"</string>
     <string name="updating_title" msgid="6130548922615719689">"Call settings"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Call settings can only be changed by the admin user."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Refresh"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS check"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific info/settings"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC available:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restricted:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR available:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR frequency:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Set radio band mode"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Loading band list…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Set"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion: Improve Bluetooth connectivity"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
 </resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index d5147e7..d325708 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail settings can only be modified by the primary user."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Your SIM card has been unblocked. Your phone is unlocking…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM network unlock PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM locked for operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Unlock"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Dismiss"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Requesting network unlock…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Forwarding to <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Off"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your operator doesn\'t support disabling call forwarding when your phone is unreachable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your operator doesn\'t support call forwarding."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Turn on call waiting?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"During a call, you\'ll be notified about incoming calls"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Turn on"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA call waiting under IMS on"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA call waiting under IMS off"</string>
     <string name="updating_title" msgid="6130548922615719689">"Call settings"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Call settings can only be changed by the admin user."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Refresh"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS check"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific info/settings"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC available:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restricted:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR available:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR frequency:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Set radio band mode"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Loading band list…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Set"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion: Improve Bluetooth connectivity"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index d48a09c..f246913 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail settings can only be modified by the primary user."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Your SIM card has been unblocked. Your phone is unlocking…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM network unlock PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM locked for operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Unlock"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Dismiss"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Requesting network unlock…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Forwarding to <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Off"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your operator doesn\'t support disabling call forwarding when your phone is unreachable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your operator doesn\'t support call forwarding."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Turn on call waiting?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"During a call, you\'ll be notified about incoming calls"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Turn on"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA call waiting under IMS on"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA call waiting under IMS off"</string>
     <string name="updating_title" msgid="6130548922615719689">"Call settings"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Call settings can only be changed by the admin user."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Refresh"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS check"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific info/settings"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC available:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restricted:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR available:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR frequency:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Set radio band mode"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Loading band list…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Set"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion: Improve Bluetooth connectivity"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index d48a09c..f246913 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail settings can only be modified by the primary user."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Your SIM card has been unblocked. Your phone is unlocking…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM network unlock PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM locked for operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Unlock"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Dismiss"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Requesting network unlock…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Forwarding to <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Off"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your operator doesn\'t support disabling call forwarding when your phone is unreachable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your operator doesn\'t support call forwarding."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Turn on call waiting?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"During a call, you\'ll be notified about incoming calls"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Turn on"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA call waiting under IMS on"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA call waiting under IMS off"</string>
     <string name="updating_title" msgid="6130548922615719689">"Call settings"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Call settings can only be changed by the admin user."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Refresh"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS check"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific info/settings"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC available:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restricted:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR available:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR frequency:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Set radio band mode"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Loading band list…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Set"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion: Improve Bluetooth connectivity"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 250a26d..cca7e56 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎Voicemail Settings can only be modified by the Primary User.‎‏‎‎‏‎"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎Your SIM card has been unblocked. Your phone is unlocking…‎‏‎‎‏‎"</string>
     <string name="label_ndp" msgid="7617392683877410341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎SIM network unlock PIN‎‏‎‎‏‎"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎SIM locked for operator‎‏‎‎‏‎"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎Unlock‎‏‎‎‏‎"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎Dismiss‎‏‎‎‏‎"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎Requesting network unlock…‎‏‎‎‏‎"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎Forwarding to ‎‏‎‎‏‏‎<xliff:g id="PHONENUMBER">{0}</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎Off‎‏‎‎‏‎"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎Your carrier doesn\'t support disabling call forwarding when your phone is unreachable.‎‏‎‎‏‎"</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎Your carrier doesn\'t support call forwarding.‎‏‎‎‏‎"</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎Turn on call waiting?‎‏‎‎‏‎"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎During a call, you\'ll be notified about incoming calls‎‏‎‎‏‎"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎Turn on‎‏‎‎‏‎"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎Cancel‎‏‎‎‏‎"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎CDMA Call Waiting under IMS On‎‏‎‎‏‎"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎CDMA Call Waiting under IMS Off‎‏‎‎‏‎"</string>
     <string name="updating_title" msgid="6130548922615719689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎Call settings‎‏‎‎‏‎"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎Call settings can only be changed by the admin user.‎‏‎‎‏‎"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎Settings (‎‏‎‎‏‏‎<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎SubId of default data SIM:‎‏‎‎‏‎"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎DL Bandwidth (kbps):‎‏‎‎‏‎"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎UL Bandwidth (kbps):‎‏‎‎‏‎"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎Cell Location Info (deprecated):‎‏‎‎‏‎"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎LTE Physical Channel Configuration:‎‏‎‎‏‎"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎Cell Info Refresh Rate:‎‏‎‎‏‎"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎All Cell Measurement Info:‎‏‎‎‏‎"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎Refresh‎‏‎‎‏‎"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‎Toggle DNS Check‎‏‎‎‏‎"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎OEM-specific Info/Settings‎‏‎‎‏‎"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎EN-DC Available:‎‏‎‎‏‎"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎DCNR Restricted:‎‏‎‎‏‎"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎NR Available:‎‏‎‎‏‎"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎NR State:‎‏‎‎‏‎"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎NR Frequency:‎‏‎‎‏‎"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎Set Radio Band Mode‎‏‎‎‏‎"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎Loading Band List…‎‏‎‎‏‎"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎Set‎‏‎‎‏‎"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎Phone info‎‏‎‎‏‎"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎Carrier Provisioning Info‎‏‎‎‏‎"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎Trigger Carrier Provisioning‎‏‎‎‏‎"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎Suggestion: Improve Bluetooth connectivity‎‏‎‎‏‎"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎Call Quality Notification‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 43d15be..d346ea0 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Solo el usuario principal puede cambiar la configuración del buzón de voz."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Tu tarjeta SIM ha sido desbloqueada. Tu dispositivo está desbloqueando..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueo de red de tarjeta SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloqueada para el operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Descartar"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Solicitando desbloqueo de red..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Reenviar a <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desactivado"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Tu proveedor no admite la inhabilitación del desvío de llamadas cuando no se puede acceder a tu teléfono."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Tu proveedor no admite el desvío de llamadas."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"¿Quieres activar la función de llamada en espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durante una llamada, recibirás notificaciones de llamadas entrantes"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activar"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancelar"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"La función de llamada en espera de CDMA en IMS está activada"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"La función de llamada en espera de CDMA en IMS está desactivada"</string>
     <string name="updating_title" msgid="6130548922615719689">"Config. de llamada"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Solo el usuario administrador puede cambiar la configuración de llamadas."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Configuración (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de SIM de datos predeterminada:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de descarga (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de carga (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Datos de ubicación del celular (obsoleto):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de datos del celular:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones del celular:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizar"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activar o desactivar la comprobación de DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Configuración/Datos específicos del OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponible:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restringida:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponible:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estado de NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frecuencia de NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Establecer modo de banda de radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Cargando lista de bandas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Establecer"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Información del teléfono"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Información del aprovisionamiento del proveedor"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activar aprovisionamiento del proveedor"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugerencia: Mejora la conectividad Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación de calidad de llamada"</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 742f996..98871c4 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"El usuario principal es el único que puede modificar los ajustes del buzón de voz."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"La tarjeta SIM se ha desbloqueado. El teléfono se está desbloqueando..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueo de red de tarjeta SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloqueada por el operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Cerrar"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Solicitando desbloqueo de red..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Desviando a <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desactivado"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Tu operador no permite inhabilitar el desvío de llamadas si no se puede establecer la llamada."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Tu operador no admite el desvío de llamadas."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"¿Quieres activar la llamada en espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Se te notificarán las llamadas entrantes mientras estés en una llamada"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activar"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancelar"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Llamada en espera de CDMA en IMS activada"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Llamada en espera de CDMA en IMS desactivada"</string>
     <string name="updating_title" msgid="6130548922615719689">"Ajustes de llamadas"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"El administrador es el único usuario que puede cambiar los ajustes de llamada."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ajustes (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de la SIM de datos predeterminada:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de bajada (Kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de subida (Kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Información sobre la ubicación del teléfono (obsoleto):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de la información del teléfono:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones de los teléfonos:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizar"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activar o desactivar comprobación de DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Ajustes o información específica de OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponible:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restringido:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponible:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estado de NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frecuencia de NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Establecer modo de banda de señal móvil"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Cargando lista de bandas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Seleccionar"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Información sobre el teléfono"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Información de servicios del operador"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activar servicios del operador"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugerencia: mejorar la conectividad Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación de calidad de la llamada"</string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 5d6a837..986525e 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Kõneposti seadeid saab muuta ainult peamine kasutaja."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Teie SIM-kaardi blokeering on tühistatud. Teie telefoni avamine ..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM-võrgu avamise PIN-kood"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-kaart on operaatori jaoks lukustatud"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ava"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Loobu"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Võrgu avamise taotlemine ..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Edastamine numbrile <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Väljas"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Teie operaator ei toeta kõneedastuse keelamist, kui teie telefon on levist väljas."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Teie operaator ei toeta kõnede suunamist."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Kas lülitada ootel kõne sisse?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Kõne ajal teavitatakse teid sissetulevatest kõnedest"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Lülita sisse"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Tühista"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA ootel kõne on IMS-i all sisse lülitatud"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA ootel kõne on IMS-i all välja lülitatud"</string>
     <string name="updating_title" msgid="6130548922615719689">"Kõneseaded"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Kõne seadeid saab muuta ainult administraator."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Seaded (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Andmete vaike-SIM-kaardi alam-ID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-i ribalaius (kbit/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-i ribalaius (kbit/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Kärje asukohateave (tugi on katkestatud):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE füüsilise kanali konfiguratsioon:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kärje teabe värskendamissagedus:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Kõik kärje mõõteandmed:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Värskendamine"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS-i kontrolli sisse- või väljalülitamine"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-i teave/seaded"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC saadaval:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR piiratud:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR saadaval:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-i olek:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-i sagedus:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Raadio ribarežiimi määramine"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Ribaloendi laadimine …"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Määra"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoniteave"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operaatori ettevalmistamise teave"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operaatori ettevalmistamise päästik"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Soovitus: parandage Bluetoothi ühenduvust"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Kõnekvaliteedi märguanne"</string>
 </resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 844f2f2..86cd334 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Erabiltzaile nagusiak bakarrik alda ditzake erantzungailuaren ezarpenak."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM txartela desblokeatu da. Telefonoa desblokeatzen…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM sarea desblokeatzeko PIN kodea"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Operadore hau dauka finkatuta SIM txartelak:"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desblokeatu"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Baztertu"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Sarea desblokeatzeko eskatzen…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen dira"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desaktibatuta"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operadoreak ez du dei-desbideratzeak desgaitzea onartzen telefonoa eskuragarri ez dagoen bitartean."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operadoreak ez du onartzen dei-desbideratzea."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Deia zain uzteko aukera aktibatu nahi duzu?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Dei batean zaudenean, jakinarazpen bat jasoko duzu deiak jasotzen badituzu"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktibatu"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Utzi"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS zerbitzupean CDMA deiak zain uzteko aukera aktibatuta dago"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS zerbitzupean CDMA deiak zain uzteko aukera desaktibatuta dago"</string>
     <string name="updating_title" msgid="6130548922615719689">"Deien ezarpenak"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Administratzaileak soilik alda ditzake deien ezarpenak."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ezarpenak (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Datu-konexioetarako SIM lehenetsiaren azpiIDa:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Deskargatzeko banda-zabalera (Kb/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kargen banda-zabalera (Kb/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Sare mugikorraren kokapenaren informazioa (zaharkitua):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE kanal fisikoaren konfigurazioa:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Sare mugikorraren informazioa eguneratzeko maiztasuna:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sare mugikorraren neurketa guztien informazioa:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Freskatu"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Aldatu DNS egiaztapenaren egoera"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Jatorrizko fabrikatzailearen berariazko informazioa edota ezarpenak"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC erabilgarri:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR mugatuta:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR erabilgarri:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR estatua:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR maiztasuna:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Ezarri irrati-bandaren modua"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Banden zerrenda kargatzen…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ezarri"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefonoaren informazioa"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operadorearen hornikuntza-informazioa"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Abiarazi operadorearen hornikuntza"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Iradokizuna: hobetu Bluetooth-konexioa"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Deien kalitateari buruzko jakinarazpena"</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index af99b7a..60c0de1 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"فقط «کاربر اصلی» می‌تواند «تنظیمات پست صوتی» را تغییر دهد."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"قفل سیم کارت شما باز شده است. قفل گوشی در حال باز شدن است..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"پین بازگشایی قفل شبکه سیم"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"سیم‌کارت برای اپراتور قفل شد"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"بازگشایی قفل"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"رد کردن"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"در حال درخواست بازگشایی قفل شبکه..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"«انتظار مکالمه» روشن شود؟"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"درحین تماس، از تماس‌های ورودی مطلع خواهید شد"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"روشن کردن"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"لغو"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"‏«انتظار مکالمه CDMA» تحت IMS روشن است"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"‏«انتظار مکالمه CDMA» تحت IMS خاموش است"</string>
     <string name="updating_title" msgid="6130548922615719689">"تنظیمات تماس"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"فقط کاربر سرپرست می‌تواند تنظیمات تماس را تغییر دهد."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"تنظیمات (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"‏SubId مربوط به سیم‌کارت داده پیش‌فرض:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"‏پهنای باند DL (کیلوبیت بر ثانیه):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"‏پهنای باند UL (کیلوبیت بر ثانیه):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"اطلاعات مکان شبکه همراه (منسوخ شده):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"‏پیکربندی کانال فیزیکی LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"نرخ بازخوانی اطلاعات شبکه همراه:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"همه اطلاعات اندازه‌گیری شبکه همراه:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"بازخوانی"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"‏تغییر وضعیت علامت DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"‏تنظیمات/اطلاعات خاص OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"‏EN-DC دردسترس است:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"‏DCNR محدود شده است:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"‏NR دردسترس است:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"‏وضعیت NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"‏فرکانس NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"تنظیم حالت باند رادیو"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"درحال بار کردن فهرست باند…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"تنظیم"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"اطلاعات تلفن"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"اطلاعات ارائه شرکت مخابراتی"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"شروع ارائه شرکت مخابراتی"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"پیشنهاد: اتصال بلوتوث را بهبود دهید"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"اعلان کیفیت تماس"</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d3cdb65..495d5fa 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Vain ensisijainen käyttäjä voi muuttaa vastaajan asetuksia."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM-korttisi esto on purettu. Puhelimen lukitusta poistetaan..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM-verkko, PIN-koodin lukituksen poisto"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Operaattorin SIM lukittu"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Poista lukitus"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Hylkää"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Pyydetään verkon lukituksen poistoa..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Puhelu siirretään numeroon <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Ei päällä"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operaattorisi ei tue soitonsiirtojen poistamista käytöstä puhelimesi ollessa saavuttamattomissa."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operaattorisi ei tue soitonsiirtoa."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Otetaanko koputus käyttöön?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Sinulle ilmoitetaan puhelun aikana saapuvista puheluista"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Ota käyttöön"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Peruuta"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS:n alainen CDMA-koputus pois käytöstä"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS:n alainen CDMA-koputus pois käytöstä"</string>
     <string name="updating_title" msgid="6130548922615719689">"Puheluasetukset"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Vain järjestelmänvalvoja voi muuttaa puheluasetuksia."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Asetukset (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Oletusarvoisen data-SIM-kortin alitunnus:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-kaistanleveys (kt/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-kaistanleveys (kt/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Matkapuhelimen sijaintitiedot (poistettu käytöstä):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fyysisen LTE-kanavan kokoonpano:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Matkapuhelintietojen päivitysaikaväli:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Matkapuhelimen kaikki mittaustiedot:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Päivitä"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Ota DNS-tarkistus käyttöön tai poista se käytöstä"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-kohtaiset tiedot/asetukset"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC saatavilla:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR rajoitettu:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR saatavilla:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR:n tila:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR:n taajuus:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Radion taajuustilan valinta"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Ladataan taajuusluetteloa…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Aseta"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Puhelimen tiedot"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operaattorin hallintatiedot"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Ota operaattorin hallinta käyttöön"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Ehdotus: Paranna Bluetooth-yhteyttä"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Puhelun laatua koskeva ilmoitus"</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 9ad819a..c81450a 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Seul l\'utilisateur principal peut modifier les paramètres de la messagerie vocale."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Votre carte SIM a été déverrouillée. Votre téléphone est en cours de déverrouillage..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"NIP de déblocage du réseau SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Carte SIM verrouillée pour le fournisseur de services :"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Déverrouiller"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ignorer"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Demande de déblocage du réseau…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Transfert vers <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Désactivé"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Votre opérateur ne permet pas la désactivation du transfert d\'appel lorsque votre téléphone n\'est pas joignable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Votre fournisseur de services ne prend pas en charge le transfert d\'appels."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Activer la mise en attente d\'appels?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Vous serez notifié des appels entrant pendant les appels."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activer"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Annuler"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Mise en attente d\'appels CDMA sous IMS activée"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Mise en attente d\'appels CDMA sous IMS désactivée"</string>
     <string name="updating_title" msgid="6130548922615719689">"Paramètres d\'appel"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Seul l\'administrateur peut modifier les paramètres d\'appel."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Paramètres (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut :"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kb/s) :"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante de téléversement (kb/s) :"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Données de la position de la cellule (obsolètes) :"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration du canal physique LTE :"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taux d\'actualisation des données de la cellule :"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Données des mesures de toutes les cellules :"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualiser"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Basculer la vérification DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informations/paramètres OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponible :"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restreinte :"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponible :"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"État NR :"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Fréquence NR :"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Définir le mode de bande radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Chargement de la liste de bandes en cours…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Définir"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informations sur le téléphone"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Données d\'approvisionnement du fournisseur de services"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Déclencher l\'approvisionnement du fournisseur de services"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion : améliorer la connectivité Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notification de qualité d\'appel"</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index bdb0694..9b83fa8 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Seul l\'utilisateur principal de la messagerie vocale peut en modifier les paramètres."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Votre carte SIM a été déverrouillée. Votre téléphone est en cours de déverrouillage..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Code PIN de déblocage du réseau SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Carte SIM verrouillée par l\'opérateur"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Déverrouiller"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Rejeter"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Demande de déblocage du réseau…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Transfert vers <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Désactivé"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Votre opérateur ne permet pas la désactivation du transfert d\'appel lorsque votre téléphone n\'est pas joignable."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Votre opérateur ne permet pas le transfert des appels."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Activer la fonctionnalité d\'appel en attente ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Lorsque vous êtes en communication, des notifications vous signalent les appels entrants"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activer"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Annuler"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Fonctionnalité d\'appel CDMA en attente sous IMS activée"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Fonctionnalité d\'appel CDMA en attente sous IMS désactivée"</string>
     <string name="updating_title" msgid="6130548922615719689">"Paramètres d\'appel"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Seul l\'administrateur peut modifier les paramètres d\'appel."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Paramètres (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut pour les données :"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kbit/s) :"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante d\'importation (kbit/s) :"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informations de géolocalisation mobiles (obsolètes) :"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration de la chaîne physique LTE :"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Fréquence d\'actualisation des informations mobiles :"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toutes les informations mobiles liées aux mesures :"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualiser"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activer/Désactiver le contrôle DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Infos/paramètres OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Accès EN-DC disponible :"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Limitation DCNR :"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Accès NR disponible :"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"État NR :"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Fréquence NR :"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Définir le mode de bande radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Chargement de la liste de bandes…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Définir"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informations sur le téléphone"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informations de gestion des comptes opérateur"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Déclencher la gestion des comptes opérateur"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestion : Améliorez la connectivité Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notification concernant la qualité de l\'appel"</string>
 </resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 61321c8..9aae097 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"O usuario principal é o único que pode modificar a configuración do correo de voz."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Desbloqueouse a tarxeta SIM. O teléfono estase desbloqueando..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueo da rede SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloqueada para o operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Rexeitar"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Solicitando desbloqueo da rede..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Desvío ao <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desactivado"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"O teu operador non admite a desactivación do desvío de chamadas cando non se pode acceder ao teléfono."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"O teu operador non admite o desvío de chamadas."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Queres activar a opción de chamada en espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durante as chamadas, recibirás notificacións das chamadas entrantes"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activar"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancelar"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"A función de chamada en espera de CDMA en IMS está activada"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"A función de chamada en espera de CDMA en IMS está desactivada"</string>
     <string name="updating_title" msgid="6130548922615719689">"Configuración de chamada"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Só o usuario administrador pode cambiar a configuración de chamada."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Configuración (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Código de identificación secundario da SIM de datos predeterminada:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de descarga (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carga (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Información da localización para móbiles (obsoleto):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración de canle física de LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de actualización da información para móbiles:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toda a información de medición para móbiles:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizar"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Alternar comprobación de DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Información ou configuración específica de OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC dispoñible:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR con restricións:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR dispoñible:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estado de NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frecuencia de NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Definir modo de banda de radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Cargando lista de bandas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Definir"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Información do teléfono"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Información de aprovisionamento do operador"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aprovisionamento do operador do activador"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suxestión: Mellora a conectividade de Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación sobre a calidade da chamada"</string>
 </resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 31db3af..0b655ad 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -50,6 +50,7 @@
     <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 નેટવર્ક અનલૉક PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ઑપરેટર દ્વારા સિમ કાર્ડ લૉક કરવામાં આવ્યું છે"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"અનલૉક કરો"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"છોડી દો"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"નેટવર્ક અનલૉકની વિનંતી કરી રહ્યાં છે…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"કૉલ પ્રતીક્ષા ચાલુ કરવા માગો છો?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"કૉલ દરમ્યાન, તમને ઇનકમિંગ કૉલ વિશે નોટિફિકેશન આપવામાં આવશે"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ચાલુ કરો"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"રદ કરો"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS હેઠળ CDMA કૉલ પ્રતીક્ષા ચાલુ છે"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS હેઠળ CDMA કૉલ પ્રતીક્ષા બંધ છે"</string>
     <string name="updating_title" msgid="6130548922615719689">"કૉલ સેટિંગ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"કૉલ સેટિંગ્સને ફક્ત એડમિન વપરાશકર્તા દ્વારા જ બદલી શકાય છે."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"સેટિંગ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ડિફૉલ્ટ ડેટા સિમનું SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL બૅન્ડવિડ્થ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL બૅન્ડવિડ્થ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"સેલ સ્થાન માહિતી (ટાળેલ):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ભૌતિક ચૅનલની ગોઠવણી:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"સેલ માહિતી રિફ્રેશ થવાનો રેટ:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"તમામ સેલ માપ માહિતી:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"રિફ્રેશ કરો"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS તપાસ ટૉગલ કરો"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-વિશિષ્ટ માહિતી/સેટિંગ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ઉપલબ્ધ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR પ્રતિબંધિત:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ઉપલબ્ધ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR સ્ટેટસ:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR આવર્તન:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"રેડિયો બૅન્ડ મોડ સેટ કરો"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"બૅન્ડની સૂચિ લોડ કરી રહ્યું છે…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"સેટ કરો"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ફોનની માહિતી"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"કૅરિઅરની જોગવાઈ વિશે માહિતી"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"કૅરિઅરની જોગવાઈ ટ્રિગર કરો"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"સૂચન: બ્લૂટૂથ કનેક્ટિવિટી બહેતર બનાવો"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"કૉલની ક્વૉલિટી માટે નોટિફિકેશન"</string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 59d9a22..df0bbc8 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"वॉइसमेल सेटिंग को केवल प्राथमिक उपयोगकर्ता ही बदल सकता है."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"आपका सिम कार्ड अनब्लॉक कर दिया गया है. आपका फ़ोन अनलॉक किया जा रहा है..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"सिम नेटवर्क अनलॉक पिन"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ऑपरेटर के लिए सिम को लॉक किया गया"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"अनब्लॉक करें"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"खारिज करें"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"नेटवर्क अनलॉक के लिए अनुरोध कर रहा है..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"क्या आप कॉल वेटिंग (कॉल के दौरान आ रहा दूसरा कॉल) की सुविधा चालू करना चाहते हैं?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"कॉल के दौरान, आपको आने वाले कॉल (इनकमिंग) के बारे में सूचना दी जाएगी"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"चालू करें"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"रद्द करें"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"आईएमएस में CDMA कॉल वेटिंग की सुविधा चालू है"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"आईएमएस में CDMA कॉल वेटिंग की सुविधा बंद है"</string>
     <string name="updating_title" msgid="6130548922615719689">"कॉल सेटिंग"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"कॉल सेटिंग केवल व्यवस्थापक उपयोगकर्ता द्वारा ही बदली जा सकती हैं."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"सेटिंग (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"डिफ़ॉल्ट डेटा सिम का सब-आईडी:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"डीएल बैंडविड्थ (केबीपीएस):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"यूएल बैंडविड्थ (केबीपीएस):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेल की जगह की जानकारी (रोकी गयी है):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"एलटीई की फ़िज़िकल चैनल कॉन्फ़िगरेशन:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल की जानकारी रीफ़्रेश होने की दर:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सभी सेल के माप की पूरी जानकारी:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"रीफ़्रेश करें"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"डीएनएस जांच टॉगल करें"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ओईएम-खास जानकारी/सेटिंग"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC उपलब्ध है:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR प्रतिबंधित है:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR उपलब्ध है:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR की स्थिति:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR की फ़्रीक्वेंसी:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"\'रेडियो बैंड\' मोड सेट करें"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"बैंड सूची लोड की जा रही है…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"सेट करें"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"फ़ोन की जानकारी"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी के प्रावधान की जानकारी"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी के प्रावधान चालू करें"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"सुझाव: ब्लूटूथ कनेक्टिविटी बेहतर करें"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"कॉल की क्वालिटी की सूचना"</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index f38d1f6..afd4e62 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Postavke govorne pošte može izmijeniti samo primarni korisnik."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Vaša je SIM kartica odblokirana. Telefon se odblokira…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"Mrežni PIN za otključavanje SIM-a"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM je zaključan za operatera"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Otključaj"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Odbaci"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Traženje mrežnog otključavanja..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Preusmjeravanje na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Isključeno"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Vaš mobilni operater ne podržava onemogućavanje preusmjeravanja poziva ako je vaš telefon nedostupan."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Vaš operater ne podržava preusmjeravanje poziva."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Uključiti poziv na čekanju?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Tijekom poziva primat ćete obavijesti o dolaznim pozivima"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Uključi"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Odustani"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA poziv na čekanju u okviru IMS-a uključen"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA poziv na čekanju u okviru IMS-a isključen"</string>
     <string name="updating_title" msgid="6130548922615719689">"Postavke poziva"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Postavke poziva može mijenjati samo korisnik koji je administrator."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Postavke (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SUBID zadanog SIM-a za podatkovni promet:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji ćelije (obustavljeno):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Stopa osvježavanja informacija u ćeliji:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije ćelija o mjerenju:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Osvježi"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Uključi/isključi provjeru DNS-a"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informacije/postavke koje se posebno odnose na OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Dostupno za EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Ograničeno za DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Dostupno za NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stanje NR-a:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekvencija NR-a:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Postavi način radijske frekvencije"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Učitavanje popisa frekvencija…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Postavi"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informacije o uslugama mobilnog operatera"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Pokretanje usluga mobilnog operatera"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Prijedlog: poboljšajte povezivost Bluetootha"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Obavijest o kvaliteti poziva"</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index f69e5b1..e053c54 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"A hangposta-beállításokat csak az elsődleges felhasználó módosíthatja."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM kártyája letiltása megszűnt. Feloldás folyamatban..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM hálózati függetlenítő PIN kódja"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"A SIM zárolva a szolgálató esetében"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Feloldás"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Elvetés"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Függetlenítés kérése..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Átirányítás ide: <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Ki"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Szolgáltatója nem támogatja a hívásátirányítás letiltását, ha a telefon nem érhető el."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"A szolgáltatója nem teszi lehetővé a hívásátirányítást."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Bekapcsolja a hívásvárakoztatást?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Hívás közben értesítést kap a bejövő hívásokról"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Igen"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Mégse"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS alatti CDMA-hívásvárakoztatás bekapcsolva"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS alatti CDMA-hívásvárakoztatás kikapcsolva"</string>
     <string name="updating_title" msgid="6130548922615719689">"Hívásbeállítások"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"A hívásbeállításokat csak a rendszergazda módosíthatja."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Beállítások (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Alapértelmezett adatok SIM-alazonosítója:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Letöltési sávszélesség (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Feltöltési sávszélesség (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobilos helyadatok (megszűnt):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizikai csatorna konfigurációja:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cellainformáció frissítési gyakorisága:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Minden cellamérési információ:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Frissítés"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS-ellenőrzés váltása"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specifikus adatok és beállítások:"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC rendelkezésre áll:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR korlátozva:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR rendelkezésre áll:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-állapot:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-frekvencia:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Rádióhullámsáv mód beállítása"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Sávlista betöltése…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Beállítás"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon adatai"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Információ a szolgáltatói ellátásról"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Szolgáltatói ellátás aktiválása"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Javaslat: Gondoskodjon jobb Bluetooth-kapcsolatról"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Értesítés a hívás minőségéről"</string>
 </resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 5aa70b3..6033af7 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -50,6 +50,7 @@
     <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 ցանցով PIN-ի ապակողպում"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Աշխատում է միայն այս օպերատորի SIM քարտով"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ապակողպել"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Անտեսել"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Հայցվում է ցանցի ապակողպում..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Միացնե՞լ զանգի սպասումը"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Հեռախոսազրույցի ժամանակ դուք կծանուցվեք մուտքային զանգերի մասին"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Միացնել"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Չեղարկել"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA զանգի սպասումը IMS-ում միացված է"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA զանգի սպասումը IMS-ում անջատված է"</string>
     <string name="updating_title" msgid="6130548922615719689">"Զանգի կարգավորումներ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Զանգի կարգավորումները կարող է փոխել միայն ադմինիստրատոր հանդիսացող օգտատերը:"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Կարգավորումներ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SIM քարտի հավելյալ ID կանխադրված բջջային ինտերնետի համար՝"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL թողունակությունը (կբ/վ)՝"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL թողունակությունը (կբ/վ)՝"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Բջիջի տեղադրության տվյալներ (հնացած)՝"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ֆիզիկական ալիքի կարգավորում՝"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Բջիջի տվյալների թարմացման հաճախականությունը՝"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Բոլոր բջիջների չափման տվյալները՝"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Թարմացնել"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Փոխարկել DNS ստուգումը"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-հատուկ տեղեկություններ/կարգավորումներ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC-ն հասանելի է՝"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR-ը սահմանափակված է՝"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR-ը հասանելի է՝"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-ի կարգավիճակը՝"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-ի հաճախականությունը՝"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Կարգավորել հաճախությունների շերտի ռեժիմը"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Շերտերի ցուցակը բեռնվում է…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Կարգավորել"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Հեռախոսի տեղեկություններ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Օպերատորի նախապատրաստման տվյալներ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Գործարկել օպերատորի նախապատրաստումը"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Հուշում. բարելավեք Bluetooth կապը"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Զանգի որակի մասին ծանուցում"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 8bf3f7a..a23444c 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Setelan Pesan Suara hanya dapat diubah oleh Pengguna Utama."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Kartu SIM Anda tidak lagi dicekal. Ponsel Anda sedang dibuka kuncinya..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN pembuka kunci jaringan SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM dikunci untuk operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Buka kunci"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Tutup"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Meminta membuka jaringan..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Meneruskan ke <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Nonaktif"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operator Anda tidak mendukung penonaktifan penerusan panggilan ketika ponsel tidak dapat dijangkau."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operator Anda tidak mendukung penerusan panggilan."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Aktifkan nada tunggu?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Selama melakukan panggilan, Anda akan menerima notifikasi jika ada panggilan masuk"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktifkan"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Batal"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Nada tunggu CDMA dalam IMS aktif"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Nada tunggu CDMA dalam IMS nonaktif"</string>
     <string name="updating_title" msgid="6130548922615719689">"Setelan panggilan"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Setelan panggilan telepon hanya dapat diubah oleh pengguna admin."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Setelan (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data default:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandwidth DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandwidth UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Info Lokasi Sel (tidak digunakan lagi):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fisik LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rasio Pembaruan Info Sel"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Info Pengukuran Sel:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Perbarui"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Aktifkan Pemeriksaan DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Info spesifik OEM/Setelan"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC Tersedia:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Dibatasi DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR Tersedia:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Status NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekuensi NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Setel Mode Band Radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Memuat Daftar Band…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Setel"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Info telepon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Info Provisioning Operator"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Memicu Provisioning Operator"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Saran: Tingkatkan konektivitas Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notifikasi Kualitas Panggilan"</string>
 </resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index cc6bc3b..1873079 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Aðeins aðalnotandinn má breyta talhólfsstillingum."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Opnað var fyrir SIM-kortið. Verið er að opna símann…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN-númer SIM-korts til að opna síma"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-kort læst fyrir símafyrirtæki"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Taka úr lás"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Hunsa"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Biður um að símkerfi sé opnað…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Áframsendir í <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Slökkt"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Símafyrirtækið leyfir ekki að slökkt sé á símtalsflutningi þegar ekki næst í símann."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Símafyrirtækið þitt styður ekki símtalsflutning."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Viltu kveikja á símtölum í bið?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Þú færð tilkynningu um móttekið símtal ef þú ert að tala í símann"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Kveikja"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Hætta"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Kveikt er á CDMA-símtölum í bið undir spjalli"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Slökkt er á CDMA-símtölum í bið undir spjalli"</string>
     <string name="updating_title" msgid="6130548922615719689">"Símtalsstillingar"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Aðeins stjórnandinn má breyta símtalsstillingum."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Stillingar (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Undirauðkenni sjálfgefins SIM-korts fyrir gögn:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Niðurhalsbandvídd (kb/sek.):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Upphleðslubandvídd (kb/sek.):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Staðsetningarupplýsingar loftneta (úrelt):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE-rásarstilling:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Endurnýjunartíðni loftnetaupplýsinga:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Allar mælingarupplýsingar loftneta:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Endurnýja"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Kveikja/slökkva á DNS-prófun"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Upplýsingar/stillingar framleiðanda"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC tiltækt:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR takmarkað:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR tiltækt:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR staða:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR tíðni:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Velja útvarpstíðni"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Hleður lista yfir tíðnisvið…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Stilla"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Upplýsingar um síma"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Úthlutunarupplýsingar símafyrirtækis"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Kveikja á úthlutun símafyrirtækis"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Tillaga: Bæta tengigetu Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Tilkynning um símtalsgæði"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index c2dbb78..c45ec81 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Le impostazioni della segreteria possono essere modificate solo dall\'utente principale."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"La SIM è stata sbloccata. Sblocco del telefono..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN sblocco rete SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloccata per l\'operatore"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Sblocca"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Chiudi"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Richiesta sblocco rete..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Deviazione al numero <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"OFF"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Il tuo operatore non supporta la disattivazione dell\'inoltro chiamate quando il telefono non è raggiungibile."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Il tuo operatore non supporta la deviazione chiamate."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Attiva avviso di chiamata"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durante una telefonata, riceverai una notifica per le chiamate in entrata"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Attiva"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Annulla"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Avviso di chiamata CDMA con IMS attivato"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Avviso di chiamata CDMA con IMS disattivato"</string>
     <string name="updating_title" msgid="6130548922615719689">"Impostazioni chiamate"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Le impostazioni delle chiamate possono essere modificate solo dall\'utente amministratore."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Impostazioni (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ID secondario della SIM dati predefinita:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Larghezza di banda DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Larghezza di banda UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informazioni sulla posizione delle celle (obsoleto):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurazione canale fisico LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frequenza di aggiornamento delle informazioni sulle celle:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Informazioni sulla misurazione di tutte le celle:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Aggiorna"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Attiva o disattiva verifica DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Info/impostazioni specifiche OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponibile:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR con limitazioni:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponibile:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stato NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frequenza NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Imposta modalità banda radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Caricamento elenco bande…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Imposta"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Info telefono"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informazioni sul provisioning operatore"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Attiva provisioning operatore"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggerimento: migliora la connettività Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notifica sulla qualità della chiamata"</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 4a2b40e..9c4c0d9 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -50,6 +50,7 @@
     <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">"‏PIN לביטול נעילה של רשת SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"‏כרטיס ה-SIM נעול על ידי הספק הסלולרי"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"בטל נעילה"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"סגור"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"מבקש ביטול נעילת רשת..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"רוצה להפעיל את השיחה הממתינה?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"יוצגו לך התראות על שיחות שנכנסות במהלך שיחות אחרות"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"הפעלה"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ביטול"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"‏השיחה הממתינה ברשת CDMA ב-IMS פועלת"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"‏השיחה הממתינה ברשת CDMA ב-IMS מושבתת"</string>
     <string name="updating_title" msgid="6130548922615719689">"הגדרות שיחה"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"רק מנהל המערכת יכול לשנות הגדרות שיחה."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"הגדרות (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"‏תת-מזהה של כרטיס ה-SIM עם חבילת גלישה המוגדר כברירת מחדל:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"‏רוחב פס DL (ב-kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"‏רוחב פס UL (ב-kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"מידע על מיקום סלולרי (הוצא משימוש):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"‏תצורת ערוץ פיזי של LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"קצב רענון של מידע סלולרי:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"כל המידע של מדידה סלולרית:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"רענון"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"‏החלפת מצב של בדיקת DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"‏מידע/הגדרות ספציפיים ל-OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"‏תומך ב-EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"‏לא תומך ב-5G NR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"‏תומך ב-5G NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"‏מצב 5G NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"‏תדירות 5G NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"הגדרת מצב תדרים של רדיו"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"טוען רשימת תדרים…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"הגדרה"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"פרטי טלפון"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"פרטי ניהול תצורה של ספק סלולרי"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"הפעלת ניהול תצורה של ספק סלולרי"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"‏הצעה: שיפור הקישוריות ל-Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"התראה על איכות השיחה"</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index e6e04d7..b3f6683 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -50,6 +50,7 @@
     <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 のネットワーク ロック解除 PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"携帯通信会社の SIM ロックがかかっています"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ロック解除"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"無効"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ネットワークのロック解除をリクエスト中..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g>に転送する"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"OFF"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"ご利用の携帯通信会社は着信不能時の転送の無効化をサポートしていません。"</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"ご利用の携帯通信会社では電話の転送機能がサポートされていません。"</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"通話中着信を ON にしますか?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"通話中でも他の通話の着信通知が届きます"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ON にする"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"キャンセル"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS での CDMA 通話中着信が ON になっています"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS での CDMA 通話中着信が OFF になっています"</string>
     <string name="updating_title" msgid="6130548922615719689">"通話設定"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"通話設定は管理者ユーザーのみが変更できます。"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"設定(<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"デフォルトのデータ SIM の SUBID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 帯域幅(kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 帯域幅(kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"セルの位置情報(サポート終了):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE の物理チャネル設定:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"セル情報の更新間隔:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"すべてのセルの測定情報:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"更新"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS チェックを切り替え"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM 固有の情報 / 設定"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC 利用可能:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR 制限あり:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR 利用可能:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR ステータス:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR 周波数:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"無線バンドモードの設定"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"バンドリストを読み込み中…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"設定"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"スマートフォン情報"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"携帯通信会社のプロビジョニング情報"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"携帯通信会社のプロビジョニングをトリガー"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Bluetooth の接続性を改善することをおすすめします"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質に関するお知らせ"</string>
 </resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index e85ff0b..b784dfe 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -50,6 +50,7 @@
     <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 ქსელის განბლოკვის PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM ჩაკეტილია ოპერატორისთვის"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"განბლოკვა"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"იგნორირება"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ქსელის განბლოკვის მოთხოვნა…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"გსურთ ზარის ლოდინის ჩართვა?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ზარის დროს გეცნობებათ შემომავალი ზარების შესახებ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ჩართვა"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"გაუქმება"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA ზარის ლოდინი IMS-ში ჩართულია"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA ზარის ლოდინი IMS-ში გამორთულია"</string>
     <string name="updating_title" msgid="6130548922615719689">"ზარის პარამეტრები"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ზარის პარამეტრების შეცვლა მხოლოდ მომხმარებელ-ადმინისტრატორს შეუძლია."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"პარამეტრები (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"მონაცემების ნაგულისხმევი SIM-ის subId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ფიჭური მდებარეობის ინფორმაცია (მოძველდა):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ფიზიკური არხის კონფიგურაცია:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ფიჭური ინფორმაციის განახლების სიხშირე:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"სრული ინფორმაცია ფიჭური ქსელის შესახებ:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"განახლება"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS შემოწმების გადართვა"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ინფორმაცია/პარამეტრები სპეციალურად OEM-ისთვის"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ხელმისაწვდომია:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR შეზღუდულია:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ხელმისაწვდომია:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-ის მდგომარეობა:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-ის სიხშირე:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"რადიოდიაპაზონის რეჟიმის დაყენება"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"მიმდინარეობს დიაპაზონთა სიის ჩატვირთვა…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"დაყენება"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ტელეფონის ინფორმაცია"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ოპერატორის უზრუნველყოფის ინფორმაცია"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ოპერატორის უზრუნველყოფის გააქტიურება"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"შეთავაზება: გააუმჯობესეთ Bluetooth კავშირი"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"შეტყობინება ზარის ხარისხის შესახებ"</string>
 </resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 16a7326..77219a3 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -50,6 +50,7 @@
     <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 желісін ашатын PIN код"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM картасы келесі операторға құлыпталған"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Бекітпесін ашу"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Бас тарту"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Желінің бекітпесін ашуды өтінуде…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Қоңырауды ұстап тұру мүмкіндігін қосу керек пе?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Сөйлесіп жатқанда сізге кіріс қоңыраулар туралы хабарландыру көрсетіледі."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Қосу"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Бас тарту"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS бойынша басқа CDMA желісіндегі қоңырауды ұстап тұру мүмкіндігі қосулы."</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS бойынша басқа CDMA желісіндегі қоңырауды ұстап тұру мүмкіндігі өшірулі."</string>
     <string name="updating_title" msgid="6130548922615719689">"Қоңырау параметрлері"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Қоңырау параметрлерін тек әкімші пайдаланушы өзгерте алады."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Параметрлер (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Әдепкі деректер SIM картасының қосалқы идентификаторы:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткізу мүмкіндігі (кбит/сек):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткізу мүмкіндігі (кбит/сек):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Ұялы желінің орналасқан жері туралы ақпарат (қолданыстан шығарылды):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалық арна конфигурациясы:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ұялы желі туралы ақпаратты жаңарту жиілігі:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Барлық ұялы желі өлшемдері туралы ақпарат:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Жаңарту"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS тексерісін қосу/өшіру"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Өндірушіге қатысты ақпарат/параметрлер"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC қолжетімді:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR шектеулі:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR қолжетімді:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR күйі:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR жиілігі:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Радиожолақ режимін орнату"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Жолақтар тізімі жүктелуде…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Орнату"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Телефон ақпараты"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Операторды инициализациялау туралы ақпарат"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Операторды инциализациялауды іске қосу"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Ұсыныс: Bluetooth байланысының сапасын жақсартыңыз"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Қоңырау сапасы туралы хабарландыру"</string>
 </resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 0ab4463..3bb7e10 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"មាន​តែ​អ្នក​ប្រើប្រាស់​ចម្បង​ទើប​អាច​កែប្រែ​ការ​កំណត់​សារ​ជា​សំឡេង​បាន។"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"បាន​ដោះ​សោ​ស៊ីមកាត​របស់​អ្នក។ ទូរស័ព្ទ​របស់​អ្នក​កំពុង​ដោះ​សោ…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"ដោះ​សោ​​កូដ PIN បណ្ដាញ​ស៊ីមកាត"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ស៊ីម​ត្រូវ​បាន​ចាក់​សោ​សម្រាប់​ប្រតិបត្តិករ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ដោះ​សោ"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"បោះបង់"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"កំពុង​ស្នើ​​ដោះ​សោ​បណ្ដាញ…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"បើក​ការរង់ចាំ​ការហៅ​ទូរសព្ទ​ឬ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ក្នុង​ពេល​ហៅ​ទូរសព្ទ អ្នក​នឹង​ទទួល​បាន​ការជូន​ដំណឹង​អំពី​ការហៅ​ចូល"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"បើក"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"បោះបង់"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"ការរង់ចាំ​ការហៅ ទូរសព្ទ CDMA ក្រោម IMS ត្រូវ​បាន​បើក"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"ការរង់ចាំ​ការហៅ ទូរសព្ទ CDMA ក្រោម IMS ត្រូវ​បាន​បិទ"</string>
     <string name="updating_title" msgid="6130548922615719689">"កំណត់​ការ​ហៅ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ការកំណត់ការហៅអាចផ្លាស់ប្តូរបានដោយអ្នកប្រើដែលមានសិទ្ធិគ្រប់គ្រងតែប៉ុណ្ណោះ។"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ការកំណត់ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"លេខសម្គាល់រង​របស់​ស៊ីម​ទិន្នន័យ​លំនាំដើម៖"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"កម្រិត​បញ្ជូន DL (kbps) ៖"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"កម្រិត​បញ្ជូន UL (kbps) ៖"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ព័ត៌មាន​ទីតាំង​ទូរសព្ទ​ចល័ត (បានបញ្ឈប់)៖"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ការកំណត់​រចនាសម្ព័ន្ធបណ្ដាញរូបវ័ន្ត LTE ៖"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"អត្រា​ផ្ទុក​ឡើង​វិញ​នៃ​ព័ត៌មាន​ទូរសព្ទ​ចល័ត៖"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ព័ត៌មាន​វាស់​ទូរសព្ទ​ចល័ត​ទាំងអស់៖"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ផ្ទុកឡើងវិញ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"បិទ/បើកការពិនិត្យ DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ការ​កំណត់/ព័ត៌មាន​ជាក់លាក់ OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"មាន EN-DC៖"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ត្រូវ​បាន​រឹតត្បិត៖"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"មាន NR៖"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"ស្ថានភាព NR៖"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"កម្រិត​ញឹកញាប់​នៃ NR៖"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"កំណត់​មុខងារ​កម្រិត​បញ្ជូន​វិទ្យុ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"កំពុងដំណើរការបញ្ជីក្រុម…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"កំណត់"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ព័ត៌មាន​ទូរសព្ទ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ព័ត៌មាន​អំពី​ការផ្តល់​ទិន្នន័យ​របស់​ក្រុមហ៊ុន​សេវា​ទូរសព្ទ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"នាំ​ឱ្យ​មាន​ការផ្តល់​ទិន្នន័យ​ពី​ក្រុមហ៊ុន​សេវា​ទូរសព្ទ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"ការណែនាំ៖ កែលម្អ​ការតភ្ជាប់ប៊្លូធូស"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ការជូនដំណឹង​អំពីគុណភាព​ហៅទូរសព្ទ"</string>
 </resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index f03fd0d..40f397e 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ಧ್ವನಿಮೇಲ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಕೇವಲ ಪ್ರಾಥಮಿಕ ಬಳಕೆದಾರರು ಮಾತ್ರ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"ನಿಮ್ಮ ಸಿಮ್‌ ಕಾರ್ಡ್‌ನ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಲಾಗಿದೆ. ನಿಮ್ಮ ಫೋನ್‌ ಅನ್‌ಲಾಕ್‌ ಆಗುತ್ತಿದೆ…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"ಸಿಮ್‌ ನೆಟ್‌ವರ್ಕ್‌ನ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ಆಪರೇಟರ್‌ಗಾಗಿ SIM ಅನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ಅನ್‌ಲಾಕ್"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ವಜಾಗೊಳಿಸಿ"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ನೆಟ್‌ವರ್ಕ್‌ ಅನ್ನು ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"ಕರೆ ನಿರೀಕ್ಷೆಯನ್ನು ಆನ್ ಮಾಡಬೇಕೆ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ಕರೆಯ ಸಮಯದಲ್ಲಿ, ಒಳಬರುವ ಕರೆಗಳ ಕುರಿತು ನಿಮಗೆ ಸೂಚಿಸಲಾಗುತ್ತದೆ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ಆನ್ ಮಾಡಿ"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS ಆನ್ ಅಡಿಯಲ್ಲಿ CDMA ಕರೆ ನಿರೀಕ್ಷೆ"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS ಆಫ್ ಅಡಿಯಲ್ಲಿ CDMA ಕರೆ ನಿರೀಕ್ಷೆ"</string>
     <string name="updating_title" msgid="6130548922615719689">"ಕರೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ಕರೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಕೇವಲ ನಿರ್ವಾಹಕ ಬಳಕೆದಾರರು ಮಾತ್ರ ಬದಲಾಯಿಸಬಹುದು."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ಡೀಫಾಲ್ಟ್ ಡೇಟಾ ಸಿಮ್‌ನ ವಿಷಯಐಡಿ:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ಬ್ಯಾಂಡ್‌ವಿಡ್ತ್ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ಬ್ಯಾಂಡ್‌ವಿಡ್ತ್ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ಸೆಲ್ ಸ್ಥಳ ಮಾಹಿತಿ (ತಡೆಹಿಡಿಯಲಾಗಿದೆ):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ಭೌತಿಕ ಚಾನೆಲ್ ಕಾನ್ಫಿಗರೇಶನ್:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ಸೆಲ್ ಮಾಹಿತಿ ರಿಫ್ರೆಶ್ ದರ:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ಎಲ್ಲಾ ಸೆಲ್ ಮಾಪನ ಮಾಹಿತಿ:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ರಿಫ್ರೆಶ್ ಮಾಡಿ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS ಪರಿಶೀಲನೆ ಟಾಗಲ್ ಮಾಡಿ"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-ನಿರ್ದಿಷ್ಟ ಮಾಹಿತಿ/ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ಲಭ್ಯವಿದೆ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"ನಿರ್ಬಂಧಿತ DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ಲಭ್ಯವಿದೆ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR ಸ್ಥಿತಿ:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ಫ್ರೀಕ್ವೆನ್ಸಿ:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ರೇಡಿಯೋ ಬ್ಯಾಂಡ್ ಮೋಡ್ ಹೊಂದಿಸಿ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ಬ್ಯಾಂಡ್ ಪಟ್ಟಿಯನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ಹೊಂದಿಸಿ"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ಫೋನ್ ಮಾಹಿತಿ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ವಾಹಕ ಪೂರೈಕೆಯ ಮಾಹಿತಿ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ಟ್ರಿಗರ್‌ ವಾಹಕ ಪೂರೈಕೆ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"ಸಲಹೆ: ಬ್ಲೂಟೂತ್ ಕನೆಕ್ಷನ್ ಅನ್ನು ಸುಧಾರಿಸಿ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ಕರೆ ಗುಣಮಟ್ಟದ ಅಧಿಸೂಚನೆ"</string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index ba69d3b..e1d9495 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -50,6 +50,7 @@
     <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 네트워크 잠금해제 PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"이동통신사 전용으로 SIM 잠김"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"잠금해제"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"취소"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"네트워크 잠금해제 요청 중..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"통화중 대기를 사용 설정하시겠습니까?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"통화 중 다른 전화가 걸려 오면 알림을 받습니다."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"사용 설정"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"취소"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS에서 CDMA 통화중 대기 사용"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS에서 CDMA 통화중 대기 사용 안함"</string>
     <string name="updating_title" msgid="6130548922615719689">"통화 설정"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"관리자만 통화 설정을 변경할 수 있습니다."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"설정(<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"기본 데이터 SIM의 subId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 대역폭(kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 대역폭(kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"셀 위치 정보(사용 중단됨):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 물리적 채널 구성:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"셀 정보 새로고침 빈도:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"모든 셀 측정 정보:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"새로고침"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS 확인 전환"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM별 정보/설정"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC 사용 가능:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR 제한됨:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR 사용 가능:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR 상태:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR 빈도:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"무선 주파수 대역 모드 설정"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"대역 목록 로드 중…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"설정"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"휴대전화 정보"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"이동통신사 프로비저닝 정보"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"이동통신사 프로비저닝 실행"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"제안: 블루투스 연결 개선"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"통화 품질 알림"</string>
 </resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index a30a3d6..be4439f 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -50,6 +50,7 @@
     <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-карта тармагынын кулпусун ачуучу PIN код"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-карта оператор үчүн кулпуланган"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Кулпусун ачуу"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Этибарга албоо"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Тармак кулпусун ачуу суралууда…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Чалууну күтүү күйгүзүлсүнбү?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Чалуу учурунда кирүүчү чалуулар тууралуу кабар аласыз"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Күйгүзүү"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Баш тартуу"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS платформасында CDMA чалуу күтүүcү күйгүзүлгөн"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS платформасында CDMA чалуу күтүүcү өчүрүлгөн"</string>
     <string name="updating_title" msgid="6130548922615719689">"Чалуу жөндөөлөрү"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Чалуу жөндөөлөрүн администратор гана өзгөртө алат."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Жөндөөлөр (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Демейки оператордун SIM картасынын көз салуу идентификатору:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Уюлдук тармакта жайгашкан жери тууралуу маалымат (жоюлган):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалык каналынын конфигурациясы:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Уюлдук маалыматты жаңылоо ылдамдыгы:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Уюлдук чен-өлчөм маалыматтары:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Жаңылоо"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS текшерүүнү которуштуруу"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM\'ге тиешелүү Маалымат/Жөндөөлөр"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC жеткиликтүү:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR чектелген:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR жеткиликтүү:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR абалы:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR жыштыгы:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Радио жыштыгынын режимин коюу"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Жыштык режиминин тизмеси жүктөлүүдө…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Жөндөө"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Телефондун маалыматы"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Байланыш оператору жөнүндө маалымат"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Байланыш операторун өзгөртүү"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Сунуш: Bluetooth байлынышын жакшыртыңыз"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Чалуунун сапаты тууралуу билдирме"</string>
 </resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 0534a5f..7c50430 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ການຕັ້ງຄ່າຂໍ້ຄວາມສຽງສາມາດແກ້ໄຂໄດ້ໂດຍຜູ້ໃຊ້ຫຼັກເທົ່ານັ້ນ."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"ຍົກເລີກການປິດກັ້ນ SIM card ຂອງທ່ານແລ້ວ. ໂທລະສັບຂອງທ່ານກຳລັງຖືກປົດລັອກ..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN ປົດລັອກເຄືອຂ່າຍ SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ລັອກ SIM ສຳລັບຜູ້ໃຫ້ບໍລິການແລ້ວ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ປົດລັອກ"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ປິດໄວ້"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ກຳລັງຮ້ອງຂໍການປົດລັອກເຄືອຂ່າຍ..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"ເປີດການລໍຖ້າສາຍບໍ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ໃນລະຫວ່າງການໂທ, ທ່ານຈະໄດ້ຮັບແຈ້ງກ່ຽວກັບສາຍໂທເຂົ້າ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ເປີດ"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ຍົກເລີກ"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"ການລໍຖ້າສາຍ CDMA ພາຍໃຕ້ IMS ເປີດຢູ່"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"ການລໍຖ້າສາຍ CDMA ພາຍໃຕ້ IMS ປິດຢູ່"</string>
     <string name="updating_title" msgid="6130548922615719689">"ການຕັ້ງຄ່າການໂທ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ມີ​ແຕ່​ຜູ້​ໃຊ້​ທີ່​ເປັນ​ຜູ້ດູແລລະບົບ​ເທົ່າ​ນັ້ນ​ທີ່​ສາ​ມາດ​ປ່ຽນການ​ຕັ້ງ​ຄ່າ​ການ​ໂທ​ໄດ້."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ການ​ຕັ້ງ​ຄ່າ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId ຂອງຊິມອິນເຕີເນັດເລີ່ມຕົ້ນ:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"ແບນວິດ DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"ແບນວິດ UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ຂໍ້ມູນສະຖານທີ່ມືຖື (ສິ້ນສຸດການສະໜັບສະໜຸນແລ້ວ):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ການຕັ້ງຄ່າຊ່ອງ LTE ກາຍະພາບ:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ອັດຕາການໂຫຼດຄືນໃໝ່ຂອງຂໍ້ມູນມືຖື:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ຂໍ້ມູນການວັດແທກມືຖືທັງໝົດ:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ໂຫຼດຂໍ້ມູນໃໝ່"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"ເປີດ/ປິດ ການກວດ DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ຂໍ້ມູນ/ການຕັ້ງຄ່າສະເພາະ OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"ມີ EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"ຈຳກັດ DCNR ໄວ້ແລ້ວ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"ມີ NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"ສະຖານະ NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"ຄວາມຖີ່ NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ຕັ້ງໂໝດແຖບຄວາມຖີ່ວິທະຍຸ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ກຳລັງດາວໂຫລດລາຍຊື່ແຖບຄວາມຖີ່..."</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ກຳນົດ"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ຂໍ້​ມູນ​ໂທລະ​ສັບ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ຂໍ້ມູນການເປີດນຳໃຊ້ເຄືອຂ່າຍ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ກະຕຸ້ນການຈັດຫາຜູ້ໃຫ້ບໍລິການ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"ການແນະນຳ: ປັບປຸງການເຊື່ອມຕໍ່ Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ການແຈ້ງເຕືອນຄຸນນະພາບການໂທ"</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index bc170a8..961d380 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Balso pašto nustatymus gali keisti tik pagrindinis naudotojas."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Jūsų SIM kortelė buvo atblokuota. Atrakinamas telefonas..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM tinklo atrakinimo PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM kortelę užrakino operatorius"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Atblokuoti"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Atsisakyti"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Pateikiama užklausa atrakinti tinklą..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Peradresuojama į <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Išjungta"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatorius nepalaiko skambučių peradresavimo išjungimo, kai telefonas nepasiekiamas."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatorius nepalaiko skambučių peradresavimo."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Įjungti laukiamų skambučių paslaugą?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Per skambutį jums bus pranešta apie laukiamus skambučius"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Įjungti"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Atšaukti"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA laukiamų skambučių paslauga įjungus IMS įjungta"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA laukiamų skambučių paslauga įjungus IMS išjungta"</string>
     <string name="updating_title" msgid="6130548922615719689">"Skambinimo nustatymai"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Skambučių nustatymus gali keisti tik administruojantis naudotojas."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Nustatymai (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -875,7 +883,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Numatytųjų duomenų SIM kortelės papildomas ID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL pralaidumas (Kb/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL pralaidumas (Kb/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobiliojo ryšio vietovės informacija (nebenaudojama):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizinio kanalo konfigūracija:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobiliojo ryšio informacijos atnaujinimo dažnis:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visų mobiliųjų ryšių įvertinimo informacija:"</string>
@@ -906,6 +913,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Atnaujinti"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Kaitalioti DNS tikrinimą"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM būdinga informacija / nustatymai"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC (pasiekiama):"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR (apribota):"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR (pasiekiama):"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR būsena:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR dažnis:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Nustatyti radijo dažnių režimą"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Įkeliamas dažnių sąrašas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Nustatyti"</string>
@@ -915,4 +927,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefono informacija"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operatoriaus aprūpinimo informacija"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktyviklio operatoriaus aprūpinimas"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Pasiūlymas: pagerinkite „Bluetooth“ ryšį"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Pranešimas apie skambučio kokybę"</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 0204958..a547255 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Tikai galvenais lietotājs var mainīt balss pasta iestatījumus."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM karte ir atbloķēta. Notiek tālruņa atbloķēšana..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM tīkla atbloķēšanas PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM karte ir bloķēta operatoram"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Atbloķēt"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Noraidīt"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Notiek tīkla atbloķēšanas pieprasīšana..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Pāradresēšana uz: <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Izslēgts"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Jūsu mobilo sakaru operators neatbalsta zvanu pāradresācijas atspējošanu, ja tālrunis nav sasniedzams."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Jūsu mobilo sakaru operators neatbalsta zvanu pāradresāciju."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Vai ieslēgt zvanu gaidīšanu?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Zvana laikā saņemsiet paziņojumu par ienākošajiem zvaniem"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Ieslēgt"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Atcelt"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA zvanu gaidīšana, kad ir ieslēgts tūlītējās ziņojumapmaiņas pakalpojums"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA zvanu gaidīšana, kad ir izslēgts tūlītējās ziņojumapmaiņas pakalpojums"</string>
     <string name="updating_title" msgid="6130548922615719689">"Zvanu iestatījumi"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Tikai lietotājs ar administratora tiesībām var mainīt zvanu iestatījumus."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Iestatījumi (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Noklusējuma datu SIM kartes papildu ID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL joslas platums (kb/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL joslas platums (kb/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobilā tālruņa atrašanās vietas informācija (novecojusi):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fiziskā kanāla konfigurācija:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobilā tīkla informācijas atsvaidzināšanas biežums:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visa mobilā tīkla mērījumu informācija:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Atsvaidzināt"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Pārslēgt DNS pārbaudi"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM raksturīga informācija/iestatījumi"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC pieejamība:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ierobežojums:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR pieejamība:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR statuss:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR biežums:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Radio frekvenču joslu režīma iestatīšana"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Notiek joslu saraksta ielāde…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Iestatīt"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Tālruņa informācija"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informācija par mobilo sakaru operatora nodrošināšanu"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivizēt operatora nodrošināšanu"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Ieteikums: uzlabojiet Bluetooth savienojamību"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Paziņojums par zvana kvalitāti"</string>
 </resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 045307c..94cc190 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -50,6 +50,7 @@
     <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">"PIN за отклучување мрежа на SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-картичката е заклучена за операторот"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Отклучи"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Отфрли"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Барање за отклучување мрежа..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Да се вклучи повик на чекање?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Во текот на повик ќе добиете известување за дојдовни повици"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Вклучи"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Откажи"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Повикот на чекање CDMA под IMS е вклучен"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Повикот на чекање CDMA под IMS е исклучен"</string>
     <string name="updating_title" msgid="6130548922615719689">"Поставки за повици"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Поставките за повик може да ги измени само администраторскиот корисник."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Поставки (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SUBID на стандардната SIM за мобилен интернет:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Брзина на пренос при преземање (кбит/с):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Брзина на пренос при прикачување (кбит/с):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информации за локација на мобилен (неподдржано):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација на физички канал на LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Стапка на освежување на информациите за мобилниот:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Сите информации за мерењата на мобилниот:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Освежи"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Префрли на DNS-проверка"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Информации/Поставки карактеристични за ОЕМ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Достапно за EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Ограничено на DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Достапно за NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Состојба на NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Фреквенција на NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Поставете режим на појас на радио"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Се вчитува список на појаси…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Постави"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Информации за телефонот"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Информации за обезбедување оператор"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Активирајте обезбедување оператор"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Предлог: подобрете го поврзувањето на Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Известување за квалитет на повик"</string>
 </resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 1c53a43..2cf119f 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"പ്രാഥമിക ഉപയോക്താവിന് മാത്രമേ വോയ്‌സ്‌മെയിൽ ക്രമീകരണം പരിഷ്‌ക്കരിക്കാനാവൂ."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"സിം കാർഡ് തടഞ്ഞത് മാറ്റി. നിങ്ങളുടെ ഫോൺ അൺലോക്കുചെയ്യുന്നു…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"സിം നെറ്റ്‌വർക്ക് അൺലോക്ക് പിൻ"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ഓപ്പറേറ്റർക്കായി SIM ലോക്ക് ചെയ്‌തിരിക്കുന്നു"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"അൺലോക്കുചെയ്യുക"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"നിരസിക്കുക"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"നെറ്റ്‌വർക്ക് അൺലോക്ക് അഭ്യർത്ഥിക്കുന്നു…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"കോൾ വെയ്‌റ്റിംഗ് ഓണാക്കണോ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"കോളിനിടയ്ക്ക് വരുന്ന മറ്റ് ഇൻകമിംഗ് കോളുകളെക്കുറിച്ച് നിങ്ങളെ അറിയിക്കും"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ഓണാക്കുക"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"റദ്ദാക്കുക"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS-ന് കീഴിലുള്ള CDMA കോൾ വെയ്‌റ്റിംഗ് ഓണാണ്"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS-ന് കീഴിലുള്ള CDMA കോൾ വെയ്‌റ്റിംഗ് ഓഫാണ്"</string>
     <string name="updating_title" msgid="6130548922615719689">"കോൾ ക്രമീകരണങ്ങൾ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"അഡ്മിൻ ഉപയോക്താവിന് മാത്രമേ കോൾ ക്രമീകരണം മാറ്റാൻ കഴിയൂ."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ക്രമീകരണം (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ഡിഫോൾട്ട് ഡാറ്റാ സിമ്മിന്റെ ഉപഐഡി:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ബാൻഡ്‌വിത്ത് (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ബാൻഡ്‍വിത്ത് (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"സെൽ ലൊക്കേഷൻ വിവരങ്ങൾ (അവസാനിപ്പിച്ചു):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ഫിസിക്കൽ ചാനൽ കോൺഫിഗറേഷൻ:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"സെൽ വിവരങ്ങൾ പുതുക്കിയെടുക്കൽ നിരക്ക്:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"എല്ലാ സെൽ അളവ് വിവരങ്ങളും:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"പുതുക്കിയെടുക്കുക"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS പരിശോധന മാറ്റുക"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-നിർദ്ദിഷ്‌ട വിവരം/ക്രമീകരണം"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ലഭ്യം:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR നിയന്ത്രിച്ചിരിക്കുന്നു:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ലഭ്യം:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR നില:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ഫ്രീക്വൻസി:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"റേഡിയോ ബാൻഡ് മോഡ് സജ്ജീകരിക്കുക"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ബാൻഡ് ലിസ്‌റ്റ് ലോഡ് ചെയ്യുന്നു…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"സജ്ജീകരിക്കുക"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ഫോൺ വിവരം"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"കാരിയർ പ്രൊവിഷനിംഗ് വിവരം"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"കാരിയർ പ്രൊവിഷനിംഗ് തുടങ്ങുക"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"നിർദ്ദേശം: Bluetooth കണക്‌റ്റിവിറ്റി മെച്ചപ്പെടുത്തുക"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"കോൾ നിലവാര അറിയിപ്പ്"</string>
 </resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 08035fd..d25876c 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -50,6 +50,7 @@
     <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 сүлжээ тайлах PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Операторын SIM түгжигдсэн"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Тайлах"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Алгасах"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Сүлжээг тайлах хүсэлтийг илгээж байна…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"\"Дуудлага хүлээлгэнд\" тохиргоог асаах уу?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Дуудлагын үеэр танд ирсэн дуудлагын талаар мэдэгдэнэ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Асаах"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Болих"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS доорх CDMA-н \"Дуудлага хүлээлгэнд\" тохиргоо асаалттай байна"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS доорх CDMA-н \"Дуудлага хүлээлгэнд\" тохиргоо унтраалттай байна"</string>
     <string name="updating_title" msgid="6130548922615719689">"Дуудлагын тохиргоо"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Дуудлагын тохиргоог зөвхөн админ хэрэглэгч солих боломжтой."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Тохиргоо (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Өгөгдмөл дата SIM-н SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DLзурвасын өргөн (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Мессежийн өргөн (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Үүрэн байршлын мэдээлэл (цуцалсан):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Сувгийн бодит тохиргоо:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Үүрэн мэдээлэл сэргээх тариф:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Бүх үүрэн хэмжилтийн мэдээлэл:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Сэргээх"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS шалгалтыг унтраах/асаах"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-тодорхой Мэдээлэл/Тохиргоо"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC боломжтой:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR хязгаарласан:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR боломжтой:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR төлөв:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR давтамж:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Радио мессежийн горимыг тохируулах"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Мессежийн жагсаалтыг ачаалж байна…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Тохируулах"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Утасны мэдээлэл"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Оператор компанийн хангалтын мэдээлэл"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Оператор компанийн хангалтыг эхлүүлэх"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Зөвлөмж: Bluetooth-н холболтыг сайжруулна уу"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Дуудлагын чанарын мэдэгдэл"</string>
 </resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index cfc7b5d..e9ec299 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"केवळ प्राथमिक वापरकर्ता व्हॉइसमेल सेटिंग्ज बदलू शकतो."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"तुमचे सिम कार्ड अवरोधित करणे रद्द केले गेले आहे. तुमचा फोन अनलॉक होत आहे…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"सिम नेटवर्क अनलॉक पिन"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ऑपरेटरसाठी सिम लॉक केले आहे"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"अनलॉक करा"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"डिसमिस करा"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"नेटवर्क अनलॉकची विनंती करत आहे..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"कॉल वेटिंग सुरू करायचे आहे का?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"कॉल दरम्यान येणाऱ्या कॉलबद्दल तुम्हाला सूचित केले जाईल"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"सुरू करा"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"रद्द करा"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS मध्ये CDMA कॉल वेटिंग सुरू आहे"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS मध्ये CDMA कॉल वेटिंग बंद आहे"</string>
     <string name="updating_title" msgid="6130548922615719689">"कॉल सेटिंग्ज"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"कॉल सेटिंग्ज केवळ प्रशासक वापरकर्त्याद्वारे बदलल्‍या जाऊ शकतात."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"सेटिंग्ज (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"डीफॉल्ट डेटा सिम SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL बँडविड्थ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL बँडविड्थ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेल स्थान माहिती (कालबाह्य झाली):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE फिजिकल चॅनल कॉंफिगरेशन:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल माहिती रिफ्रेश रेट:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सर्व सेल परिमाण माहिती:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"रिफ्रेश करा"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS तपासणी टॉगल करा"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-विशिष्ट माहिती/सेटिंग्ज"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC उपलब्ध:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR प्रतिबंधित:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR उपलब्ध:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR स्थिती:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR वारंवारता:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"रेडिओ बँड मोड सेट करा"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"बँड सूची लोड करत आहे…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"सेट करा"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"फोनची माहिती"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"वाहक सुविधा माहिती"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"वाहक सुविधा ट्रिगर करा"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"सूचना: ब्लूटूथ कनेक्टिव्हिटीमध्ये सुधारणा करा"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"कॉल गुणवत्ता सूचना"</string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 6224356..0f07649 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Tetapan Mel Suara hanya boleh diubah suai oleh Pengguna Utama."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Kad SIM anda telah dinyahsekat. Telefon anda dibuka kunci..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN buka kunci rangkaian SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM dikunci untuk pengendali"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Buka kunci"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ketepikan"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Meminta dibukakan kunci rangkaian..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Memajukan ke <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Dimatikan"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Pembawa anda tidak menyokong pelumpuhan pemajuan panggilan semasa telefon anda tidak boleh dihubungi."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Pembawa anda tidak menyokong pemajuan panggilan."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Hidupkan panggilan menunggu?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Semasa panggilan, anda akan diberitahu tentang panggilan masuk"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Hidupkan"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Batal"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Panggilan Menunggu CDMA di bawah IMS Dihidupkan"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Panggilan Menunggu CDMA di bawah IMS Dimatikan"</string>
     <string name="updating_title" msgid="6130548922615719689">"Tetapan panggilan"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Tetapan panggilan hanya boleh diubah oleh pengguna pentadbir."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Tetapan (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data lalai:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lebar Jalur DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lebar Jalur UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Maklumat Lokasi Selular (ditamatkan):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fizikal LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kadar Muat Semula Maklumat Selular:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Maklumat Ukuran Selular:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Muat semula"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Togol Semakan DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Maklumat/Tetapan khusus OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC Tersedia:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR Terhad:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR Tersedia:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Keadaan NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekuensi NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Tetapkan Mod Jalur Radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Memuatkan Senarai Jalur…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Tetapkan"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Maklumat telefon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Maklumat Peruntukan Pembawa"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Cetus Peruntukan Pembawa"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Cadangan: Tingkatkan kesambungan Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Pemberitahuan Kualiti Panggilan"</string>
 </resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index b622d73..efd3e6b 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"အသံမေးလ်ဆက်တင်များကို အဓိကအသုံးပြုသူသာ ပြင်ဆင်နိုင်ပါသည်။"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"သင့် ဆင်းမ်ကဒ်အား ပိတ်ဆို့မှုကို ဖယ်ရှားပြီးပါပြီ။ သင့်ဖုန်းဟာ သော့ဖွင့်နေပါသည်…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"ဆင်းမ်ကဒ် ကွန်ရက် သော့ဖွင့်သော ပင်နံပါတ်"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"အော်ပရေတာအတွက် ဆင်းမ်ကတ်ကို လော့ခ်ချထားသည်"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ဖွင့်ရန်"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ပယ်ရန်"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ကွန်ယက်သော့ဖွင့်ခြင်း တောင်းဆိုနေပါသည်…"</string>
@@ -123,6 +124,13 @@
     <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">"သင့် ဖုန်း ဆက်သွယ်မှု လုပ်လို့မရစဉ် call forwarding ပြုလုပ်မှု ပယ်ဖျက်ရန် သင့် အော်ပရေတာမှ ခွင့်မပြုပါ"</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"သင်၏ ဝန်ဆောင်မှုပေးသူသည် အဝင်ဖုန်းကို ဆက်ပို့ပေးခြင်းအား ပံ့ပိုးမထားပါ။"</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"အဝင်ဖုန်း စောင့်ဆိုင်းခြင်းကို ဖွင့်မလား။"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ဖုန်းပြောနေစဉ် အဝင်ခေါ်ဆိုမှုများအတွက် သင့်ထံ အကြောင်းကြားပါမည်"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ဖွင့်ရန်"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"မလုပ်တော့"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS အောက်ရှိ CDMA အဝင်ဖုန်း စောင့်ဆိုင်းခြင်းကို ဖွင့်ထားသည်"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS အောက်ရှိ CDMA အဝင်ဖုန်း စောင့်ဆိုင်းခြင်းကို ပိတ်ထားသည်"</string>
     <string name="updating_title" msgid="6130548922615719689">"ဖုန်းခေါ်ဆိုခြင်း ဆက်တင်များ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ခေါ်ဆိုမှုကြိုတင်ပြင်ဆင်ချက်များကို ကြီးကြပ်သူသာလျှင် ပြောင်းလဲနိုင်သည်။"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ဆက်တင်များ ( <xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g> )"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"မူရင်း ဒေတာဆင်းမ်ကဒ်အတွက် Id အခွဲ −"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL မြန်နှုန်း (kbps)−"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL မြန်နှုန်း (kbps)−"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ဆဲလ်လူလာတည်နေရာ အချက်အလက် (ကန့်ကွက်ထားသည်) −"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ရုပ်ပိုင်းဆိုင်ရာ ချန်နယ်စီစဉ်သတ်မှတ်မှု−"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ဆဲလ်လူလာ အချက်အလက် ရယူမှုနှုန်း −"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ဆဲလ်လူလာတိုင်းတာမှု အချက်အလက် အားလုံး −"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ပြန်စရန်"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS စစ်ဆေးမှုခလုတ်ကို နှိပ်ပါ"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ထုတ်လုပ်သူနှင့် သက်ဆိုင်သော အချက်အလက်/ဆက်တင်များ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC အသုံးပြုနိုင်သည် -"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ကန့်သတ်ထားသည် -"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR အသုံးပြုနိုင်သည် -"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR အခြေအနေ -"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ကြိမ်နှုန်း -"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ရေဒီယိုလိုင်းမုဒ်အဖြစ် သတ်မှတ်ပါ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ရေဒီယိုလိုင်းစာရင်းကို ဖွင့်နေသည်…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"သတ်မှတ်ရန်"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ဖုန်းအချက်အလက်"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ဝန်ဆောင်မှုပေးသူက ပေးထားသည့် အချက်အလက်များ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"အစပျိုးပေးသော ဖုန်းကုမ္ပဏီ ပံ့ပိုးမှု"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"အကြံပြုချက်- ဘလူးတုသ်ချိတ်ဆက်နိုင်မှုကို ပိုကောင်းအောင် ပြုလုပ်ပါ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ခေါ်ဆိုမှုအရည်အသွေး အကြောင်းကြားချက်"</string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 6629893..93e734a 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Talepost-innstillinger kan bare endres av hovedbrukeren."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM-kortet er blitt avblokkert. Telefonen låses opp…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN-kode for å fjerne operatørlås"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-kortet er operatørlåst"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Lås opp"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Skjul"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Spør om fjerning av operatørlås…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Viderekobler til <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Av"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatøren støtter ikke deaktivering av viderekobling når telefonen er utenfor dekning."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatøren støtter ikke viderekobling."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Vil du slå på «samtale venter»?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Du blir varslet om innkommende anrop under pågående samtaler"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Slå på"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Lukk"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA samtale venter under IMS er på"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA samtale venter under IMS er av"</string>
     <string name="updating_title" msgid="6130548922615719689">"Samtaleinnstillinger"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Anropsinnstillinger kan bare endres av administratoren."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Innstillinger (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Under-ID for standard-SIM-kort for data:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde for nedlasting (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde for opplasting (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informasjon om celleposisjonen (avviklet):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurering av fysisk LTE-kanal:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Oppdateringsfrekvens for celleinformasjon:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All informasjon for cellemåling:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Last inn på nytt"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Slå av/på DNS-sjekk"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Produsentspesfikk informasjon og innstillinger"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC tilgjengelig:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR begrenset:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR tilgjengelig:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-tilstand:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-frekvens:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Angi båndmodus for radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Laster inn båndlisten …"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Angi"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoninformasjon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informasjon om operatørhåndtering"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Utløs operatørhåndtering"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Forslag: Gjør Bluetooth-tilkoblingen bedre"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Varsel om anropskvalitet"</string>
 </resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index e7bc6e5..817f24b 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -50,6 +50,7 @@
     <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 नेटवर्क अनलक PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"अपरेटरका लागि SIM लक गरिएको छ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"अनलोक गर्नुहोस्"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"खारेज गर्नुहोस्"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"नेटवर्क अनलक गर्न अनुरोध गर्दै..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"कल प्रतीक्षाको सुविधा सक्रिय गर्ने हो?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"कल हुँदै गर्दा, तपाईंलाई आगमन कलबारे जानकारी दिइने छ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"सक्रिय गर्नुहोस्"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"रद्द गर्नुहोस्"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS अन्तर्गत CDMA कल प्रतीक्षाको सुविधा सक्रिय छ"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS अन्तर्गत CDMA कल प्रतीक्षाको सुविधा निष्क्रिय छ"</string>
     <string name="updating_title" msgid="6130548922615719689">"कल सेटिङहरू"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"कल सेटिङहरू केवल प्रशासकीय प्रयोगकर्ताद्वारा परिवर्तन गर्न सकिन्छ।"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"सेटिङहरू (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"पूर्वनिर्धारित डेटा SIM को SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ब्यान्डविथ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL व्यान्डविथ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेलको स्थानबारे जानकारी (चल्तीबाट हटाइएको):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE को भौतिक च्यानलको कन्फिगरेसन:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेलसम्बन्धी जानकारीलाई पुनः ताजा गरिने दर:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सेलको मापनसम्बन्धी सबै जानकारी:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"पुनः ताजा गर्नुहोस्"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS को जाँचलाई टगल गर्नुहोस्"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-विशिष्ट जानकारी/सेटिङ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC उपलब्ध छ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR प्रतिबन्धित छ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR उपलब्ध छ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR को स्थिती:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR फ्रिक्वेन्सी:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"रेडियोको ब्यान्डसम्बन्धी मोडलाई सेट गर्नुहोस्"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ब्यान्डको सूची लोड गर्दै…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"सेट गर्नुहोस्"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"फोनसम्बन्धी जानकारी"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"सेवा प्रदायकको प्रावधानसम्बन्धी जानकारी"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"सेवा प्रदायकको प्रावधानलाई ट्रिगर गर्नुहोस्"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"सुझाव: ब्लुटुथको कनेक्टिभिटीको गुणस्तर सुधार्नुहोस्"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"कलको गुणस्तरसम्बन्धी सूचना"</string>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 37e0b27..546efa7 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemailinstellingen kunnen alleen worden gewijzigd door de primaire gebruiker."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Je simkaart is gedeblokkeerd. Je telefoon wordt ontgrendeld..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Pincode voor ontgrendelen SIM-netwerk"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Simkaart vergrendeld voor provider"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ontgrendelen"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Negeren"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Verzoek om ontgrendelen netwerk..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Doorschakelen naar <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Uit"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Je provider biedt geen ondersteuning voor het uitschakelen van oproepdoorschakelingen wanneer je telefoon niet bereikbaar is."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Je provider ondersteunt het doorschakelen van gesprekken niet."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Wisselgesprek inschakelen?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Tijdens een gesprek krijg je een melding over inkomende gesprekken"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Inschakelen"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Annuleren"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA-wisselgesprek onder IMS aan"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA-wisselgesprek onder IMS uit"</string>
     <string name="updating_title" msgid="6130548922615719689">"Gespreksinstellingen"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Oproepinstellingen kunnen alleen worden gewijzigd door de beheerder."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Instellingen (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId van standaard simkaart voor data:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-bandbreedte (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-bandbreedte (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobiele locatiegegevens (beëindigd):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysieke LTE-kanaalconfiguratie:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Vernieuwingsfrequentie van mobiele data:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle mobiele meetgegevens:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Vernieuwen"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS-controle in-/uitschakelen"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specifieke gegevens/instellingen"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC beschikbaar:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR beperkt:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR beschikbaar:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-frequentie:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Modus voor radioband instellen"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Bandlijst laden…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Instellen"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefooninformatie"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Gegevens voor providerregistratie"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Providerregistratie activeren"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suggestie: verbeter de bluetooth-verbinding"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Melding over gesprekskwaliteit"</string>
 </resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 9ce5b9a..b883db1 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -50,6 +50,7 @@
     <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 ନେଟ୍‌ୱର୍କ‌କୁ ଅନଲକ୍ କରିବା ପାଇଁ PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ଅପରେଟର୍ ପାଇଁ SIM ଲକ୍ କରାଯାଇଛି"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ଅନଲକ୍‌ କରନ୍ତୁ"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ଖାରଜ କରନ୍ତୁ"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ନେଟ୍‌ୱର୍କକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"\'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ଚାଲୁ କରିବେ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"କଲ୍ ସମୟରେ, ଇନକମିଂ କଲଗୁଡ଼ିକ ବିଷୟରେ ଆପଣଙ୍କୁ ସୂଚିତ କରାଯିବ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMSରେ CDMA \'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ଚାଲୁ ଅଛି"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMSରେ CDMA \'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ବନ୍ଦ ଅଛି"</string>
     <string name="updating_title" msgid="6130548922615719689">"କଲ୍‌ ସେଟିଂସ୍"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"କଲ୍ ସେଟିଙ୍ଗକୁ କେବଳ ଆଡମିନ୍ ୟୁଜର୍‌ ବଦଳାଇପାରିବେ।"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ସେଟିଙ୍ଗ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ଡିଫଲ୍ଟ ଡାଟା SIMର SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ସେଲ୍ ଲୋକେସନ୍ ସୂଚନା (ଅନୁରୋଧ କରାଯାଇଛି):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ଫିଜିକାଲ୍ ଚ୍ୟାନେଲ୍ କନ୍‌ଫିଗରେସନ୍:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ସେଲ୍ ସୂଚନା ରିଫ୍ରେସ୍ ଦର:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ସମସ୍ତ ସେଲ୍ ପରିମାପ ସୂଚନା:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ରିଫ୍ରେସ୍ କରନ୍ତୁ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS ଯାଞ୍ଚ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-ନିର୍ଦ୍ଦିଷ୍ଟ ସୂଚନା/ସେଟିଂସ୍"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ଉପଲବ୍ଧ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ପ୍ରତିବନ୍ଧିତ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ଉପଲବ୍ଧ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR ସ୍ଥିତି:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ଫ୍ରିକ୍ୱେନ୍ସୀ:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ରେଡିଓ ବ୍ୟାଣ୍ଡ ମୋଡ୍ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ବ୍ୟାଣ୍ଡ ତାଲିକା ଲୋଡ୍ କରାଯାଉଛି…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ସେଟ୍ କରନ୍ତୁ"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ଫୋନ୍ ସୂଚନା"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ମୋବାଇଲ୍ କମ୍ପାନୀ ପ୍ରାବଧାନ ସୂଚନା"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"କେରିଅର୍ ପ୍ରୋଭିଜନିଂ ଟ୍ରିଗର୍ କରନ୍ତୁ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"ପରାମର୍ଶ: ବ୍ଲୁଟୁଥ୍ ସଂଯୋଗ ଉନ୍ନତ କରନ୍ତୁ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"କଲ୍ ଗୁଣବତ୍ତା ବିଜ୍ଞପ୍ତି"</string>
 </resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 08d69b8..2bf0d45 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -50,6 +50,7 @@
     <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 ਨੈਟਵਰਕ ਅਣਲਾਕ PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ਓਪਰੇਟਰ ਲਈ ਸਿਮ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ਖਾਰਜ ਕਰੋ"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ਨੈਟਵਰਕ ਅਣਲਾਕ ਦੀ ਬੇਨਤੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"ਕੀ ਕਾਲ ਦੀ ਉਡੀਕ ਸੈਟਿੰਗ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ਕਾਲ ਕਰਨ ਵੇਲੇ, ਤੁਹਾਨੂੰ ਇਨਕਮਿੰਗ ਕਾਲਾਂ ਬਾਰੇ ਸੂਚਿਤ ਕੀਤਾ ਜਾਵੇਗਾ"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ਚਾਲੂ ਕਰੋ"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ਰੱਦ ਕਰੋ"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS ਦੇ ਅਧੀਨ CDMA ਕਾਲ ਦੀ ਉਡੀਕ ਵਾਲੀ ਸੁਵਿਧਾ ਚਾਲੂ ਹੈ"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS ਦੇ ਅਧੀਨ CDMA ਕਾਲ ਦੀ ਉਡੀਕ ਵਾਲੀ ਸੁਵਿਧਾ ਬੰਦ ਹੈ"</string>
     <string name="updating_title" msgid="6130548922615719689">"ਕਾਲ ਸੈਟਿੰਗਾਂ"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ਕਾਲ ਸੈਟਿੰਗਾਂ ਸਿਰਫ਼ ਪ੍ਰਸ਼ਾਸਕ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਹੀ ਬਦਲੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ਸੈਟਿੰਗਾਂ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਟਾ ਸਿਮ ਦਾ SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ਬੈਂਡਵਿਡਥ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ਬੈਂਡਵਿਡਥ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ਸੈੱਲ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ (ਨਾਪਸੰਦ ਕੀਤੀ):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ਭੌਤਿਕ ਚੈਨਲ ਸੰਰੂਪਣ:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ਸੈੱਲ ਦੀ ਜਾਣਕਾਰੀ ਦੀ ਰਿਫ੍ਰੈਸ਼ ਦਰ:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ਸਾਰੀ ਸੈੱਲ ਮਾਪ ਜਾਣਕਾਰੀ:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ਰਿਫ੍ਰੈਸ਼ ਕਰੋ"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS ਜਾਂਚ ਟੌਗਲ ਕਰੋ"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-ਵਿਸ਼ੇਸ਼ ਜਾਣਕਾਰੀ/ਸੈਟਿੰਗਾਂ"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ਉਪਲਬਧ:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ਪ੍ਰਤਿਬੰਧਿਤ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ਉਪਲਬਧ:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR ਸਥਿਤੀ:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ਵਾਰਵਾਰਤਾ:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ਰੇਡੀਓ ਬੈਂਡ ਮੋਡ ਸੈੱਟ ਕਰੋ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"ਬੈਂਡ ਸੂਚੀ ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ਸੈੱਟ ਕਰੋ"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ਫ਼ੋਨ ਜਾਣਕਾਰੀ"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ਕੈਰੀਅਰ ਪ੍ਰੋਵਿਜ਼ਨਿੰਗ ਜਾਣਕਾਰੀ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ਕੈਰੀਅਰ ਪ੍ਰਵਿਜ਼ਨਿੰਗ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"ਸੁਝਾਅ: ਬਲੂਟੁੱਥ ਕਨੈਕਟੀਵਿਟੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਓ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ਕਾਲ ਦੀ ਕੁਆਲਿਟੀ ਸੰਬੰਧੀ ਸੂਚਨਾ"</string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 410887c..f5ccdc6 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Ustawienia poczty głosowej może zmienić tylko użytkownik główny."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Karta SIM została odblokowana. Odblokowywanie telefonu..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Kod PIN do karty SIM odblokowujący sieć"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Urządzenie obsługuje tylko karty SIM operatora"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Odblokuj"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Zamknij"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Żądanie odblokowania sieci..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Przekierowanie na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Wyłączone"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Twój operator nie umożliwia wyłączenia przekazywania połączeń, gdy numer jest nieosiągalny."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Twój operator nie obsługuje przekierowania połączeń."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Włączyć połączenie oczekujące?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Podczas rozmowy otrzymasz powiadomienie o połączeniach przychodzących"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Włącz"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Anuluj"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Połączenie oczekujące CDMA, gdy usługa IMS jest włączona"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Połączenie oczekujące CDMA, gdy usługa IMS jest wyłączona"</string>
     <string name="updating_title" msgid="6130548922615719689">"Ustawienia połączeń"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Ustawienia połączeń może zmieniać tylko użytkownik będący administratorem."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ustawienia (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Identyfikator domyślnej karty SIM do transmisji danych:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Przepustowość kanału DL (kb/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Przepustowość kanału UL (kb/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacje o lokalizacji z sieci komórkowej (wycofane):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracja kanału fizycznego LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Częstotliwość odświeżania informacji o sieci komórkowej:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Wszystkie informacje pomiarowe z sieci komórkowej:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Odśwież"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Przełącz sprawdzanie DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informacje/ustawienia specyficzne dla producenta OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Dostępne EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Ograniczenie DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Dostępne NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stan NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Częstotliwość NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Ustawianie trybu pasma radiowego"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Ładuję listę pasm…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ustaw"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacje o telefonie"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informacje o obsłudze administracyjnej operatora"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Uruchom obsługę administracyjną operatora"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugestia: popraw łączność Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Powiadomienie o jakości połączenia"</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 91a50d0..8537eaf 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"As definições do correio de voz só podem ser modificadas pelo utilizador principal."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"O cartão SIM foi desbloqueado. O telefone está a ser desbloqueado..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN para desbloqueio de rede do cartão SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM bloqueado para o operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ignorar"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"A pedir desbloqueio de rede..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"A encaminhar para <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desativado"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"O seu operador não suporta a desativação do encaminhamento de chamadas quando o telemóvel não está acessível."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"O seu operador não suporta encaminhamento de chamadas."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Ativar chamada em espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durante uma chamada, será notificado sobre as chamadas recebidas."</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Ativar"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancelar"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Chamada em espera CDMA em IMS ativada"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Chamada em espera CDMA em IMS desativada"</string>
     <string name="updating_title" msgid="6130548922615719689">"Definições de chamadas"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"As definições de chamadas só podem ser alteradas pelo utilizador gestor."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Definições (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubID do SIM de dados predefinido:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de transferência (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carregamento (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informações da localização da célula (descontinuadas):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações da célula:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição de células:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Atualizar"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Ativar/desativar verificação de DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informações/definições específicas de OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponível:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restrito:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponível:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estado NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frequência NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Definir modo de banda de rádio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"A carregar lista de bandas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Definir"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informações do telefone"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informações de fornecimento do operador"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Acionar fornecimento do operador"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugestão: melhore a conetividade Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificação de qualidade da chamada"</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 4415428..9cafc46 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"As configurações do correio de voz só podem ser modificadas pelo usuário principal."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"O seu chip foi desbloqueado. O seu telefone está desbloqueando…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueio da rede SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Chip bloqueado para o operador"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Dispensar"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Solicitando o desbloqueio de rede…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Encaminhar para <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desativado"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Sua operadora não suporta a desativação do encaminhamento de chamada quando seu telefone não está acessível."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Sua operadora não é compatível com o encaminhamento de chamada."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Ativar chamada em espera?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Durante uma chamada, você receberá notificações das chamadas recebidas"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Ativar"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Cancelar"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"A chamada CDMA em espera está ativada no IMS"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"A chamada CDMA em espera está desativada no IMS"</string>
     <string name="updating_title" msgid="6130548922615719689">"Configurações de chamadas"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"As configurações de chamada só podem ser alteradas pelo usuário administrador."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Configurações (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Subcódigo do chip de dados padrão:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informações de local do celular (uso suspenso):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico de LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações do celular:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição do celular:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Atualizar"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Ativar/desativar verificação do DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informações/configurações específicas de OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC disponível:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR restrita:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR disponível:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Estado do NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frequência do NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Definir modo de banda de rádio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Carregando a lista de bandas…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Definir"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informações do telefone"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informações de provisionamento da operadora"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Acionar provisionamento da operadora"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugestão: melhore a conectividade Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificação sobre a qualidade da chamada"</string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 358343b..55bb13f 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Setările pentru mesagerie vocală pot fi modificate numai de utilizatorul principal."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Cardul dvs. SIM a fost deblocat. Telefonul dvs. se deblochează..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Codul PIN de deblocare a rețelei SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Cardul SIM a fost blocat pentru operator"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Deblocați"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Renunțați"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Se solicită deblocarea rețelei..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Se redirecționează la <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Dezactivat"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatorul dvs. nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul nu este accesibil."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatorul dvs. nu acceptă redirecționarea apelurilor."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Activați apelurile în așteptare?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"În timpul unui apel, veți primi o notificare despre apelurile primite"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Activați"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Anulați"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Apelurile în așteptare CDMA din IMS sunt activate"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Apelurile în așteptare CDMA din IMS sunt dezactivate"</string>
     <string name="updating_title" msgid="6130548922615719689">"Setări pentru apeluri"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Numai administratorul poate să modifice setările pentru apeluri."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Setări (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId pentru SIM-ul de date prestabilit:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lățime de bandă de descărcare (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lățime de bandă de încărcare (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informații despre localizarea celulei (învechite):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurarea canalului fizic LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rata de actualizare a informațiilor despre celulă:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toate informațiile de măsurare despre celulă:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizați"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activați/dezactivați verificarea DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informații/Setări caracteristice OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Disponibilă EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Restricționată DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Disponibilă NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stare NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frecvență NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Setați Modul bandă radio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Se încarcă lista de benzi…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Setați"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informații despre telefon"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informații despre provizionarea operatorului"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Declanșați provizionarea operatorului"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugestie: îmbunătățiți conectivitatea Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notificare privind calitatea apelului"</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 77ceeee..b4e6da5 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -50,6 +50,7 @@
     <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">"PIN для разблокировки сети SIM-карты"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM-карта заблокирована для оператора"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Разблокировать"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Закрыть"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Запрос разблокировки сети..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Включить ожидание вызова?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Во время телефонного разговора вы будете получать уведомления о входящих вызовах"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Включить"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Отмена"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Ожидание вызова CDMA, если сервис IMS включен"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Ожидание вызова CDMA, если сервис IMS выключен"</string>
     <string name="updating_title" msgid="6130548922615719689">"Настройки вызовов"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Настройки вызовов может изменить только основной пользователь"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Настройки (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Доп. идентификатор SIM-карты для мобильного Интернета по умолчанию:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускная способность DL-канала (кбит/c):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускная способность UL-канала (кбит/с):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информация о местоположении сети (устаревшее):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация физического канала LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота обновления данных о сетях:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Статистика сети:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Обновить"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Включить/отключить проверку DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Информация/настройки OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC доступно:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ограничено:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR доступно:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Состояние NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Частота NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Настроить режим сети"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Загрузка списка частот…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Сохранить"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Информация о телефоне"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Сведения о синхронизации оператора"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запустить синхронизацию оператора"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Рекомендация: повысьте качество связи по Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Уведомление о качестве связи"</string>
 </resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index b89b1d8..174fd1c 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -50,6 +50,7 @@
     <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 ජාල අඟුළු හැරීමේ PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"මෙහෙයවන්නා සඳහා SIM අගුලු දමා ඇත"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"අඟුල අරින්න"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ඉවතලන්න"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"ජාල අඟුළු ඇරීමක් ඉල්ලුම් කරමින්…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"ඇමතුම රඳවා ගැනීම ක්‍රියාත්මක කරන්නද?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ඇමතුමක් අතරතුර, ඔබට එන ඇමතුම් පිළිබඳ දැනුම් දෙනු ඇත"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ක්‍රියාත්මක කරන්න"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"අවලංගු කරන්න"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS යටත් CDMA ඇමතුම රඳවා ගැනීම ක්‍රියාත්මකයි"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS යටත් CDMA ඇමතුම රඳවා ගැනීම ක්‍රියාවිරහිතයි"</string>
     <string name="updating_title" msgid="6130548922615719689">"ඇමතුම් සැකසීම්"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ඇමතුම් සැකසීම් වෙනස් කළ හැක්කේ පරිපාලක පරිශීලකයාට පමණි."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"සැකසීම් (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"පෙරනිමි දත්ත SIM පතේ උප හැඳුනුම:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL කලාප පළල (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL කලාප පළල (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"සෙල් ස්ථාන තොරතුරු (අත් හරින ලදී):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE භෞතික නාලිකා වින්‍යාසය:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"සෙල් තොරතුරු නැවුම් කිරීමේ අනුපාතය:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"සියලු සෙල් මිනුම් තොරතුරු:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"නැවුම් කරන්න"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS පරීක්ෂාව ටොගල කරන්න"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-විශේෂිත තොරතුරු/සැකසීම්"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ලබා ගත හැකි:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR සීමා කළ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ලබා ගත හැකි:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR තත්ත්වය:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR සංඛ්‍යාතය:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"රේඩියෝ කලාප ප්‍රකාරය සකසන්න"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"කලාප ලැයිස්තුව පූරණය කරමින්…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"සකසන්න"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"දුරකථන තොරතුරු"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"වාහක ප්‍රතිපාදන තතු"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"උත්ප්‍රේරක වාහක ප්‍රතිපාදන"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"යෝජනාව: බ්ලූටූත් සබැඳුම වැඩි දියුණු කිරීම"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"ඇමතුම් ගුණත්ව දැනුම්දීම"</string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index d783fc7..8d996a1 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Nastavenia hlasovej schránky môže zmeniť iba primárny používateľ."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM karta bola odblokovaná. Prebieha odomykanie telefónu..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Kód PIN odomknutia siete pre SIM kartu"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM karta je uzamknutá pre operátora"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Odomknúť"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Zatvoriť"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Žiadosť o odomknutie siete..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Presmerovanie na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Vypnuté"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Váš operátor neumožňuje zakázanie presmerovaní, keď je telefón nedostupný."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Váš operátor nepodporuje presmerovanie hovorov."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Chcete zapnúť funkciu Čakajúci hovor?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Počas hovoru budete dostávať upozornenia na prichádzajúce hovory"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Zapnúť"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Zrušiť"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA – čakajúci hovor službe IMS – zapnuté"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA – čakajúci hovor v službe IMS – vypnuté"</string>
     <string name="updating_title" msgid="6130548922615719689">"Nastavenia hovorov"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Nastavenia hovorov môže zmeniť iba používateľ s povoleniami správcu."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Nastavenia (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Podradený identifikátor predvolenej dátovej SIM karty:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rýchlosť pripojenia DL (kB/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rýchlosť pripojenia UL (kB/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informácie o polohe mobilnej siete (podpora bola ukončená):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurácia fyzického kanála LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvencia obnovenia informácií o mobilnej sieti:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všetky informácie o meraní mobilnej siete:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Obnoviť"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Prepnúť kontrolu DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informácie alebo nastavenia špecifické pre výrobcu OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Dostupné EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Obmedzené DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Dostupné NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stav NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekvencia NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Nastaviť režim rádiového pásma"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Načítava sa zoznam pásiem…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Nastaviť"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informácie o telefóne"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informácie o poskytovaní služieb operátorom"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Spustiť poskytovanie služieb operátorom"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Návrh: zlepšenie pripojenia cez Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Upozornenie o kvalite hovoru"</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 58a087d..5b88521 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Nastavitve odzivnika lahko spremeni samo primarni uporabnik."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Kartica SIM je bila deblokirana. Telefon se odklepa ..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN za odklep omrežja kartice SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Kartica SIM je zaklenjena za operaterja"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Odkleni"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Opusti"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Zahteva za odklepanje omrežja ..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Preusmerjanje na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Izklopljeno"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Vaš operater ne podpira izklopa preusmeritve klicev, kadar je telefon nedosegljiv."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Vaš operater ne podpira posredovanja klicev."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Želite vklopiti čakajoči klic?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Med klicem boste obveščeni o dohodnih klicih"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Vklopi"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Prekliči"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Čakajoči klic CDMA v sistemu IMS je vklopljen"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Čakajoči klic CDMA v sistemu IMS je izklopljen"</string>
     <string name="updating_title" msgid="6130548922615719689">"Nastavitve klicev"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Nastavitve klicanja lahko spremeni samo uporabnik s skrbniškim dostopom."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Nastavitve (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ID naročnine privzete kartice SIM za prenos podatkov:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Pasovna širina za prenos (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Pasovna širina za nalaganje (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Podatki o lokaciji celice (zastarelo):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija fizičnega kanala LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvenca osveževanja podatkov o celici:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Vsi podatki o meritvah celice:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Osveži"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Preklop preverjanja DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informacije/nastavitve za OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Razpoložljivo za EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Omejeno za DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Razpoložljivo za NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Stanje NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekvenca NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Nastavljanje načina radijskega območja"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Nalaganje seznama frekvenčnih pasov …"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Nastavi"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Podatki o omogočanju uporabe operaterja"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Sproži omogočanje uporabe operaterja"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Predlog: Izboljšajte povezavo Bluetooth."</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Obvestilo o kakovosti klica"</string>
 </resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 888feac..64f880d 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Cilësimet e postës zanore mund të modifikohen vetëm nga \"Përdoruesi kryesor\""</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Karta jote SIM u zhbllokua. Telefoni yt po shkyçet..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN-i i shkyçjes së rrjetit të kartës SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Karta SIM e kyçur për operatorin"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Shkyçe"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Injoro"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Po kërkon shkyçjen e rrjetit…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Transferim te <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Çaktivizuar"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatori yt nuk mbështet çaktivizimin e transferimit të telefonatës kur telefoni është i paarritshëm."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatori celular nuk e mbështet transferimin e telefonatave."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Do të aktivizosh telefonatat në pritje?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Gjatë një telefonate, do të njoftohesh për telefonatat hyrëse"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktivizo"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Anulo"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Telefonatat në pritje CDMA në sistemin IMS janë aktive"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Telefonatat në pritje CDMA në sistemin IMS janë joaktive"</string>
     <string name="updating_title" msgid="6130548922615719689">"Cilësimet e telefonatës"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Cilësimet e telefonatës mund të ndryshohen vetëm nga administratori."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Cilësimet (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"ID-ja dytësore e kartës SIM të parazgjedhur të të dhënave:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Gjerësia e bandës DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Gjerësia e bandës UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacionet e vendndodhjes të rrjetit celular (e vjetruar):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurimi i kanalit fizik LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Shpejtësia e rifreskimit të informacioneve të rrjetit celular"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Të gjitha informacionet e matjes së rrjetit celular:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Rifresko"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Ndrysho kontrollin e DNS-së"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Informacion/cilësime specifike për OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Ofrohet EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR me kufizime:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Ofrohet NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Gjendja e NR-së:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frekuenca e NR-së:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Cakto modalitetin e brezit të radios"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Po ngarkon listën e brezave…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Cakto"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacioni i telefonit"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Informacionet e përgatitjes së operatorit celular"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivizo përgatitjen e operatorit celular"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Sugjerim: Përmirëso lidhshmërinë me Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Njoftim për cilësinë e telefonatës"</string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 03403e9..f242d5d 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -50,6 +50,7 @@
     <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">"PIN за откључавање мреже на SIM картици"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM картица је закључана за оператера"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Откључај"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Одбаци"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Тражење откључавања мреже"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Желите да укључите стављање позива на чекање?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Током позива ћете добијати обавештења о долазним позивима"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Укључи"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Откажи"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Стављање CDMA позива на чекање у IMS-у је укључено"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Стављање CDMA позива на чекање у IMS-у је искључено"</string>
     <string name="updating_title" msgid="6130548922615719689">"Подешавања позива"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Само кориснику са администраторским правима је дозвољено да мења подешавања позива."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Подешавања (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -870,7 +878,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubID подразумеваног SIM-а за податке:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL пропусни опсег (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL пропусни опсег (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информације о локацији предајника (застарело):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација LTE физичког канала:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Учесталост освежавања информација о предајнику:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Све информације о мерењу за предајник:"</string>
@@ -901,6 +908,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Освежи"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Укључи/искључи проверу DNS-а"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Информације/подешавања специфична за произвођача оригиналне опреме"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC доступно:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ограничено:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR доступно:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR стање:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR учесталост:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Подесите режим радијског опсега"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Учитава се листа опсега…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Подеси"</string>
@@ -910,4 +922,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Информације о телефону"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Информације о додели мобилног оператера"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Покретање доделе мобилног оператера"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Предлог: побољшајте Bluetooth везу"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Обавештење о квалитету позива"</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 2a7b8b0..458a768 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Endast den primära användaren får ändra röstbrevlådans inställningar."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM-kortets spärr har tagits bort. Låser upp telefonen…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN-kod för upplåsning av SIM-nätverk"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Operatörslåst SIM-kort"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Lås upp"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ta bort permanent"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Försöker låsa upp nätverket…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Vidarebefordrar till <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Av"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatören stöder inte inaktivering av vidarebefordran av samtal när det inte går att nå telefonen."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Din operatör stöder inte vidarebefordran av samtal."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Aktivera Samtal väntar?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Du meddelas om inkommande samtal under samtal"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Aktivera"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Avbryt"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA samtal väntar under IMS på"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA samtal väntar under IMS av"</string>
     <string name="updating_title" msgid="6130548922615719689">"Samtalsinställningar"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Det är bara administratören som kan ändra samtalsinställningar."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Inställningar (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId för standarddata på SIM-kortet:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandbredd för nedladdning (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandbredd för uppladdning (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Platsinformation för mast (utfasad):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration för LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvens för uppdatering av mastinformation:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alla information om mastmätning:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Uppdatera"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Aktivera och inaktivera DNS-kontroll"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specifik information/inställningar"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC tillgänglig:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR begränsad:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR tillgänglig:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR-status:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR-frekvens:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Konfigurera radiobandsläget"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Läser in bandlista …"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ange"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoninformation"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Information om operatörsadministration"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivera operatörsadministration"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Förslag: Förbättra Bluetooth-anslutningen"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Avisering om samtalskvalitet"</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 7493201..acfeb3b 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Mipangilio ya ujumbe wa sauti inaweza kubadilishwa na Mtumiaji wa Msingi Pekee."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Kadi yako ya simu imefunguliwa. Simu yangu inafungua…."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN ya kufungua mtandao wa SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM imefungwa kwa mtoa huduma"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Fungua"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ondoa"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Inaomba mtandao ufunguliwe…."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Inasambaza kwa <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Imezimwa"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Mtoa huduma wako haauni ulemezaji wa kusambaza simu wakati simu yako haifikiwi."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Kampuni inayokupa huduma za simu haina huduma ya kusambaza simu."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Ungependa kuwasha kipengele cha simu inayosubiri kupokewa?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Simu inapoendelea, utaarifiwa kuhusu simu unazopigiwa"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Washa"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Ghairi"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Kipengele cha Simu Inayosubiri Kupokewa ya CDMA chini ya IMS Kimewashwa"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Kipengele cha Simu Inayosubiri Kupokewa ya CDMA chini ya IMS Kimezimwa"</string>
     <string name="updating_title" msgid="6130548922615719689">"Mipangilio ya simu"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Mipangilio ya simu inaweza kubadilishwa na mtumiaji wa akaunti ya msimamizi."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Mipangilio (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId ya SIM chaguomsingi ya data:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Kipimo Data cha DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kipimo Data cha UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Maelezo ya Mahali Simu ya Mkononi Ilipo (huduma haipo tena):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Mipangilio ya Kituo Halisi cha LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kasi ya Kuonyesha Upya Maelezo ya Simu:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Maelezo Yote ya Vipimo vya Simu:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Onyesha upya"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Geuza Ukaguzi wa DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Maelezo/Mipangilio Mahususi kwa Kampuni Inayotengeneza Vifaa (OEM)"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC Inapatikana:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR Imewekewa Vizuizi:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR Inapatikana:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Hali ya NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Masafa ya NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Weka Hali ya Bendi ya Redio"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Inapakia Orodha ya Bendi…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Weka"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Maelezo ya simu"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Maelezo ya Utaratibu wa Kutayarisha Mtandao"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Anzisha Utaratibu wa Kutayarisha Mtandao"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Pendekezo: Boresha muunganisho wa Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Arifa ya Ubora wa Simu"</string>
 </resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index f9c80dd..533988d 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"முதன்மை பயனர் மட்டுமே குரலஞ்சல் அமைப்புகளை மாற்ற முடியும்."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"சிம் கார்டின் தடுப்பு நீக்கப்பட்டது. மொபைல் திறக்கப்படுகிறது…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"சிம் நெட்வொர்க்கின் தடைநீக்க பின்"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ஆப்பரேட்டருக்கு சிம் பூட்டப்பட்டுள்ளது"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"தடைநீக்கு"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"விலக்கு"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"நெட்வொர்க் தடைநீக்கத்தைக் கோருகிறது…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"அழைப்பு காத்திருப்பை இயக்கவா?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ஒரு அழைப்பில் இருக்கும்போது, உள்வரும் அழைப்புகள் குறித்து உங்களுக்குத் தெரிவிக்கப்படும்"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"இயக்கு"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ரத்துசெய்"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA அழைப்பு காத்திருப்பு IMS இயக்கத்தில்"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA அழைப்பு காத்திருப்பு IMS முடக்கத்தில்"</string>
     <string name="updating_title" msgid="6130548922615719689">"அழைப்பு அமைப்பு"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"நிர்வாகிப் பயனர் மட்டுமே அழைப்பிற்கான அமைப்புகளை மாற்ற முடியும்."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"அமைப்புகள் (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"இயல்பான டேட்டா சிம்மின் துணை ஐடி:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL இணைய வேகம் (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL இணைய வேகம் (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"மொபைலின் இருப்பிடத் தகவல் (நிறுத்தப்பட்டது):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ஃபிசிக்கல் சேனல் உள்ளமைவு:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"மொபைல் தகவலின் புதுப்பிப்பு விகிதம்:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"அனைத்து மொபைல் அளவீட்டுத் தகவல்:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"புதுப்பி"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS சரிபார்ப்பை நிலைமாற்று"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM சார்ந்த தகவல்/அமைப்புகள்"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC உள்ளது:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR கட்டுப்படுத்தப்பட்டது:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR உள்ளது:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR நிலை:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR அலைவரிசை:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ரேடியோ பேண்டு பயன்முறையை அமை"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"பேண்டு பட்டியலை ஏற்றுகிறது…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"அமை"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"மொபைலின் தகவல்"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Carrier Provisioning Info"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger Carrier Provisioning"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"பரிந்துரை: புளூடூத் இணைப்பை மேம்படுத்துங்கள்"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"அழைப்பின் தரம் தொடர்பான அறிவிப்பு"</string>
 </resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index aeb207c..a233f9e 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -50,6 +50,7 @@
     <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>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"అన్‌లాక్ చేయి"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"తీసివేయి"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"నెట్‌వర్క్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"కాల్ వెయిటింగ్‌ను ఆన్ చేయాలా?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"మీరు కాల్‌లో ఉండగా, ఇన్‌కమింగ్ కాల్‌ల గురించి మీకు తెలియజేయబడుతుంది"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"ఆన్ చేయి"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"రద్దు చేయి"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMSలో CDMA కాల్ వెయిటింగ్ ఆన్‌లో ఉంది"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMSలో CDMA కాల్ వెయిటింగ్ ఆఫ్‌లో ఉంది"</string>
     <string name="updating_title" msgid="6130548922615719689">"కాల్ సెట్టింగ్‌లు"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"కాల్ సెట్టింగ్‌లను నిర్వాహక వినియోగదారు మాత్రమే మార్చగలరు."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"సెట్టింగ్‌లు (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"డిఫాల్ట్ డేటా SIM యొక్క SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL బ్యాండ్‌విడ్త్ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL బ్యాండ్‌విడ్త్ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"సెల్ స్థాన సమాచారం (నిలిపివేయబడింది):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE భౌతిక ఛానెల్ కాన్ఫిగరేషన్:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"సెల్ సమాచార రిఫ్రెష్ సగటు:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"మొత్తం సెల్ పరిమాణ సమాచారం:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"రిఫ్రెష్ చేయి"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS తనిఖీని టోగుల్ చేయండి"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-నిర్దిష్ట సమాచారం/సెట్టింగ్‌లు"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC అందుబాటులో ఉంది:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR నియంత్రించబడింది:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR అందుబాటులో ఉంది:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR స్టేటస్:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR ఫ్రీక్వెన్సీ:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"రేడియో బ్యాండ్ మోడ్‌ను సెట్ చేయండి"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"బ్యాండ్ జాబితాను లోడ్ చేస్తోంది…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"సెట్ చేయి"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ఫోన్ సమాచారం"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"క్యారియర్ కేటాయింపు సమాచారం"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"క్యారియర్ కేటాయింపు సక్రియం చేయండి"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"సూచన: బ్లూటూత్ కనెక్టివిటీని మెరుగుపరచండి"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"కాల్ క్వాలిటీ నోటిఫికేషన్"</string>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 29fb43d..5a4e293 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ผู้ใช้หลักเท่านั้นที่สามารถเปลี่ยนการตั้งค่าข้อความเสียงได้"</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"ยกเลิกการปิดกั้นซิมการ์ดแล้ว กำลังปลดล็อกโทรศัพท์ของคุณ..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN ปลดล็อกเครือข่ายซิม"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"ล็อก SIM สำหรับโอเปอเรเตอร์แล้ว"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ปลดล็อก"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"เลิกแสดง"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"กำลังขอปลดล็อกเครือข่าย..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"เปิดใช้สายเรียกซ้อนไหม"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"ระบบจะแจ้งเตือนหากมีสายเรียกเข้าซ้อนระหว่างการโทร"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"เปิด"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"ยกเลิก"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"เปิดใช้สายเรียกซ้อนระบบ CDMA ภายใต้ IMS"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"ปิดใช้สายเรียกซ้อนระบบ CDMA ภายใต้ IMS"</string>
     <string name="updating_title" msgid="6130548922615719689">"การตั้งค่าการโทร"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"ผู้ใช้ระดับผู้ดูแลระบบเท่านั้นที่สามารถเปลี่ยนแปลงการตั้งค่าการโทรได้"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"การตั้งค่า (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId ของซิมอินเทอร์เน็ตเริ่มต้น:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"แบนด์วิดท์ดาวน์โหลด (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"แบนด์วิดท์อัปโหลด (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ข้อมูลตำแหน่งของเครือข่ายมือถือ (เลิกใช้งานแล้ว):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"การกำหนดค่าแชเนลทางกายภาพของ LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"อัตราการรีเฟรชข้อมูลมือถือ:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ข้อมูลการวัดเครือข่ายมือถือทั้งหมด:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"รีเฟรช"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"สลับการตรวจสอบ DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"ข้อมูล/การตั้งค่าเฉพาะตาม OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"มี EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR ถูกจำกัด:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"มี NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"สถานะ NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"ความถี่ NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ตั้งค่าโหมดย่านความถี่วิทยุ"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"กำลังโหลดรายการย่านความถี่…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"ตั้งค่า"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"ข้อมูลโทรศัพท์"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"ข้อมูลการจัดสรรผู้ให้บริการ"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ทริกเกอร์การจัดสรรผู้ให้บริการ"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"คำแนะนำ: ปรับปรุงการเชื่อมต่อบลูทูธ"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"การแจ้งเตือนคุณภาพการโทร"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 7a0a576..0d266a4 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Maaari lang baguhin ng Pangunahing User ang Mga Setting ng Voicemail."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Na-unblock ang iyong SIM card. Nag-a-unlock ang telepono mo…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"PIN na pang-unlock ng SIM network"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Na-lock para sa operator ang SIM"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"I-unlock"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Balewalain"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Humihiling ng pag-unlock sa network…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Pinapasa sa <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Naka-off"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Hindi sinusuportahan ng iyong carrier ang hindi pagpapagana ng pagpasa ng tawag kapag hindi maabot ang iyong telepono."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Hindi sinusuportahan ng iyong carrier ang pagpasa ng tawag."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"I-on ang call waiting?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Habang tumatawag, aabisuhan ka sa mga papasok na tawag"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"I-on"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Kanselahin"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Naka-on ang CDMA Call Waiting sa IMS"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Naka-off ang CDMA Call Waiting sa IMS"</string>
     <string name="updating_title" msgid="6130548922615719689">"Mga setting ng tawag"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Ang admin user lang ang maaaring magbago sa mga setting ng tawag."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Mga Setting (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"SubId ng default na data SIM:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Impormasyon ng Lokasyon ng Cell (hindi na ginagamit):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration ng LTE Physical Channel:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rate ng Pag-refresh ng Impormasyon ng Cell:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Impormasyon ng Pagsukat sa Lahat ng Cell:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"I-refresh"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"I-toggle ang DNS Check"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Impormasyon/Mga Setting na partikular sa OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Available ang EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Pinaghihigpitan ang DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Available ang NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Status ng NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frequency ng NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Itakda ang Band Mode ng Radyo"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Nilo-load ang Listahan ng Band…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Itakda"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Impormasyon ng telepono"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Impormasyon sa Provisioning ng Carrier"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"I-trigger ang Provisioning ng Carrier"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Suhestyon: Pahusayin ang connectivity ng Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Notification sa Kalidad ng Tawag"</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index ade129a..c6ed1da 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Sesli Mesaj Ayarları yalnızca Birincil Kullanıcı tarafından değiştirilebilir."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"SIM kartınızın engellemesi kaldırıldı. Telefonunuzun kilidi açılıyor..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM ağı kilit açma PIN kodu"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM şu operatör için kilitlendi"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Kilit Aç"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Kapat"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Ağ kilidini açma isteği yapılıyor..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Şuraya yönlendiriliyor: <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Kapalı"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatörünüz, telefonunuza ulaşılamadığında çağrı yönlendirmenin devre dışı bırakılmasını desteklemiyor."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatörünüz arama yönlendirmeyi desteklemiyor."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Arama bekletme etkinleştirilsin mi?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Bir arama sırasında gelen aramalarla ilgili olarak bilgilendirilirsiniz"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Etkinleştir"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"İptal"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS altında CDMA Arama Bekletme Etkin"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS altında CDMA Arama Bekletme Devre Dışı"</string>
     <string name="updating_title" msgid="6130548922615719689">"Çağrı ayarları"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Çağrı ayarları sadece yönetici tarafından değiştirilebilir."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Ayarlar (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Varsayılan veri SIM\'inin alt kimliği:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"İndirme Bant Genişliği (kb/sn.):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Yükleme Bant Genişliği (kb/sn.):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Hücre Konumu Bilgisi (kullanımdan kaldırıldı):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziksel Kanal Yapılandırması:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Hücre Bilgilerini Yenileme Hızı:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tüm Hücre Ölçümü Bilgileri:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Yenile"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS Denetimini Aç/Kapat"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM\'e Özgü Bilgiler/Ayarlar"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC Kullanılabilir:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR Kısıtlanmış:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR Kullanılabilir:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR Durumu:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR Frekansı:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Radyo Bant Modunu Ayarla"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Bant Listesi Yükleniyor…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Ayarla"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon bilgileri"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operatör Temel Hazırlık Bilgileri"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Tetikleyici Operatör Temel Hazırlığı"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Öneri: Bluetooth bağlantısını iyileştirin"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Arama Kalitesiyle İlgili Bildirim"</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 7f5b8cb..8e73fef 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -50,6 +50,7 @@
     <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">"Розбл. PIN-код мережі SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Заблокована SIM-карта оператора"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Розблок."</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Відхилити"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Запитув. розблок. мережі..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Увімкнути паралельний виклик?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Під час дзвінків ви отримуватимете сповіщення про інші вхідні виклики"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Увімкнути"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Скасувати"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Паралельний виклик CDMA на платформі IMS увімкнено"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Паралельний виклик CDMA на платформі IMS вимкнено"</string>
     <string name="updating_title" msgid="6130548922615719689">"Налаштування викликів"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Налаштування викликів може змінювати лише адміністратор."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Налаштування (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -873,7 +881,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Субідентифікатор SIM-карти для даних за умовчанням:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускна спроможність DL (кбіт/с):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускна спроможність UL (кбіт/с):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Геодані телефона (більше не підтримуються):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфігурація фізичного каналу LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота оновлення даних про мобільний зв\'язок:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усі дані про показники мобільного зв\'язку:"</string>
@@ -904,6 +911,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Оновити"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Увімк./вимк. перевірку DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Інформація/налаштування OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC доступно:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR обмежено:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR доступно:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Статус NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Частота NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Установити режим радіодіапазону"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Завантаження списку діапазонів частот…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Установити"</string>
@@ -913,4 +925,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Інформація про телефон"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Інформація про ініціалізацію оператора"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запустити ініціалізацію оператора"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Пропозиція: покращте якість підключення Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Сповіщення про якість виклику"</string>
 </resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 9724d8e..012142a 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -50,6 +50,7 @@
     <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 نیٹ ورک غیر مقفل کرنے کا PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"‏آپریٹر کے لیے SIM مقفل ہے"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"غیر مقفل کریں"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"برخاست کریں"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"نیٹ ورک غیر مقفل کرنے کی درخواست کر رہا ہے…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"\'کال کا انتظار کرنا\' آن کریں؟"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"کال کے دوران، آپ کو موصول ہونے والی کالز کے بارے میں مطلع کیا جائے گا"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"آن کریں"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"منسوخ کریں"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"‏IMS آن کے تحت CDMA کال کا انتظار کرنا"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"‏IMS آف کے تحت CDMA کال کا انتظار کرنا"</string>
     <string name="updating_title" msgid="6130548922615719689">"کال کی ترتیبات"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"صرف منتظم صارف ہی کال کی ترتیبات تبدیل کر سکتا ہے۔"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"ترتیبات (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"‏ڈیفالٹ ڈیٹا SIM کی SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"‏DL بینڈ وڈتھ (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"‏UL بینڈ وڈتھ (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"سیل کے مقام کی معلومات (فرسودہ):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"‏LTE فزيکل چینل کنفیگریشن:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"سیل کی معلومات ریفریش کرنے کی شرح:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"سیل پیمائش کی تمام معلومات:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"ریفریش کریں"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"‏DNS چیک ٹوگل کریں"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"‏OEM-کیلئے مخصوص معلومات/ترتیبات"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"‏EN-DC دستیاب ہے:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"‏DCNR محدود کردہ:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"‏NR دستیاب ہے:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"‏NR ریاست:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"‏NR فریکوئنسی:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"ریڈیو بینڈ موڈ سیٹ کریں"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"بینڈ کی فہرست لوڈ ہو رہی ہے…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"سیٹ کریں"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"فون کی معلومات"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"کیرئیر فراہمی معلومات"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ٹرگر کیرئیر فراہمی"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"تجویز: بلوٹوتھ کنیکٹوٹی کو بہتر بنائیں"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"کال کی کوالٹی کی اطلاع"</string>
 </resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 8ef5448..fa3bd82 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Ovozli pochta sozlamalarini faqat bosh foydalanuvchi o‘zgartira oladi."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"To‘sib qo‘yilgan SIM kartangiz ochildi. Telefoningiz qulfdan chiqarilmoqda…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"SIM kartani tarmoqdagi qulfidan chiqarish PIN kodi"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"SIM karta operator uchun bloklangan"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Qulfdan chiqarish"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Rad etish"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Tarmoqni qulfdan chiqarish so‘ralmoqda…"</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g> raqamiga yo‘naltiriladi"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Yoqilmagan"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Telefoningiz o‘chiq bo‘lganida qo‘ng‘iroqlarni boshqa raqamga yo‘naltirishni o‘chirish xususiyati tarmoq operatoringizda yo‘q."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatoringiz tarmog‘i orqali chaqiruvlarni uzatib bo‘lmaydi"</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Chaqiruvdagi kutish rejimi yoqilsinmi?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Suhbat paytida boshqa kiruvchi chaqiruvlar haqida sizga bildirishnoma keladi"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Yoqish"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Bekor qilish"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS asosidagi CDMA chaqiruvlari uchun kutish rejimi yoqildi"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS asosidagi CDMA chaqiruvlari uchun kutish rejimi faolsizlantirildi"</string>
     <string name="updating_title" msgid="6130548922615719689">"Chaqiruv sozlamalari"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Faqat administrator qo‘ng‘iroq sozlamalarini o‘zgartirishi mumkin."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Sozlamalar (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Mobil internet uchun birlamchi SIM kartaning qoʻshimcha identifikatori:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Axborot uzatish tezligi (kbit/s):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL kanalining axborot uzatish tezligi (kbit/s):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Tarmoq joylashuvi haqidagi axborot (eskirgan):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE jismoniy kanal konfiguratsiyasi:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tarmoq haqidagi axborotning yangilanish darajasi:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tarmoq statistikasi:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Yangilash"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS tekshiruvini yoqish/o‘chirish"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM maxsus axboroti va sozlamalari"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC ochiq:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR cheklangan:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR ochiq:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR holati:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR chastotasi:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Tarmoq rejimini sozlash"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Chastotalar ro‘yxati yuklanmoqda…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Saqlash"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon haqida"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Operator sinxronizatsiyasi haqida"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operator sinxronizatsiyasini yoqish/o‘chirish"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Tavsiya: Aloqa sifatini Bluetooth orqali oshiring"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Chaqiruv sifati haqida bildirishnoma"</string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index dfc0c11..bd8a291 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Chỉ người dùng chính mới có thể sửa đổi Cài đặt thư thoại."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Thẻ SIM của bạn đã được bỏ chặn. Điện thoại của bạn đang mở khóa…"</string>
     <string name="label_ndp" msgid="7617392683877410341">"Mã PIM mở khóa mạng SIM"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"Đã khóa SIM đối với nhà cung cấp dịch vụ"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Mở khóa"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Loại bỏ"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Đang yêu cầu mở khóa mạng..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Chuyển tiếp tới <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Tắt"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Nhà cung cấp dịch vụ của bạn không hỗ trợ vô hiệu hóa chuyển tiếp cuộc gọi khi điện thoại của bạn không thể truy cập được."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Nhà mạng của bạn không hỗ trợ tính năng chuyển tiếp cuộc gọi."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Bật chế độ cuộc gọi chờ?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Trong suốt cuộc gọi, bạn sẽ nhận được thông báo về các cuộc gọi đến"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Bật"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Hủy"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Cuộc gọi chờ CDMA trong IMS đang bật"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Cuộc gọi chờ CDMA trong IMS đang tắt"</string>
     <string name="updating_title" msgid="6130548922615719689">"Cài đặt cuộc gọi"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Chỉ người dùng quản trị mới có thể thay đổi cài đặt cuộc gọi."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Cài đặt (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"Mã phụ của SIM dữ liệu mặc định:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Băng thông DL (kb/giây):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Băng thông UL (kb/giây):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Thông tin vị trí mạng di động (không dùng nữa):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Cấu hình kênh LTE thực:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tốc độ làm mới thông tin mạng di động:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toàn bộ thông tin về số đo mạng di động:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Làm mới"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Bật/tắt chế độ kiểm tra DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Thông tin/Cài đặt dành riêng cho OEM"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"Hỗ trợ EN-DC:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Hạn chế DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"Hỗ trợ NR:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Trạng thái NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Tần số NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Đặt chế độ dải tần số"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Đang tải danh sách băng tần…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Đặt"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Thông tin điện thoại"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Thông tin cấp phép của nhà mạng"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Kích hoạt dịch vụ cấp phép của nhà mạng"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Mục đề xuất: Cải thiện khả năng kết nối Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Thông báo về chất lượng cuộc gọi"</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 304230d..2164961 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -50,6 +50,7 @@
     <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 网络解锁 PIN 码"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"已锁定以下运营商的 SIM 卡:"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"解锁"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"关闭"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"正在请求网络解锁..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"要启用来电等待吗?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"如果您在通话期间接到来电,则会收到通知"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"开启"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"取消"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"基于 IMS 的 CDMA 来电等待功能已开启"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"基于 IMS 的 CDMA 来电等待功能已关闭"</string>
     <string name="updating_title" msgid="6130548922615719689">"通话设置"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"只有管理员用户才能更改通话设置。"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"设置(<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"默认数据 SIM 卡的 SubId:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 带宽 (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 带宽 (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"移动网络位置信息(已弃用):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 物理信道配置:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"移动网络信息刷新频率:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有移动网络测量信息:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"刷新"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"切换 DNS 检查"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"特定 OEM 的信息/设置"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"4G/5G 双连接可用:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"5G 双连接受限:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"5G 可用:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"5G 状态:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"5G 频率:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"设置无线装置频道模式"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"正在加载频道列表…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"设置"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"手机信息"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"运营商配置信息"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"触发运营商配置"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"建议:改善蓝牙连接"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"通话质量通知"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 085ad57..c9c8f4f 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -50,6 +50,7 @@
     <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 網絡解除鎖定 PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"流動網絡供應商的 SIM 卡已上鎖"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"解除鎖定"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"關閉"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"正在要求解除網絡鎖定..."</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"要開啟來電等候功能嗎?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"您會在通話期間收到來電通知"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"開啟"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"取消"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS 下的 CDMA 來電等候功能已開啟"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS 下的 CDMA 來電等候功能已關閉"</string>
     <string name="updating_title" msgid="6130548922615719689">"通話設定"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"只有管理員可以變更通話設定。"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"設定 (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"預設數據 SIM 卡的子 ID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"下載頻寬 (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"上載頻寬 (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"發射站位置資料 (已淘汰):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體渠道設定:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"發射站資料重新整理頻率:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有發射站量度資料:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"重新整理"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"切換 DNS 檢查"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM 專用資訊/設定"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC 可用:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR 受限:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR 可用:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR 狀態:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR 頻率:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"設定無線電頻段模式"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"正在載入頻段清單…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"設定"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"手機資訊"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"流動網絡供應商佈建資料"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"觸發流動網絡供應商佈建程序"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"建議:改善 Bluetooth 連線品質"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質通知"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 1761625..a47f998 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -50,6 +50,7 @@
     <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 網路解鎖 PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"以下電信業者的 SIM 卡已鎖定"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"解除鎖定"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"關閉"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"正在要求解除網路鎖定…"</string>
@@ -123,6 +124,13 @@
     <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>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"要開啟來電等候功能嗎?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"如果通話期間有來電,系統會通知你"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"開啟"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"取消"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS 的 CDMA 來電等候功能已開啟"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS 的 CDMA 來電等候功能已關閉"</string>
     <string name="updating_title" msgid="6130548922615719689">"通話設定"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"只有管理員使用者可以變更通話設定。"</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"設定 (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -867,7 +875,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"預設資料 SIM 卡的子 ID:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"下行頻寬 (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"上行頻寬 (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"行動網路位置資訊 (已不適用):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體通道設定:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"行動網路資訊重新整理頻率:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有行動網路測量資訊:"</string>
@@ -898,6 +905,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"重新整理"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"切換 DNS 檢查"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"原始設備製造商 (OEM) 專用資訊/設定"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"EN-DC 可供使用:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"DCNR 受限:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"NR 可供使用:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"NR 狀態:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR 頻率:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"設定無線電頻帶模式"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"正在載入頻帶清單…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"設定"</string>
@@ -907,4 +919,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"手機資訊"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"電信業者佈建資訊"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"觸發電信業者佈建程序"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"建議:改善藍牙連線能力"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質通知"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 77096f3..dace3b1 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -50,6 +50,7 @@
     <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Izilungiselelo zevoyisimeyili zingashintshwa kuphela umsebenzisi oyinhloko."</string>
     <string name="puk_unlocked" msgid="4627340655215746511">"Ikhadi lakho le-SIM livuliwe. Ifoni yakho iyavula..."</string>
     <string name="label_ndp" msgid="7617392683877410341">"Inethiwekhi ye-SIM yokuvula i-PIN"</string>
+    <string name="label_phoneid" msgid="8775611434123577808">"I-SIM ivalelwe umsebenzisi"</string>
     <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Vula"</string>
     <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Cashisa"</string>
     <string name="requesting_unlock" msgid="930512210309437741">"Icela ukuvula inethiwekhi..."</string>
@@ -123,6 +124,13 @@
     <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Idlulisela ku-<xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
     <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Valiwe"</string>
     <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Isiphathi sakho asisekeli ukuvimbela ukudlulisela ucingo lapho ifoni yakho ingafinyeleleki."</string>
+    <string name="registration_cf_forbidden" msgid="4386482610771190420">"Inkampani yakho yenethiwekhi ayisekeli ukudlulisela phambili ikholi."</string>
+    <string name="cdma_call_waiting" msgid="4565070960879673216">"Vula ukulinda ikholi?"</string>
+    <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Phakathi nekholi, uzokwaziswa ngamakholi angenayo"</string>
+    <string name="enable_cdma_cw" msgid="811047045863422232">"Vula"</string>
+    <string name="disable_cdma_cw" msgid="7119290446496301734">"Hoxa"</string>
+    <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Ukulinda kwekholi ye-CDMA ngaphansi kwe-IMS kuvuliwe"</string>
+    <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Ukulinda kwekholi ye-CDMA ngaphansi kwe-IMS kuvaliwe"</string>
     <string name="updating_title" msgid="6130548922615719689">"Izilungiselelo zekholi"</string>
     <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Izilungiselelo zekholi zingaguqulwa kuphela ngumsebenzisi oyinhloko."</string>
     <string name="call_settings_with_label" msgid="8460230435361579511">"Izilungiselelo (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -869,7 +877,6 @@
     <string name="radio_info_dds" msgid="1122593144425697126">"I-SubId ye-SIM yedatha yokuzenzakalela:"</string>
     <string name="radio_info_dl_kbps" msgid="2382922659525318726">"Umkhawulokudonsa we-DL (kbps):"</string>
     <string name="radio_info_ul_kbps" msgid="2102225400904799036">"Umkhawulokudonsa we-UL (kbps):"</string>
-    <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Ulwazi lwendawo lweseli (kwehlisiwe):"</string>
     <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Ukulungiselelwa okuphathekayo kwesiteshi se-LTE:"</string>
     <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Isilinganiso sokuqalisa kabusha solwazi lweseli:"</string>
     <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Ulwazi lwesilinganiso seseli:"</string>
@@ -900,6 +907,11 @@
     <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Vuselela"</string>
     <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Guqula ukuhlola i-DNS"</string>
     <string name="oem_radio_info_label" msgid="2914167475119997456">"Ulwazi oucacile kwe-OEM/Izilungiselelo"</string>
+    <string name="radio_info_endc_available" msgid="4410653375290113436">"I-EN-DC Iyatholakala:"</string>
+    <string name="radio_info_dcnr_restricted" msgid="2469125498066960807">"Okukhawulelwe kwe-DCNR:"</string>
+    <string name="radio_info_nr_available" msgid="1321318331361249997">"I-NR Iyatholakala:"</string>
+    <string name="radio_info_nr_state" msgid="1337571996788535356">"Isimo se-NR:"</string>
+    <string name="radio_info_nr_frequency" msgid="1201156032796584128">"Imvamisa ye-NR:"</string>
     <string name="band_mode_title" msgid="7988822920724576842">"Isetha imodi yebhendi yerediyo"</string>
     <string name="band_mode_loading" msgid="795923726636735967">"Ilayisha uhlu lwebhendi…"</string>
     <string name="band_mode_set" msgid="6657819412803771421">"Setha"</string>
@@ -909,4 +921,6 @@
     <string name="phone_info_label" product="default" msgid="1784175881556791433">"Ulwazi lwefoni"</string>
     <string name="carrier_provisioning" msgid="2668065041869578376">"Ulwazi lokuhlinzeka lenkampani yenethiwekhi"</string>
     <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Cupha ukunikezwa kwenkampani yenethiwekhi"</string>
+    <string name="call_quality_notification_bluetooth_details" msgid="219073466476340435">"Isiphakamiso: Thuthukisa uxhumo lwe-Bluetooth"</string>
+    <string name="call_quality_notification_name" msgid="3476828289553948830">"Isaziso Sekhwalithi"</string>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 7e71068..7ce141e 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -211,9 +211,6 @@
     CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING does not handle it -->
     <string name="system_visual_voicemail_client" translatable="false"/>
 
-    <!-- Flag to enable VVM3 visual voicemail. VVM3 is used by Verizon Wireless. -->
-    <bool name="vvm3_enabled">false</bool>
-
     <!-- Flag indicating whether to allow pstn phone accounts [DO NOT TRANSLATE] -->
     <bool name="config_pstn_phone_accounts_enabled">true</bool>
 
@@ -299,4 +296,18 @@
         <item>250</item>
         <item>350</item>
     </integer-array>
+
+    <!-- String indicating the package name of the device GbaService implementation. -->
+    <string name="config_gba_package" translatable="false"/>
+    <!-- The interval to release/unbind GbaService after the authentication request
+        by millisecond. -1 - no release, 0 - release immediately,
+        positive n - release in n milliseconds -->
+    <integer name="config_gba_release_time">0</integer>
+
+    <!-- Whether or not to support RCS User Capability Exchange -->
+    <bool name="config_rcs_user_capability_exchange_enabled">true</bool>
+
+    <!-- Whether or not to support device to device communication using RTP and DTMF communication
+         transports. -->
+    <bool name="config_use_device_to_device_communication">false</bool>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1e44c72..1613ca8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -107,6 +107,8 @@
     <!-- network depersonalization -->
     <!-- Label text for PIN entry widget on SIM Network Depersonalization panel -->
     <string name="label_ndp">SIM network unlock PIN</string>
+    <!-- Label text for Operator displayName on SIM Network Depersonalization panel -->
+    <string name="label_phoneid">SIM locked for operator</string>
     <!-- Button label on SIM Network Depersonalization panel -->
     <string name="sim_ndp_unlock_text">Unlock</string>
     <!-- Button label on SIM Network Depersonalization panel -->
@@ -273,6 +275,15 @@
     <string name="sum_cfnrc_disabled">Off</string>
     <!-- Error message displayed after failing to disable forwarding calls when the phone is unreachable -->
     <string name="disable_cfnrc_forbidden">Your carrier doesn\'t support disabling call forwarding when your phone is unreachable.</string>
+    <string name="registration_cf_forbidden">Your carrier doesn\'t support call forwarding.</string>
+
+    <!-- Cdma Call waiting settings screen, setting option name -->
+    <string name="cdma_call_waiting">Turn on call waiting?</string>
+    <string name="enable_cdma_call_waiting_setting">During a call, you\'ll be notified about incoming calls</string>
+    <string name="enable_cdma_cw">Turn on</string>
+    <string name="disable_cdma_cw">Cancel</string>
+    <string name="cdma_call_waiting_in_ims_on">CDMA Call Waiting under IMS On</string>
+    <string name="cdma_call_waiting_in_ims_off">CDMA Call Waiting under IMS Off</string>
 
     <!-- Title of the progress dialog displayed while updating Call settings -->
     <string name="updating_title">Call settings</string>
@@ -2068,8 +2079,6 @@
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_ul_kbps">UL Bandwidth (kbps):</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
-    <string name="radio_info_signal_location_label">Cell Location Info (deprecated):</string>
-    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_phy_chan_config">LTE Physical Channel Configuration:</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_cell_info_refresh_rate">Cell Info Refresh Rate:</string>
@@ -2131,6 +2140,16 @@
     <string name="radio_info_toggle_dns_check_label">Toggle DNS Check</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="oem_radio_info_label">OEM-specific Info/Settings</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_endc_available">EN-DC Available:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_dcnr_restricted">DCNR Restricted:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_available">NR Available:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_state">NR State:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_frequency">NR Frequency:</string>
 
     <!-- Band Mode Selection -->
     <!-- Band mode screen.  Title of activity. -->
@@ -2154,4 +2173,11 @@
     <!-- Trigger Carrier Provisioning [CHAR LIMIT=NONE] -->
     <string name="trigger_carrier_provisioning">Trigger Carrier Provisioning</string>
 
+    <!-- details of the message popped up when there is
+    bad call quality caused by bluetooth connection-->
+    <string name="call_quality_notification_bluetooth_details">
+        Suggestion: Improve Bluetooth connectivity</string>
+    <!-- name of the notification that pops up during
+    a phone call when there is bad call quality -->
+    <string name="call_quality_notification_name">Call Quality Notification</string>
 </resources>
diff --git a/res/xml/cdma_call_privacy.xml b/res/xml/cdma_call_privacy.xml
index 1aeeefe..a16a504 100644
--- a/res/xml/cdma_call_privacy.xml
+++ b/res/xml/cdma_call_privacy.xml
@@ -7,4 +7,14 @@
         android:title="@string/voice_privacy"
         android:persistent="false"
         android:summary="@string/voice_privacy_summary"/>
+
+    <PreferenceScreen
+        android:key="call_forwarding_key"
+        android:title="@string/labelCF"
+        android:persistent="false" />
+
+    <com.android.phone.CdmaCallWaitingPreference
+        android:key="call_waiting_key"
+        android:title="@string/labelCW"
+        android:persistent="false" />
 </PreferenceScreen>
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index 5c7409f..a5793d0 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -63,7 +63,9 @@
         Intent intent = new Intent(context, SipIncomingCallReceiver.class);
         intent.setAction(SipManager.ACTION_SIP_INCOMING_CALL);
         intent.putExtra(EXTRA_PHONE_ACCOUNT, SipUtil.createAccountHandle(context, sipProfileName));
-        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+        return PendingIntent.getBroadcast(context, 0, intent,
+                // Mutable because information associated with the call is passed back here.
+                PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
     public static boolean isPhoneIdle(Context context) {
diff --git a/src/com/android/phone/CallBarringEditPreference.java b/src/com/android/phone/CallBarringEditPreference.java
index b8e3250..757600e 100644
--- a/src/com/android/phone/CallBarringEditPreference.java
+++ b/src/com/android/phone/CallBarringEditPreference.java
@@ -26,6 +26,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
 import android.text.method.DigitsKeyListener;
 import android.text.method.PasswordTransformationMethod;
 import android.util.AttributeSet;
@@ -35,7 +37,6 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
@@ -109,7 +110,7 @@
         if (!skipReading) {
             // Query call barring status
             mPhone.getCallBarring(mFacility, "", mHandler.obtainMessage(
-                    MyHandler.MESSAGE_GET_CALL_BARRING), CommandsInterface.SERVICE_CLASS_VOICE);
+                    MyHandler.MESSAGE_GET_CALL_BARRING), getServiceClassForCallBarring(mPhone));
             if (mTcpListener != null) {
                 mTcpListener.onStarted(this, true);
             }
@@ -204,7 +205,7 @@
             // Send set call barring message to RIL layer.
             mPhone.setCallBarring(mFacility, !mIsActivated, password,
                     mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_BARRING),
-                    CommandsInterface.SERVICE_CLASS_VOICE);
+                    getServiceClassForCallBarring(mPhone));
             if (mTcpListener != null) {
                 mTcpListener.onStarted(this, false);
             }
@@ -218,6 +219,18 @@
         }
     }
 
+    private static int getServiceClassForCallBarring(Phone phone) {
+        int serviceClass = CarrierConfigManager.SERVICE_CLASS_VOICE;
+        PersistableBundle carrierConfig = PhoneGlobals.getInstance()
+                .getCarrierConfigForSubId(phone.getSubId());
+        if (carrierConfig != null) {
+            serviceClass = carrierConfig.getInt(
+                    CarrierConfigManager.KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT,
+                    CarrierConfigManager.SERVICE_CLASS_VOICE);
+        }
+        return serviceClass;
+    }
+
     void updateSummaryText() {
         notifyChanged();
         notifyDependencyChange(shouldDisableDependents());
@@ -327,8 +340,7 @@
                     pref.mFacility,
                     "",
                     obtainMessage(MESSAGE_GET_CALL_BARRING, 0, MESSAGE_SET_CALL_BARRING,
-                            ar.exception),
-                    CommandsInterface.SERVICE_CLASS_VOICE);
+                            ar.exception), getServiceClassForCallBarring(pref.mPhone));
         }
     }
 }
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 54acaad..2fcc2ee 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -30,6 +30,9 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.os.PersistableBundle;
 import android.os.UserManager;
 import android.preference.Preference;
@@ -103,6 +106,7 @@
     private ImsManager mImsMgr;
     private SubscriptionInfoHelper mSubscriptionInfoHelper;
     private TelecomManager mTelecomManager;
+    private PhoneStateListener mPhoneStateListener;
 
     private SwitchPreference mButtonAutoRetry;
     private PreferenceScreen mVoicemailSettingsScreen;
@@ -263,6 +267,7 @@
         mSubscriptionInfoHelper.setActionBarTitle(
                 getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
         mTelecomManager = getSystemService(TelecomManager.class);
+        mPhoneStateListener = new CallFeaturesPhoneStateListener();
     }
 
     private void updateImsManager(Phone phone) {
@@ -279,11 +284,16 @@
     private void listenPhoneState(boolean listen) {
         TelephonyManager telephonyManager = getSystemService(TelephonyManager.class)
                 .createForSubscriptionId(mPhone.getSubId());
-        telephonyManager.listen(mPhoneStateListener, listen
-                ? PhoneStateListener.LISTEN_CALL_STATE : PhoneStateListener.LISTEN_NONE);
+        if (listen) {
+            telephonyManager.registerPhoneStateListener(
+                    new HandlerExecutor(new Handler(Looper.getMainLooper())), mPhoneStateListener);
+        } else {
+            telephonyManager.unregisterPhoneStateListener(mPhoneStateListener);
+        }
     }
 
-    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+    private final class CallFeaturesPhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.CallStateChangedListener {
         @Override
         public void onCallStateChanged(int state, String incomingNumber) {
             if (DBG) log("PhoneStateListener onCallStateChanged: state is " + state);
@@ -295,7 +305,7 @@
                 mButtonWifiCalling.setEnabled(isCallStateIdle);
             }
         }
-    };
+    }
 
     private final ProvisioningManager.Callback mProvisioningCallback =
             new ProvisioningManager.Callback() {
@@ -397,14 +407,10 @@
             } else {
                 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                     prefSet.removePreference(fdnButton);
-
-                    if (!carrierConfig.getBoolean(
-                            CarrierConfigManager.KEY_VOICE_PRIVACY_DISABLE_UI_BOOL)) {
-                        addPreferencesFromResource(R.xml.cdma_call_privacy);
-                        CdmaVoicePrivacySwitchPreference buttonVoicePrivacy =
-                                (CdmaVoicePrivacySwitchPreference) findPreference(BUTTON_VP_KEY);
-                        buttonVoicePrivacy.setPhone(mPhone);
-                    }
+                    addPreferencesFromResource(R.xml.cdma_call_privacy);
+                    CdmaVoicePrivacySwitchPreference buttonVoicePrivacy =
+                            (CdmaVoicePrivacySwitchPreference) findPreference(BUTTON_VP_KEY);
+                    buttonVoicePrivacy.setPhone(mPhone);
                 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                     if (mPhone.getIccCard() == null || !mPhone.getIccCard().getIccFdnAvailable()) {
                         prefSet.removePreference(fdnButton);
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index e8cf0d1..bf296f9 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -122,7 +122,27 @@
         Log.d(LOG_TAG, "mButtonClicked=" + mButtonClicked + ", positiveResult=" + positiveResult);
         // Ignore this event if the user clicked the cancel button, or if the dialog is dismissed
         // without any button being pressed (back button press or click event outside the dialog).
-        if (this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
+        if (isUnknownStatus() && this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
+            int action = (mButtonClicked == DialogInterface.BUTTON_POSITIVE) ?
+                CommandsInterface.CF_ACTION_REGISTRATION :
+                CommandsInterface.CF_ACTION_DISABLE;
+            final String number = (action == CommandsInterface.CF_ACTION_DISABLE) ?
+                    "" : getPhoneNumber();
+
+            Log.d(LOG_TAG, "reason=" + reason + ", action=" + action + ", number=" + number);
+
+            // Display no forwarding number while we're waiting for confirmation.
+            setSummaryOff("");
+
+            mPhone.setCallForwardingOption(action,
+                    reason,
+                    number,
+                    mServiceClass,
+                    0,
+                    mHandler.obtainMessage(MyHandler.MESSAGE_SET_CF,
+                        action,
+                        MyHandler.MESSAGE_SET_CF));
+        } else if (this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
             int action = (isToggled() || (mButtonClicked == DialogInterface.BUTTON_POSITIVE)) ?
                     CommandsInterface.CF_ACTION_REGISTRATION :
                     CommandsInterface.CF_ACTION_DISABLE;
@@ -194,6 +214,7 @@
             Log.i(LOG_TAG, "handleGetCFResponse: Overridding CF number");
         }
 
+        setUnknownStatus(callForwardInfo.status == CommandsInterface.SS_STATUS_UNKNOWN);
         setToggled(callForwardInfo.status == 1);
         boolean displayVoicemailNumber = false;
         if (TextUtils.isEmpty(callForwardInfo.number)) {
@@ -343,6 +364,7 @@
             AsyncResult ar = (AsyncResult) msg.obj;
 
             callForwardInfo = null;
+            boolean summaryOff = false;
             if (ar.exception != null) {
                 Log.d(LOG_TAG, "handleGetCFResponse: ar.exception=" + ar.exception);
                 if (ar.exception instanceof CommandException) {
@@ -362,7 +384,9 @@
                 CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
                 if (cfInfoArray == null || cfInfoArray.length == 0) {
                     Log.d(LOG_TAG, "handleGetCFResponse: cfInfoArray.length==0");
-                    mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
+                    if (!(ar.userObj instanceof Throwable)) {
+                        mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
+                    }
                 } else {
                     for (int i = 0, length = cfInfoArray.length; i < length; i++) {
                         Log.d(LOG_TAG, "handleGetCFResponse, cfInfoArray[" + i + "]="
@@ -372,6 +396,8 @@
                             CallForwardInfo info = cfInfoArray[i];
                             handleCallForwardResult(info);
 
+                            summaryOff = (info.status == CommandsInterface.SS_STATUS_UNKNOWN);
+
                             if (ar.userObj instanceof Throwable) {
                                 Log.d(LOG_TAG, "Skipped duplicated error dialog");
                                 continue;
@@ -379,8 +405,7 @@
 
                             // Show an alert if we got a success response but
                             // with unexpected values.
-                            // Currently only handle the fail-to-disable case
-                            // since we haven't observed fail-to-enable.
+                            // Handle the fail-to-disable case.
                             if (msg.arg2 == MESSAGE_SET_CF &&
                                     msg.arg1 == CommandsInterface.CF_ACTION_DISABLE &&
                                     info.status == 1) {
@@ -404,7 +429,21 @@
                                 }
                                 AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                                 builder.setNeutralButton(R.string.close_dialog, null);
-                                builder.setTitle(getContext().getText(R.string.error_updating_title));
+                                builder.setTitle(getContext()
+                                        .getText(R.string.error_updating_title));
+                                builder.setMessage(s);
+                                builder.setCancelable(true);
+                                builder.create().show();
+                            } else if (msg.arg2 == MESSAGE_SET_CF &&
+                                    msg.arg1 == CommandsInterface.CF_ACTION_REGISTRATION &&
+                                    info.status == 0) {
+                                // Handle the fail-to-enable case.
+                                CharSequence s = getContext()
+                                    .getText(R.string.registration_cf_forbidden);
+                                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+                                builder.setNeutralButton(R.string.close_dialog, null);
+                                builder.setTitle(getContext()
+                                        .getText(R.string.error_updating_title));
                                 builder.setMessage(s);
                                 builder.setCancelable(true);
                                 builder.create().show();
@@ -417,7 +456,15 @@
             // Now whether or not we got a new number, reset our enabled
             // summary text since it may have been replaced by an empty
             // placeholder.
-            updateSummaryText();
+            // for CDMA, doesn't display summary.
+            if (summaryOff) {
+                setSummaryOff("");
+            } else {
+                // Now whether or not we got a new number, reset our enabled
+                // summary text since it may have been replaced by an empty
+                // placeholder.
+                updateSummaryText();
+            }
         }
 
         private void handleSetCFResponse(Message msg) {
@@ -426,6 +473,16 @@
                 Log.d(LOG_TAG, "handleSetCFResponse: ar.exception=" + ar.exception);
                 // setEnabled(false);
             }
+
+            if (ar.result != null) {
+                int arr = (int)ar.result;
+                if (arr == CommandsInterface.SS_STATUS_UNKNOWN) {
+                    Log.d(LOG_TAG, "handleSetCFResponse: no need to re get in CDMA");
+                    mTcpListener.onFinished(CallForwardEditPreference.this, false);
+                    return;
+                }
+            }
+
             Log.d(LOG_TAG, "handleSetCFResponse: re get");
             if (!mCallForwardByUssd) {
                 mPhone.getCallForwardingOption(reason, mServiceClass,
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 6c18623..4c38d98 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -25,6 +25,7 @@
 import android.media.ToneGenerator;
 import android.os.AsyncResult;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Message;
 import android.os.SystemProperties;
 import android.telecom.TelecomManager;
@@ -583,9 +584,8 @@
                 mApplication.notificationMgr.updateMwi(subId, false);
                 mApplication.notificationMgr.updateCfi(subId, false);
 
-                // Listening to LISTEN_NONE removes the listener.
-                mTelephonyManager.listen(
-                        mPhoneStateListeners.get(subId), PhoneStateListener.LISTEN_NONE);
+                // Unregister the listener.
+                mTelephonyManager.unregisterPhoneStateListener(mPhoneStateListeners.get(subId));
                 mPhoneStateListeners.remove(subId);
             } else {
                 Log.d(LOG_TAG, "updatePhoneStateListeners: update CF notifications.");
@@ -618,9 +618,8 @@
             int subId = subInfos.get(i).getSubscriptionId();
             if (!mPhoneStateListeners.containsKey(subId)) {
                 CallNotifierPhoneStateListener listener = new CallNotifierPhoneStateListener(subId);
-                mTelephonyManager.createForSubscriptionId(subId).listen(listener,
-                        PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
-                        | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
+                mTelephonyManager.createForSubscriptionId(subId).registerPhoneStateListener(
+                        new HandlerExecutor(this), listener);
                 mPhoneStateListeners.put(subId, listener);
             }
         }
@@ -768,7 +767,10 @@
                 }
             };
 
-    private class CallNotifierPhoneStateListener extends PhoneStateListener {
+    private class CallNotifierPhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.MessageWaitingIndicatorChangedListener,
+            PhoneStateListener.CallForwardingIndicatorChangedListener {
+
         private final int mSubId;
 
         CallNotifierPhoneStateListener(int subId) {
@@ -790,7 +792,7 @@
             mCFIStatus.put(this.mSubId, visible);
             updatePhoneStateListeners(false, UPDATE_TYPE_CFI, this.mSubId);
         }
-    };
+    }
 
     private void log(String msg) {
         Log.d(LOG_TAG, msg);
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 866e481..37a0618 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -99,10 +99,16 @@
     private PersistableBundle[] mPersistentOverrideConfigs;
     // Carrier configs that are provided via the override test API, indexed by phone ID.
     private PersistableBundle[] mOverrideConfigs;
+    // Carrier configs to override code default when there is no SIM inserted
+    private PersistableBundle mNoSimConfig;
     // Service connection for binding to config app.
     private CarrierServiceConnection[] mServiceConnection;
+    // Service connection for binding to carrier config app for no SIM config.
+    private CarrierServiceConnection[] mServiceConnectionForNoSimConfig;
     // Whether we are bound to a service for each phone
     private boolean[] mServiceBound;
+    // Whether we are bound to a service for no SIM config
+    private boolean[] mServiceBoundForNoSimConfig;
     // Whether we have sent config change broadcast for each phone id.
     private boolean[] mHasSentConfigChange;
     // Whether the broadcast was sent from EVENT_SYSTEM_UNLOCKED, to track rebroadcasts
@@ -150,6 +156,16 @@
     private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16;
     // Multi-SIM config changed.
     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 17;
+    // Attempt to fetch from default app or read from XML for no SIM case.
+    private static final int EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG = 18;
+    // No SIM config has been loaded from default app (or cache).
+    private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE = 19;
+    // Has connected to default app for no SIM config.
+    private static final int EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG = 20;
+    // Bind timed out for the default app when trying to fetch no SIM config.
+    private static final int EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 21;
+    // Fetching config timed out from the default app for no SIM config.
+    private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 22;
 
     private static final int BIND_TIMEOUT_MILLIS = 30000;
 
@@ -505,6 +521,118 @@
                 case EVENT_MULTI_SIM_CONFIG_CHANGED:
                     onMultiSimConfigChanged();
                     break;
+
+                case EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG: {
+                    PersistableBundle config =
+                            restoreNoSimConfigFromXml(mPlatformCarrierConfigPackage);
+
+                    if (config != null) {
+                        logd("Loaded no SIM config from XML. package="
+                                + mPlatformCarrierConfigPackage);
+                        mNoSimConfig = config;
+                        sendMessage(
+                                obtainMessage(
+                                        EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE,
+                                            phoneId, -1));
+                    } else {
+                        // No cached config, so fetch it from the default app.
+                        if (bindToConfigPackage(
+                                mPlatformCarrierConfigPackage,
+                                phoneId,
+                                EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG)) {
+                            sendMessageDelayed(
+                                    obtainMessage(
+                                            EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT,
+                                                phoneId, -1), BIND_TIMEOUT_MILLIS);
+                        } else {
+                            broadcastConfigChangedIntent(phoneId, false);
+                            // TODO: We *must* call unbindService even if bindService returns false.
+                            // (And possibly if SecurityException was thrown.)
+                            loge("binding to default app to fetch no SIM config: "
+                                    + mPlatformCarrierConfigPackage + " fails");
+                        }
+                    }
+                    break;
+                }
+
+                case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE: {
+                    broadcastConfigChangedIntent(phoneId, false);
+                    break;
+                }
+
+                case EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT:
+                case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: {
+                    loge("Bind/fetch time out for no SIM config from "
+                            + mPlatformCarrierConfigPackage);
+                    removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT);
+                    // If we attempted to bind to the app, but the service connection is null due to
+                    // the race condition that clear config event happens before bind/fetch complete
+                    // then config was cleared while we were waiting and we should not continue.
+                    if (mServiceConnectionForNoSimConfig[phoneId] != null) {
+                        // If a ResponseReceiver callback is in the queue when this happens, we will
+                        // unbind twice and throw an exception.
+                        unbindIfBoundForNoSimConfig(mContext,
+                                mServiceConnectionForNoSimConfig[phoneId], phoneId);
+                    }
+                    broadcastConfigChangedIntent(phoneId, false);
+                    break;
+                }
+
+                case EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG: {
+                    removeMessages(EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT);
+                    final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj;
+                    // If new service connection has been created, unbind.
+                    if (mServiceConnectionForNoSimConfig[phoneId] != conn || conn.service == null) {
+                        unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                        break;
+                    }
+
+                    // ResultReceiver callback will execute in this Handler's thread.
+                    final ResultReceiver resultReceiver =
+                            new ResultReceiver(this) {
+                                @Override
+                                public void onReceiveResult(int resultCode, Bundle resultData) {
+                                    unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                                    // If new service connection has been created, this is stale.
+                                    if (mServiceConnectionForNoSimConfig[phoneId] != conn) {
+                                        loge("Received response for stale request.");
+                                        return;
+                                    }
+                                    removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT);
+                                    if (resultCode == RESULT_ERROR || resultData == null) {
+                                        // On error, abort config fetching.
+                                        loge("Failed to get no SIM carrier config");
+                                        return;
+                                    }
+                                    PersistableBundle config =
+                                            resultData.getParcelable(KEY_CONFIG_BUNDLE);
+                                    saveNoSimConfigToXml(mPlatformCarrierConfigPackage, config);
+                                    mNoSimConfig = config;
+                                    sendMessage(
+                                            obtainMessage(
+                                                    EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE,
+                                                        phoneId, -1));
+                                }
+                            };
+                    // Now fetch the config asynchronously from the ICarrierService.
+                    try {
+                        ICarrierService carrierService =
+                                ICarrierService.Stub.asInterface(conn.service);
+                        carrierService.getCarrierConfig(null, resultReceiver);
+                        logdWithLocalLog("Fetch no sim config from default app: "
+                                + mPlatformCarrierConfigPackage);
+                    } catch (RemoteException e) {
+                        loge("Failed to get no sim carrier config from default app: " +
+                                mPlatformCarrierConfigPackage + " err: " + e.toString());
+                        unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                        break; // So we don't set a timeout.
+                    }
+                    sendMessageDelayed(
+                            obtainMessage(
+                                    EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT,
+                                        phoneId, -1), BIND_TIMEOUT_MILLIS);
+                    break;
+                }
             }
         }
     }
@@ -539,10 +667,13 @@
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
         mPersistentOverrideConfigs = new PersistableBundle[numPhones];
         mOverrideConfigs = new PersistableBundle[numPhones];
+        mNoSimConfig = new PersistableBundle();
         mServiceConnection = new CarrierServiceConnection[numPhones];
         mServiceBound = new boolean[numPhones];
         mHasSentConfigChange = new boolean[numPhones];
         mFromSystemUnlocked = new boolean[numPhones];
+        mServiceConnectionForNoSimConfig = new CarrierServiceConnection[numPhones];
+        mServiceBoundForNoSimConfig = new boolean[numPhones];
         // Make this service available through ServiceManager.
         TelephonyFrameworkInitializer
                 .getTelephonyServiceManager().getCarrierConfigServiceRegisterer().register(this);
@@ -568,7 +699,7 @@
         }
     }
 
-    private void clearConfigForPhone(int phoneId, boolean sendBroadcast) {
+    private void clearConfigForPhone(int phoneId, boolean fetchNoSimConfig) {
         /* Ignore clear configuration request if device is being shutdown. */
         Phone phone = PhoneFactory.getPhone(phoneId);
         if (phone != null) {
@@ -582,7 +713,12 @@
         mServiceConnection[phoneId] = null;
         mHasSentConfigChange[phoneId] = false;
 
-        if (sendBroadcast) broadcastConfigChangedIntent(phoneId, false);
+        if (fetchNoSimConfig) {
+            // To fetch no SIM config
+            mHandler.sendMessage(
+                    mHandler.obtainMessage(
+                            EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG, phoneId, -1));
+        }
     }
 
     private void notifySubscriptionInfoUpdater(int phoneId) {
@@ -661,11 +797,21 @@
         logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId);
         Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
         carrierService.setPackage(pkgName);
-        mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, pkgName, eventId);
+        CarrierServiceConnection serviceConnection =  new CarrierServiceConnection(
+                phoneId, pkgName, eventId);
+        if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) {
+            mServiceConnectionForNoSimConfig[phoneId] = serviceConnection;
+        } else {
+            mServiceConnection[phoneId] = serviceConnection;
+        }
         try {
-            if (mContext.bindService(carrierService, mServiceConnection[phoneId],
+            if (mContext.bindService(carrierService, serviceConnection,
                     Context.BIND_AUTO_CREATE)) {
-                mServiceBound[phoneId] = true;
+                if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) {
+                    mServiceBoundForNoSimConfig[phoneId] = true;
+                } else {
+                    mServiceBound[phoneId] = true;
+                }
                 return true;
             } else {
                 return false;
@@ -767,26 +913,39 @@
      *
      * In case of errors or invalid input, no file will be written.
      *
-     * @param packageName the name of the package from which we fetched this bundle.
-     * @param extraString An extra string to be used in the XML file name.
-     * @param phoneId     the phone ID.
-     * @param carrierId   contains all carrier-identifying information.
-     * @param config      the bundle to be written. Null will be treated as an empty bundle.
+     * @param packageName   the name of the package from which we fetched this bundle.
+     * @param extraString   An extra string to be used in the XML file name.
+     * @param phoneId       the phone ID.
+     * @param carrierId     contains all carrier-identifying information.
+     * @param config        the bundle to be written. Null will be treated as an empty bundle.
+     * @param isNoSimConfig whether this is invoked for noSimConfig or not.
      */
     private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
-            CarrierIdentifier carrierId, PersistableBundle config) {
-        if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
-                != TelephonyManager.SIM_STATE_LOADED) {
-            loge("Skip save config because SIM records are not loaded.");
+            CarrierIdentifier carrierId, PersistableBundle config, boolean isNoSimConfig) {
+        if (packageName == null) {
+            loge("Cannot save config with null packageName");
             return;
         }
 
-        final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = carrierId.getSpecificCarrierId();
-        if (packageName == null || iccid == null) {
-            loge("Cannot save config with null packageName or iccid.");
-            return;
+        String fileName;
+        if (isNoSimConfig) {
+            fileName = getFilenameForNoSimConfig(packageName);
+        } else {
+            if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+                    != TelephonyManager.SIM_STATE_LOADED) {
+                loge("Skip save config because SIM records are not loaded.");
+                return;
+            }
+
+            final String iccid = getIccIdForPhoneId(phoneId);
+            final int cid = carrierId.getSpecificCarrierId();
+            if (iccid == null) {
+                loge("Cannot save config with null iccid.");
+                return;
+            }
+            fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
         }
+
         // b/32668103 Only save to file if config isn't empty.
         // In case of failure, not caching an empty bundle will
         // try loading config again on next power on or sim loaded.
@@ -807,9 +966,7 @@
 
         FileOutputStream outFile = null;
         try {
-            outFile = new FileOutputStream(
-                    new File(mContext.getFilesDir(),
-                            getFilenameForConfig(packageName, extraString, iccid, cid)));
+            outFile = new FileOutputStream(new File(mContext.getFilesDir(), fileName));
             config.putString(KEY_VERSION, version);
             config.writeToStream(outFile);
             outFile.flush();
@@ -819,6 +976,15 @@
         }
     }
 
+    private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
+            CarrierIdentifier carrierId, PersistableBundle config) {
+        saveConfigToXml(packageName, extraString, phoneId, carrierId, config, false);
+    }
+
+    private void saveNoSimConfigToXml(String packageName, PersistableBundle config) {
+        saveConfigToXml(packageName, "", -1, null, config, true);
+    }
+
     /**
      * Reads a bundle from an XML file.
      *
@@ -828,38 +994,48 @@
      * In case of errors, or if the saved config is from a different package version than the
      * current version, then null will be returned.
      *
-     * @param packageName the name of the package from which we fetched this bundle.
-     * @param extraString An extra string to be used in the XML file name.
-     * @param phoneId     the phone ID.
+     * @param packageName    the name of the package from which we fetched this bundle.
+     * @param extraString    An extra string to be used in the XML file name.
+     * @param phoneId        the phone ID.
+     * @param isNoSimConfig  whether this is invoked for noSimConfig or not.
      * @return the bundle from the XML file. Returns null if there is no saved config, the saved
      * version does not match, or reading config fails.
      */
     private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
-            int phoneId) {
+            int phoneId, boolean isNoSimConfig) {
+        if (packageName == null) {
+            loge("Cannot restore config with null packageName");
+        }
         final String version = getPackageVersion(packageName);
         if (version == null) {
             loge("Failed to get package version for: " + packageName);
             return null;
         }
-        if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
-                != TelephonyManager.SIM_STATE_LOADED) {
-            loge("Skip restoring config because SIM records are not yet loaded.");
-            return null;
-        }
 
-        final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = getSpecificCarrierIdForPhoneId(phoneId);
-        if (packageName == null || iccid == null) {
-            loge("Cannot restore config with null packageName or iccid.");
-            return null;
+        String fileName;
+        if (isNoSimConfig) {
+            fileName = getFilenameForNoSimConfig(packageName);
+        } else {
+            if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+                    != TelephonyManager.SIM_STATE_LOADED) {
+                loge("Skip restore config because SIM records are not loaded.");
+                return null;
+            }
+
+            final String iccid = getIccIdForPhoneId(phoneId);
+            final int cid = getSpecificCarrierIdForPhoneId(phoneId);
+            if (iccid == null) {
+                loge("Cannot restore config with null iccid.");
+                return null;
+            }
+            fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
         }
 
         PersistableBundle restoredBundle = null;
         File file = null;
         FileInputStream inFile = null;
         try {
-            file = new File(mContext.getFilesDir(),
-                    getFilenameForConfig(packageName, extraString, iccid, cid));
+            file = new File(mContext.getFilesDir(),fileName);
             inFile = new FileInputStream(file);
 
             restoredBundle = PersistableBundle.readFromStream(inFile);
@@ -883,6 +1059,15 @@
         return restoredBundle;
     }
 
+    private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
+            int phoneId) {
+        return restoreConfigFromXml(packageName, extraString, phoneId, false);
+    }
+
+    private PersistableBundle restoreNoSimConfigFromXml(String packageName) {
+        return restoreConfigFromXml(packageName, "", -1, true);
+    }
+
     /**
      * Clears cached carrier config.
      * This deletes all saved XML files associated with the given package name. If packageName is
@@ -912,7 +1097,8 @@
     }
 
     /** Builds a canonical file name for a config file. */
-    private String getFilenameForConfig(@NonNull String packageName, @NonNull String extraString,
+    private static String getFilenameForConfig(
+            @NonNull String packageName, @NonNull String extraString,
             @NonNull String iccid, int cid) {
         // the same carrier should have a single copy of XML file named after carrier id.
         // However, it's still possible that platform doesn't recognize the current sim carrier,
@@ -921,6 +1107,11 @@
         return "carrierconfig-" + packageName + extraString + "-" + iccid + "-" + cid + ".xml";
     }
 
+    /** Builds a canonical file name for no SIM config file. */
+    private String getFilenameForNoSimConfig(@NonNull String packageName) {
+        return "carrierconfig-" + packageName + "-" + "nosim" + ".xml";
+    }
+
     /** Return the current version code of a package, or null if the name is not found. */
     private String getPackageVersion(String packageName) {
         try {
@@ -995,6 +1186,10 @@
             if (config != null) {
                 retConfig.putAll(config);
             }
+        } else {
+            if (mNoSimConfig != null) {
+                retConfig.putAll(mNoSimConfig);
+            }
         }
         return retConfig;
     }
@@ -1104,6 +1299,14 @@
         }
     }
 
+    private void unbindIfBoundForNoSimConfig(Context context, CarrierServiceConnection conn,
+            int phoneId) {
+        if (mServiceBoundForNoSimConfig[phoneId]) {
+            mServiceBoundForNoSimConfig[phoneId] = false;
+            context.unbindService(conn);
+        }
+    }
+
     /**
      * If {@code args} contains {@link #DUMP_ARG_REQUESTING_PACKAGE} and a following package name,
      * we'll also call {@link IBinder#dump} on the default carrier service (if bound) and the
@@ -1144,6 +1347,7 @@
             printConfig(mOverrideConfigs[i], indentPW, "mOverrideConfigs");
         }
 
+        printConfig(mNoSimConfig, indentPW, "mNoSimConfig");
         indentPW.println("CarrierConfigLoadingLog=");
         mCarrierConfigLoadingLog.dump(fd, indentPW, args);
 
diff --git a/src/com/android/phone/CdmaCallForwardOptions.java b/src/com/android/phone/CdmaCallForwardOptions.java
new file mode 100644
index 0000000..a8d2e93
--- /dev/null
+++ b/src/com/android/phone/CdmaCallForwardOptions.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.app.ActionBar;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.util.Log;
+import android.view.MenuItem;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+
+import java.util.ArrayList;
+
+public class CdmaCallForwardOptions extends TimeConsumingPreferenceActivity {
+    private static final String LOG_TAG = "CdmaCallForwardOptions";
+
+    private static final String NUM_PROJECTION[] = {
+        android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER
+    };
+
+    private static final String BUTTON_CFU_KEY   = "button_cfu_key";
+    private static final String BUTTON_CFB_KEY   = "button_cfb_key";
+    private static final String BUTTON_CFNRY_KEY = "button_cfnry_key";
+    private static final String BUTTON_CFNRC_KEY = "button_cfnrc_key";
+
+    private static final String KEY_TOGGLE = "toggle";
+    private static final String KEY_STATUS = "status";
+    private static final String KEY_NUMBER = "number";
+    private static final String KEY_ENABLE = "enable";
+
+    private CallForwardEditPreference mButtonCFU;
+    private CallForwardEditPreference mButtonCFB;
+    private CallForwardEditPreference mButtonCFNRy;
+    private CallForwardEditPreference mButtonCFNRc;
+
+    private final ArrayList<CallForwardEditPreference> mPreferences =
+            new ArrayList<CallForwardEditPreference> ();
+    private int mInitIndex= 0;
+
+    private boolean mFirstResume;
+    private Bundle mIcicle;
+    private Phone mPhone;
+    private SubscriptionInfoHelper mSubscriptionInfoHelper;
+    private boolean mReplaceInvalidCFNumbers;
+    private boolean mCallForwardByUssd;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        addPreferencesFromResource(R.xml.callforward_options);
+
+        mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
+        mSubscriptionInfoHelper.setActionBarTitle(
+                getActionBar(), getResources(), R.string.call_forwarding_settings_with_label);
+        mPhone = mSubscriptionInfoHelper.getPhone();
+
+        PersistableBundle b = null;
+        boolean supportCFNRc = true;
+        if (mSubscriptionInfoHelper.hasSubId()) {
+            b = PhoneGlobals.getInstance().getCarrierConfigForSubId(
+                    mSubscriptionInfoHelper.getSubId());
+        } else {
+            b = PhoneGlobals.getInstance().getCarrierConfig();
+        }
+        if (b != null) {
+            mReplaceInvalidCFNumbers = b.getBoolean(
+                    CarrierConfigManager.KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL);
+            mCallForwardByUssd = b.getBoolean(
+                    CarrierConfigManager.KEY_USE_CALL_FORWARDING_USSD_BOOL);
+            supportCFNRc = b.getBoolean(
+                    CarrierConfigManager.KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL);
+        }
+
+        PreferenceScreen prefSet = getPreferenceScreen();
+        mButtonCFU = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFU_KEY);
+        mButtonCFB = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFB_KEY);
+        mButtonCFNRy = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFNRY_KEY);
+        mButtonCFNRc = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFNRC_KEY);
+
+        mButtonCFU.setParentActivity(this, mButtonCFU.reason);
+        mButtonCFB.setParentActivity(this, mButtonCFB.reason);
+        mButtonCFNRy.setParentActivity(this, mButtonCFNRy.reason);
+        mButtonCFNRc.setParentActivity(this, mButtonCFNRc.reason);
+
+        mPreferences.add(mButtonCFU);
+        mPreferences.add(mButtonCFB);
+        mPreferences.add(mButtonCFNRy);
+
+        if (supportCFNRc) {
+            mPreferences.add(mButtonCFNRc);
+        } else {
+            // When CFNRc is not supported, mButtonCFNRc is grayed out from the menu.
+            // Default state for the preferences in this PreferenceScreen is disabled.
+            // Only preferences listed in the ArrayList mPreferences will be enabled.
+            // By not adding mButtonCFNRc to mPreferences it will be kept disabled.
+            Log.d(LOG_TAG, "onCreate: CFNRc is not supported, grey out the item.");
+        }
+
+        if (mCallForwardByUssd) {
+            //the call forwarding ussd command's behavior is similar to the call forwarding when
+            //unanswered,so only display the call forwarding when unanswered item.
+            prefSet.removePreference(mButtonCFU);
+            prefSet.removePreference(mButtonCFB);
+            prefSet.removePreference(mButtonCFNRc);
+            mPreferences.remove(mButtonCFU);
+            mPreferences.remove(mButtonCFB);
+            mPreferences.remove(mButtonCFNRc);
+            mButtonCFNRy.setDependency(null);
+        }
+
+        // we wait to do the initialization until onResume so that the
+        // TimeConsumingPreferenceActivity dialog can display as it
+        // relies on onResume / onPause to maintain its foreground state.
+
+        mFirstResume = true;
+        mIcicle = icicle;
+
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            // android.R.id.home will be triggered in onOptionsItemSelected()
+            actionBar.setDisplayHomeAsUpEnabled(true);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        if (mFirstResume) {
+            if (mIcicle == null) {
+                Log.d(LOG_TAG, "start to init ");
+                CallForwardEditPreference pref = mPreferences.get(mInitIndex);
+                pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd);
+                pref.startCallForwardOptionsQuery();
+
+            } else {
+                mInitIndex = mPreferences.size();
+
+                for (CallForwardEditPreference pref : mPreferences) {
+                    Bundle bundle = mIcicle.getParcelable(pref.getKey());
+                    pref.setToggled(bundle.getBoolean(KEY_TOGGLE));
+                    pref.setEnabled(bundle.getBoolean(KEY_ENABLE));
+                    CallForwardInfo cf = new CallForwardInfo();
+                    cf.number = bundle.getString(KEY_NUMBER);
+                    cf.status = bundle.getInt(KEY_STATUS);
+                    pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd);
+                    pref.restoreCallForwardInfo(cf);
+                }
+            }
+            mFirstResume = false;
+            mIcicle = null;
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        for (CallForwardEditPreference pref : mPreferences) {
+            Bundle bundle = new Bundle();
+            bundle.putBoolean(KEY_TOGGLE, pref.isToggled());
+            bundle.putBoolean(KEY_ENABLE, pref.isEnabled());
+            if (pref.callForwardInfo != null) {
+                bundle.putString(KEY_NUMBER, pref.callForwardInfo.number);
+                bundle.putInt(KEY_STATUS, pref.callForwardInfo.status);
+            }
+            outState.putParcelable(pref.getKey(), bundle);
+        }
+    }
+
+    @Override
+    public void onFinished(Preference preference, boolean reading) {
+        if (mInitIndex < mPreferences.size()-1 && !isFinishing()) {
+            mInitIndex++;
+            CallForwardEditPreference pref = mPreferences.get(mInitIndex);
+            pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd);
+            pref.startCallForwardOptionsQuery();
+        }
+
+        super.onFinished(preference, reading);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.d(LOG_TAG, "onActivityResult: done");
+        if (resultCode != RESULT_OK) {
+            Log.d(LOG_TAG, "onActivityResult: contact picker result not OK.");
+            return;
+        }
+        Cursor cursor = null;
+        try {
+            cursor = getContentResolver().query(data.getData(),
+                NUM_PROJECTION, null, null, null);
+            if ((cursor == null) || (!cursor.moveToFirst())) {
+                Log.d(LOG_TAG, "onActivityResult: bad contact data, no results found.");
+                return;
+            }
+
+            switch (requestCode) {
+                case CommandsInterface.CF_REASON_UNCONDITIONAL:
+                    mButtonCFU.onPickActivityResult(cursor.getString(0));
+                    break;
+                case CommandsInterface.CF_REASON_BUSY:
+                    mButtonCFB.onPickActivityResult(cursor.getString(0));
+                    break;
+                case CommandsInterface.CF_REASON_NO_REPLY:
+                    mButtonCFNRy.onPickActivityResult(cursor.getString(0));
+                    break;
+                case CommandsInterface.CF_REASON_NOT_REACHABLE:
+                    mButtonCFNRc.onPickActivityResult(cursor.getString(0));
+                    break;
+                default:
+                    // TODO: may need exception here.
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        final int itemId = item.getItemId();
+        if (itemId == android.R.id.home) {  // See ActionBar#setDisplayHomeAsUpEnabled()
+            CallFeaturesSetting.goUpToTopLevelSetting(this, mSubscriptionInfoHelper);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/src/com/android/phone/CdmaCallOptions.java b/src/com/android/phone/CdmaCallOptions.java
index 8513664..2e310aa 100644
--- a/src/com/android/phone/CdmaCallOptions.java
+++ b/src/com/android/phone/CdmaCallOptions.java
@@ -19,18 +19,19 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.preference.Preference;
-import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
 import android.telephony.CarrierConfigManager;
 import android.view.MenuItem;
 
 import com.android.internal.telephony.PhoneConstants;
 
-public class CdmaCallOptions extends PreferenceActivity {
+public class CdmaCallOptions extends TimeConsumingPreferenceActivity {
     private static final String LOG_TAG = "CdmaCallOptions";
     private final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
 
     private static final String BUTTON_VP_KEY = "button_voice_privacy_key";
+    private static final String CALL_FORWARDING_KEY = "call_forwarding_key";
+    private static final String CALL_WAITING_KEY = "call_waiting_key";
     private CdmaVoicePrivacySwitchPreference mButtonVoicePrivacy;
 
     @Override
@@ -55,8 +56,15 @@
         if (subInfoHelper.getPhone().getPhoneType() != PhoneConstants.PHONE_TYPE_CDMA
                 || carrierConfig.getBoolean(CarrierConfigManager.KEY_VOICE_PRIVACY_DISABLE_UI_BOOL)) {
             // disable the entire screen
-            getPreferenceScreen().setEnabled(false);
+            mButtonVoicePrivacy.setEnabled(false);
         }
+
+        Preference callForwardingPref = getPreferenceScreen().findPreference(CALL_FORWARDING_KEY);
+        callForwardingPref.setIntent(subInfoHelper.getIntent(CdmaCallForwardOptions.class));
+
+        CdmaCallWaitingPreference callWaitingPref = (CdmaCallWaitingPreference)getPreferenceScreen()
+                                                     .findPreference(CALL_WAITING_KEY);
+        callWaitingPref.init(this, subInfoHelper.getPhone());
     }
 
     @Override
@@ -76,5 +84,4 @@
         }
         return false;
     }
-
 }
diff --git a/src/com/android/phone/CdmaCallWaitingPreference.java b/src/com/android/phone/CdmaCallWaitingPreference.java
new file mode 100644
index 0000000..4cda7ba
--- /dev/null
+++ b/src/com/android/phone/CdmaCallWaitingPreference.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.util.AttributeSet;
+import android.util.Log;
+
+public class CdmaCallWaitingPreference extends Preference {
+    private static final String LOG_TAG = "CdmaCallWaitingPreference";
+    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
+
+    private int mButtonClicked;
+    private Context mContext;
+    private Phone mPhone;
+    private SubscriptionInfoHelper mSubscriptionInfoHelper;
+    private TimeConsumingPreferenceListener mTcpListener;
+    private MyHandler mHandler = new MyHandler();
+
+    public CdmaCallWaitingPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mContext = context;
+    }
+
+    public CdmaCallWaitingPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.preferenceStyle);
+    }
+
+    public CdmaCallWaitingPreference(Context context) {
+        this(context, null);
+    }
+
+    public void init(TimeConsumingPreferenceListener listener, Phone phone) {
+        mPhone = phone;
+        mTcpListener = listener;
+        Log.d(LOG_TAG, "phone id= " + mPhone.getPhoneId());
+        mPhone.getCallWaiting(mHandler.obtainMessage(MyHandler.MESSAGE_GET_CALL_WAITING,
+                    MyHandler.MESSAGE_GET_CALL_WAITING, MyHandler.MESSAGE_GET_CALL_WAITING));
+        if (mTcpListener != null) {
+            mTcpListener.onStarted(this, true);
+        }
+    }
+
+    @Override
+    public void onClick() {
+        super.onClick();
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+        builder.setTitle(mContext.getText(R.string.cdma_call_waiting));
+        builder.setMessage(mContext.getText(R.string.enable_cdma_call_waiting_setting));
+        builder.setPositiveButton(R.string.enable_cdma_cw, new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int whichButton) {
+                mPhone.setCallWaiting(true,
+                        mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_WAITING));
+                if (mTcpListener != null) {
+                    mTcpListener.onStarted(CdmaCallWaitingPreference.this, false);
+                }
+            }
+        });
+        builder.setNegativeButton(R.string.disable_cdma_cw, new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int whichButton) {
+                mPhone.setCallWaiting(false,
+                        mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_WAITING));
+                if (mTcpListener != null) {
+                    mTcpListener.onStarted(CdmaCallWaitingPreference.this, false);
+                }
+            }
+        });
+        builder.create().show();
+    }
+
+    private class MyHandler extends Handler {
+        static final int MESSAGE_GET_CALL_WAITING = 0;
+        static final int MESSAGE_SET_CALL_WAITING = 1;
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_GET_CALL_WAITING:
+                    handleGetCallWaitingResponse(msg);
+                    break;
+                case MESSAGE_SET_CALL_WAITING:
+                    handleSetCallWaitingResponse(msg);
+                    break;
+            }
+        }
+
+        private void handleGetCallWaitingResponse(Message msg) {
+            AsyncResult ar = (AsyncResult) msg.obj;
+
+            if (mTcpListener != null) {
+                if (msg.arg2 == MESSAGE_SET_CALL_WAITING) {
+                    mTcpListener.onFinished(CdmaCallWaitingPreference.this, false);
+                } else {
+                    mTcpListener.onFinished(CdmaCallWaitingPreference.this, true);
+                }
+            }
+
+            if (ar.exception instanceof CommandException) {
+                if (DBG) {
+                    Log.d(LOG_TAG, "handleGetCallWaitingResponse: CommandException=" +
+                            ar.exception);
+                }
+                if (mTcpListener != null) {
+                    mTcpListener.onException(CdmaCallWaitingPreference.this,
+                                             (CommandException)ar.exception);
+                }
+            } else if (ar.userObj instanceof Throwable || ar.exception != null) {
+                if (DBG) {
+                    Log.d(LOG_TAG, "handleGetCallWaitingResponse: Exception" + ar.exception);
+                }
+                if (mTcpListener != null) {
+                    mTcpListener.onError(CdmaCallWaitingPreference.this,
+                                         TimeConsumingPreferenceActivity.RESPONSE_ERROR);
+                }
+            } else {
+                if (DBG) {
+                    Log.d(LOG_TAG, "handleGetCallWaitingResponse: CW state successfully queried.");
+                }
+                int[] cwArray = (int[])ar.result;
+                if (cwArray == null) {
+                    if (mTcpListener != null) {
+                        mTcpListener.onError(CdmaCallWaitingPreference.this,
+                                             TimeConsumingPreferenceActivity.RESPONSE_ERROR);
+                    }
+                    return;
+                }
+
+                try {
+                    if (cwArray[0] == CommandsInterface.SS_STATUS_UNKNOWN) {
+                        setSummary("");
+                    } else if(cwArray[0] == 1) {
+                        setSummary(mContext.getString(R.string.cdma_call_waiting_in_ims_on));
+                    } else if(cwArray[0] == 0) {
+                        setSummary(mContext.getString(R.string.cdma_call_waiting_in_ims_off));
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    setSummary("");
+                    Log.e(LOG_TAG, "handleGetCallWaitingResponse: improper result: err ="
+                            + e.getMessage());
+                }
+            }
+        }
+
+        private void handleSetCallWaitingResponse(Message msg) {
+            AsyncResult ar = (AsyncResult) msg.obj;
+
+            if (ar.exception != null) {
+                if (DBG) {
+                    Log.d(LOG_TAG, "handleSetCallWaitingResponse: ar.exception=" + ar.exception);
+                }
+            }
+
+            if (ar.result != null) {
+                int arr = (int)ar.result;
+                if (arr == CommandsInterface.SS_STATUS_UNKNOWN) {
+                    Log.d(LOG_TAG, "handleSetCallWaitingResponse: no need to re get in CDMA");
+                    mTcpListener.onFinished(CdmaCallWaitingPreference.this, false);
+                    return;
+                }
+            }
+
+            if (DBG) Log.d(LOG_TAG, "handleSetCallWaitingResponse: re get");
+            mPhone.getCallWaiting(obtainMessage(MESSAGE_GET_CALL_WAITING,
+                        MESSAGE_SET_CALL_WAITING, MESSAGE_SET_CALL_WAITING, ar.exception));
+        }
+    }
+}
diff --git a/src/com/android/phone/EditPhoneNumberPreference.java b/src/com/android/phone/EditPhoneNumberPreference.java
index 74b8a45..505c284 100644
--- a/src/com/android/phone/EditPhoneNumberPreference.java
+++ b/src/com/android/phone/EditPhoneNumberPreference.java
@@ -16,6 +16,9 @@
 
 package com.android.phone;
 
+import static android.view.View.LAYOUT_DIRECTION_LOCALE;
+import static android.view.View.TEXT_DIRECTION_LOCALE;
+
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
@@ -37,6 +40,8 @@
 import android.widget.ImageButton;
 import android.widget.TextView;
 
+import com.android.internal.telephony.CommandsInterface;
+
 public class EditPhoneNumberPreference extends EditTextPreference {
 
     //allowed modes for this preference.
@@ -90,6 +95,7 @@
     private String mPhoneNumber;
     private boolean mChecked;
 
+    private boolean mIsUnknownStatus;
 
     /**
      * Interface for the dialog closed listener, related to
@@ -209,7 +215,9 @@
                 }
             }
             editText.setText(BidiFormatter.getInstance().unicodeWrap(
-                    mPhoneNumber, TextDirectionHeuristics.LTR));
+                    mPhoneNumber, TextDirectionHeuristics.LOCALE));
+            editText.setTextDirection(TEXT_DIRECTION_LOCALE);
+            editText.setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
             editText.setMovementMethod(ArrowKeyMovementMethod.getInstance());
             editText.setKeyListener(DialerKeyListener.getInstance());
             editText.setOnFocusChangeListener(mDialogFocusChangeListener);
@@ -254,7 +262,13 @@
         // displayed, since there is no need to hide the edittext
         // field anymore.
         if (mConfirmationMode == CM_ACTIVATION) {
-            if (mChecked) {
+            if (mIsUnknownStatus) {
+                builder.setPositiveButton(mEnableText, this);
+                builder.setNeutralButton(mDisableText, this);
+                if (mPrefId == CommandsInterface.CF_REASON_ALL) {
+                    builder.setPositiveButton(null, null);
+                }
+            } else if (mChecked) {
                 builder.setPositiveButton(mChangeNumberText, this);
                 builder.setNeutralButton(mDisableText, this);
             } else {
@@ -310,7 +324,8 @@
     @Override
     public void onClick(DialogInterface dialog, int which) {
         // The neutral button (button3) is always the toggle.
-        if ((mConfirmationMode == CM_ACTIVATION) && (which == DialogInterface.BUTTON_NEUTRAL)) {
+        if ((mConfirmationMode == CM_ACTIVATION) && (which == DialogInterface.BUTTON_NEUTRAL)
+             && !mIsUnknownStatus) {
             //flip the toggle if we are in the correct mode.
             setToggled(!isToggled());
         }
@@ -499,4 +514,12 @@
     public void showPhoneNumberDialog() {
         showDialog(null);
     }
+
+    public void setUnknownStatus(boolean isUnknown) {
+        mIsUnknownStatus = isUnknown;
+    }
+
+    public boolean isUnknownStatus() {
+        return mIsUnknownStatus;
+    }
 }
diff --git a/src/com/android/phone/IccNetworkDepersonalizationPanel.java b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
index a26225e..a4ec8a4 100644
--- a/src/com/android/phone/IccNetworkDepersonalizationPanel.java
+++ b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
@@ -23,6 +23,8 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.Spannable;
@@ -68,6 +70,7 @@
     private static IccNetworkDepersonalizationPanel [] sNdpPanel =
             new IccNetworkDepersonalizationPanel[
                     TelephonyManager.getDefault().getSupportedModemCount()];
+    private SubscriptionInfo mSir;
 
     //UI elements
     private EditText     mPinEntry;
@@ -75,6 +78,7 @@
     private LinearLayout mStatusPanel;
     private TextView     mPersoSubtypeText;
     private PersoSubState mPersoSubState;
+    private TextView     mPhoneIdText;
     private TextView     mStatusText;
 
     private Button       mUnlockButton;
@@ -167,6 +171,8 @@
         super(context);
         mPhone = PhoneGlobals.getPhone();
         mPersoSubtype = PersoSubState.PERSOSUBSTATE_SIM_NETWORK.ordinal();
+        mSir = SubscriptionManager.from(context)
+                .getActiveSubscriptionInfoForSimSlotIndex(mPhone.getPhoneId());
     }
 
     //constructor
@@ -175,6 +181,8 @@
         super(context);
         mPhone = phone == null ? PhoneGlobals.getPhone() : phone;
         mPersoSubtype = subtype;
+        mSir = SubscriptionManager.from(context)
+                .getActiveSubscriptionInfoForSimSlotIndex(mPhone.getPhoneId());
     }
 
     @Override
@@ -194,6 +202,7 @@
 
         mEntryPanel = (LinearLayout) findViewById(R.id.entry_panel);
         mPersoSubtypeText = (TextView) findViewById(R.id.perso_subtype_text);
+        mPhoneIdText = (TextView) findViewById(R.id.perso_phoneid_text);
         displayStatus(statusType.ENTRY.name());
 
         mUnlockButton = (Button) findViewById(R.id.ndp_unlock);
@@ -282,6 +291,17 @@
             log ("Unsupported Perso Subtype :" + mPersoSubState.name());
             return;
         }
+        if(mSir != null) {
+            CharSequence displayName = mSir.getDisplayName();
+            log("Operator displayName is: " + displayName + "phoneId: " + mPhone.getPhoneId());
+
+            if(displayName != null && displayName != "") {
+                // Displaying Operator displayName  on UI
+                String phoneIdText = getContext().getString(R.string.label_phoneid)
+                        + ": " + displayName;
+                mPhoneIdText.setText(phoneIdText);
+            }
+        }
 
         if (type == statusType.ENTRY.name()) {
             String displayText = getContext().getString(label);
diff --git a/src/com/android/phone/IccPanel.java b/src/com/android/phone/IccPanel.java
index 73dd8bc..4018e40 100644
--- a/src/com/android/phone/IccPanel.java
+++ b/src/com/android/phone/IccPanel.java
@@ -74,13 +74,13 @@
     @Override
     protected void onStart() {
         super.onStart();
-        mStatusBarManager.setDisabledForSimNetworkLock(true);
+        mStatusBarManager.setExpansionDisabledForSimNetworkLock(true);
     }
 
     @Override
     public void onStop() {
         super.onStop();
-        mStatusBarManager.setDisabledForSimNetworkLock(false);
+        mStatusBarManager.setExpansionDisabledForSimNetworkLock(false);
     }
 
     public boolean onKeyDown(int keyCode, KeyEvent event) {
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index dcae24b..c91cc3b 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -16,30 +16,42 @@
 
 package com.android.phone;
 
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
+import android.os.UserHandle;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.ims.DelegateRequest;
 import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsUceAdapter.PublishState;
 import android.telephony.ims.RegistrationManager;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsRcsController;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.RcsFeature;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
 import com.android.ims.ImsManager;
+import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.services.telephony.rcs.RcsFeatureController;
+import com.android.services.telephony.rcs.SipTransportController;
 import com.android.services.telephony.rcs.TelephonyRcsService;
-import com.android.services.telephony.rcs.UserCapabilityExchangeImpl;
+import com.android.services.telephony.rcs.UceControllerManager;
 
 import java.util.List;
 
@@ -54,6 +66,9 @@
 
     private PhoneGlobals mApp;
     private TelephonyRcsService mRcsService;
+    private ImsResolver mImsResolver;
+    // set by shell cmd phone src set-device-enabled true/false
+    private Boolean mSingleRegistrationOverride;
 
     /**
      * Initialize the singleton ImsRcsController instance.
@@ -76,6 +91,7 @@
         mApp = app;
         TelephonyFrameworkInitializer
                 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
+        mImsResolver = mApp.getImsResolver();
     }
 
     /**
@@ -249,36 +265,92 @@
     public void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
             List<Uri> contactNumbers, IRcsUceControllerCallback c) {
         enforceReadPrivilegedPermission("requestCapabilities");
-        if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
-            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
-                    "The user has not enabled UCE for this subscription.");
-        }
         final long token = Binder.clearCallingIdentity();
         try {
-            UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
-                    UserCapabilityExchangeImpl.class);
-            if (uce == null) {
+            UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+                    UceControllerManager.class);
+            if (uceCtrlManager == null) {
                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
                         "This subscription does not support UCE.");
             }
-            uce.requestCapabilities(contactNumbers, c);
+            uceCtrlManager.requestCapabilities(contactNumbers, c);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
     @Override
-    public int getUcePublishState(int subId) {
-        enforceReadPrivilegedPermission("getUcePublishState");
+    public void requestAvailability(int subId, String callingPackage,
+            String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
+        enforceReadPrivilegedPermission("requestAvailability");
         final long token = Binder.clearCallingIdentity();
         try {
-            UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
-                    UserCapabilityExchangeImpl.class);
-            if (uce == null) {
+            UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+                    UceControllerManager.class);
+            if (uceCtrlManager == null) {
                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
                         "This subscription does not support UCE.");
             }
-            return uce.getUcePublishState();
+            uceCtrlManager.requestNetworkAvailability(contactNumber, c);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public @PublishState int getUcePublishState(int subId) {
+        enforceReadPrivilegedPermission("getUcePublishState");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+                    UceControllerManager.class);
+            if (uceCtrlManager == null) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "This subscription does not support UCE.");
+            }
+            return uceCtrlManager.getUcePublishState();
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
+        enforceReadPrivilegedPermission("registerUcePublishStateCallback");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+                    UceControllerManager.class);
+            if (uceCtrlManager == null) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "This subscription does not support UCE.");
+            }
+            uceCtrlManager.registerPublishStateCallback(c);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
+        enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+                    UceControllerManager.class);
+            if (uceCtrlManager == null) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "This subscription does not support UCE.");
+            }
+            uceCtrlManager.unregisterPublishStateCallback(c);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -313,6 +385,143 @@
         }
     }
 
+    @Override
+    public boolean isSipDelegateSupported(int subId) {
+        enforceReadPrivilegedPermission("isSipDelegateSupported");
+        if (!isImsSingleRegistrationSupportedOnDevice()) {
+            return false;
+        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            SipTransportController transport = getRcsFeatureController(subId).getFeature(
+                    SipTransportController.class);
+            if (transport == null) {
+                return false;
+            }
+            return transport.isSupported(subId);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
+                return false;
+            }
+            throw e;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void createSipDelegate(int subId, DelegateRequest request, String packageName,
+            ISipDelegateConnectionStateCallback delegateState,
+            ISipDelegateMessageCallback delegateMessage) {
+        enforceModifyPermission();
+        if (!isImsSingleRegistrationSupportedOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "SipDelegate creation is only supported for devices supporting IMS single "
+                            + "registration");
+        }
+        if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "SipDelegate creation is only available to primary user.");
+        }
+        try {
+            int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
+            if (Binder.getCallingUid() != remoteUid) {
+                throw new SecurityException("passed in packageName does not match the caller");
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new SecurityException("Passed in PackageName can not be found on device");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        SipTransportController transport = getRcsFeatureController(subId).getFeature(
+                SipTransportController.class);
+        if (transport == null) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "This subscription does not support the creation of SIP delegates");
+        }
+        try {
+            transport.createSipDelegate(subId, request, packageName, delegateState,
+                    delegateMessage);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode(), e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            SipTransportController transport = getRcsFeatureController(subId).getFeature(
+                    SipTransportController.class);
+            if (transport == null) {
+                return;
+            }
+            transport.destroySipDelegate(subId, connection, reason);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
+            String sipReason) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            SipTransportController transport = getRcsFeatureController(subId).getFeature(
+                    SipTransportController.class);
+            if (transport == null) {
+                return;
+            }
+            transport.triggerFullNetworkRegistration(subId, connection, sipCode, sipReason);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
+     * callback.
+     */
+    @Override
+    public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "Device does not support IMS");
+            }
+            mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
+     */
+    @Override
+    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) return;
+            mImsResolver.unregisterImsFeatureCallback(callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     /**
      * Make sure either called from same process as self (phone) or IPC caller has read privilege.
      *
@@ -387,7 +596,21 @@
         return c;
     }
 
+    private boolean isImsSingleRegistrationSupportedOnDevice() {
+        return mSingleRegistrationOverride != null ? mSingleRegistrationOverride
+                : mApp.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
+    }
+
     void setRcsService(TelephonyRcsService rcsService) {
         mRcsService = rcsService;
     }
+
+    /**
+     * Override device RCS single registration support check for CTS testing or remove override
+     * if the Boolean is set to null.
+     */
+    void setDeviceSingleRegistrationSupportOverride(Boolean deviceOverrideValue) {
+        mSingleRegistrationOverride = deviceOverrideValue;
+    }
 }
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 18fc534..0825cfb 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -25,6 +25,8 @@
 
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.imsphone.ImsPhone;
 
 public class ImsUtil {
     private static final String LOG_TAG = ImsUtil.class.getSimpleName();
@@ -113,12 +115,25 @@
     public static boolean shouldPromoteWfc(Context context, int phoneId) {
         CarrierConfigManager cfgManager = (CarrierConfigManager) context
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+        ImsManager imsManager = ImsManager.getInstance(context, phoneId);
+        if (!imsManager.isWfcEnabledByPlatform()) {
+            return false;
+        }
+
+        if (!imsManager.isWfcProvisionedOnDevice()) {
+            return false;
+        }
+
         if (cfgManager == null || !cfgManager.getConfigForSubId(getSubId(phoneId))
                 .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
             return false;
         }
 
-        if (!getDefaultImsManagerInstance(context).isWfcProvisionedOnDevice()) {
+        // Do not promote WFC if in roaming and WFC roaming not allowed.
+        // WFC roaming setting is not modifiable, so its value is decided by the default value
+        // chosen by the carrier, hence it really means if the carrier supports WFC roaming.
+        if (getLastKnownRoamingState(phoneId) && !imsManager.isWfcRoamingEnabledByUser()) {
             return false;
         }
 
@@ -146,4 +161,13 @@
         }
         return subId;
     }
+
+    private static boolean getLastKnownRoamingState(int phoneId) {
+        try {
+            ImsPhone imsPhone = (ImsPhone) (PhoneFactory.getPhone(phoneId).getImsPhone());
+            return imsPhone.getRoamingState();
+        } catch (NullPointerException | ClassCastException e) {
+            return false;
+        }
+    }
 }
diff --git a/src/com/android/phone/LocalConnectionImpl.java b/src/com/android/phone/LocalConnectionImpl.java
new file mode 100644
index 0000000..c2630ef
--- /dev/null
+++ b/src/com/android/phone/LocalConnectionImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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 android.content.Context;
+import android.telephony.TelephonyLocalConnection;
+
+import com.android.phone.callcomposer.CallComposerPictureManager;
+
+import java.util.UUID;
+
+public class LocalConnectionImpl implements TelephonyLocalConnection.ConnectionImpl {
+    private Context mContext;
+
+    public LocalConnectionImpl(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public String getCallComposerServerUrlForHandle(int subscriptionId, UUID uuid) {
+        return CallComposerPictureManager.getInstance(mContext, subscriptionId)
+                .getServerUrlForImageId(uuid);
+    }
+}
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index c2dece5..4fb61f0 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.READ_PHONE_STATE;
 
 import android.annotation.Nullable;
+import android.app.BroadcastOptions;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -106,6 +107,12 @@
 
     private static final String ACTION_MOBILE_NETWORK_LIST = "android.settings.MOBILE_NETWORK_LIST";
 
+    /**
+     * Grant recipients of new voicemail broadcasts a 10sec allowlist so they can start a background
+     * service to do VVM processing.
+     */
+    private final long VOICEMAIL_ALLOW_LIST_DURATION_MILLIS = 10000L;
+
     /** The singleton NotificationMgr instance. */
     private static NotificationMgr sInstance;
 
@@ -470,7 +477,10 @@
                             pendingIntent);
                 }
             }
-            mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE);
+
+            BroadcastOptions bopts = BroadcastOptions.makeBasic();
+            bopts.setTemporaryAppWhitelistDuration(VOICEMAIL_ALLOW_LIST_DURATION_MILLIS);
+            mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE, bopts.toBundle());
             return true;
         }
 
@@ -536,7 +546,11 @@
                 int slotId = SubscriptionManager.getSlotIndex(subId);
                 resId = (slotId == 0) ? R.drawable.stat_sys_phone_call_forward_sub1
                         : R.drawable.stat_sys_phone_call_forward_sub2;
-                notificationTitle = subInfo.getDisplayName().toString();
+                if (subInfo.getDisplayName() != null) {
+                    notificationTitle = subInfo.getDisplayName().toString();
+                } else {
+                    notificationTitle = mContext.getString(R.string.labelCF);
+                }
             } else {
                 notificationTitle = mContext.getString(R.string.labelCF);
             }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 8f987b7..9692a50 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -49,12 +49,14 @@
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+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;
 
+import com.android.ims.ImsFeatureBinderRepository;
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.MmiCode;
@@ -68,6 +70,8 @@
 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;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.phone.settings.SettingsConstants;
 import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver;
@@ -120,6 +124,7 @@
     private static final int EVENT_RESTART_SIP = 14;
     private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 15;
     private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 16;
+    private static final int EVENT_CARRIER_CONFIG_CHANGED = 17;
 
     // The MMI codes are also used by the InCallScreen.
     public static final int MMI_INITIATE = 51;
@@ -266,7 +271,9 @@
                     // process.
                     EventSimStateChangedBag bag = (EventSimStateChangedBag)msg.obj;
                     if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(bag.mIccStatus)
-                            || IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(bag.mIccStatus)) {
+                            || IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(bag.mIccStatus)
+                            || IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(bag.mIccStatus)
+                            || IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(bag.mIccStatus)) {
                         // when the right event is triggered and there
                         // are UI objects in the foreground, we close
                         // them to display the lock panel.
@@ -280,7 +287,7 @@
                             mPUKEntryProgressDialog.dismiss();
                             mPUKEntryProgressDialog = null;
                         }
-                        Log.i(LOG_TAG, "Dismissing depersonal panel");
+                        Log.i(LOG_TAG, "Dismissing depersonal panel" + (bag.mIccStatus));
                         IccNetworkDepersonalizationPanel.dialogDismiss(bag.mPhoneId);
                     }
                     break;
@@ -303,6 +310,12 @@
                 case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
                     updateDataRoamingStatus();
                     break;
+                case EVENT_CARRIER_CONFIG_CHANGED:
+                    int subId = (Integer) msg.obj;
+                    // The voicemail number could be overridden by carrier config, so need to
+                    // refresh the message waiting (voicemail) indicator.
+                    refreshMwiIndicator(subId);
+                    break;
             }
         }
     };
@@ -318,6 +331,9 @@
 
         ContentResolver resolver = getContentResolver();
 
+        // Initialize the shim from frameworks/opt/telephony into packages/services/Telephony.
+        TelephonyLocalConnection.setInstance(new LocalConnectionImpl(this));
+
         // Cache the "voice capable" flag.
         // This flag currently comes from a resource (which is
         // overrideable on a per-product basis):
@@ -347,8 +363,28 @@
                 String defaultImsRcsPackage = getResources().getString(
                         R.string.config_ims_rcs_package);
                 mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
-                        defaultImsRcsPackage, PhoneFactory.getPhones().length);
+                        defaultImsRcsPackage, PhoneFactory.getPhones().length,
+                        new ImsFeatureBinderRepository());
                 mImsResolver.initialize();
+
+                // With the IMS phone created, load static config.xml values from the phone process
+                // so that it can be provided to the ImsPhoneCallTracker.
+                for (Phone p : PhoneFactory.getPhones()) {
+                    Phone imsPhone = p.getImsPhone();
+                    if (imsPhone != null && imsPhone instanceof ImsPhone) {
+                        ImsPhone theImsPhone = (ImsPhone) imsPhone;
+                        if (theImsPhone.getCallTracker() instanceof ImsPhoneCallTracker) {
+                            ImsPhoneCallTracker ict = (ImsPhoneCallTracker)
+                                    theImsPhone.getCallTracker();
+
+                            ImsPhoneCallTracker.Config config = new ImsPhoneCallTracker.Config();
+                            config.isD2DCommunicationSupported = getResources().getBoolean(
+                                    R.bool.config_use_device_to_device_communication);
+                            ict.setConfig(config);
+                        }
+                    }
+                }
+                RcsProvisioningMonitor.make(this);
             }
 
             // Start TelephonyDebugService After the default phone is created.
@@ -356,9 +392,6 @@
             startService(intent);
 
             mCM = CallManager.getInstance();
-            for (Phone phone : PhoneFactory.getPhones()) {
-                mCM.registerPhone(phone);
-            }
 
             // Create the NotificationMgr singleton, which is used to display
             // status bar icons and control other status bar behavior.
@@ -708,6 +741,12 @@
                 if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
                 updateDataRoamingStatus();
                 updateLimitedSimFunctionForDualSim();
+                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARRIER_CONFIG_CHANGED,
+                            new Integer(subId)));
+                }
             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
                 // We also need to pay attention when default data subscription changes.
                 if (VDBG) Log.v(LOG_TAG, "default data sub changed.");
@@ -905,6 +944,23 @@
     }
 
     /**
+     * @return whether the device supports RCS User Capability Exchange or not.
+     */
+    public boolean getDeviceUceEnabled() {
+        return (mTelephonyRcsService == null) ? false : mTelephonyRcsService.isDeviceUceEnabled();
+    }
+
+    /**
+     * Set the device supports RCS User Capability Exchange.
+     * @param isEnabled true if the device supports UCE.
+     */
+    public void setDeviceUceEnabled(boolean isEnabled) {
+        if (mTelephonyRcsService != null) {
+            mTelephonyRcsService.setDeviceUceEnabled(isEnabled);
+        }
+    }
+
+    /**
      * Dump the state of the object, add calls to other objects as desired.
      *
      * @param fd File descriptor
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 0fd7ec0..a98a769 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -26,12 +26,12 @@
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -64,7 +64,9 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.ThermalMitigationResult;
 import android.telephony.CallForwardingInfo;
+import android.telephony.CarrierBandwidth;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CarrierRestrictionRules;
 import android.telephony.CellIdentity;
@@ -74,6 +76,8 @@
 import android.telephony.CellInfoGsm;
 import android.telephony.CellInfoWcdma;
 import android.telephony.ClientRequestStats;
+import android.telephony.DataThrottlingRequest;
+import android.telephony.IBootstrapAuthenticationCallback;
 import android.telephony.ICellInfoCallback;
 import android.telephony.IccOpenLogicalChannelResponse;
 import android.telephony.LocationAccessPolicy;
@@ -84,30 +88,36 @@
 import android.telephony.PhoneNumberRange;
 import android.telephony.RadioAccessFamily;
 import android.telephony.RadioAccessSpecifier;
+import android.telephony.RadioInterfaceCapabilities;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.SignalStrengthUpdateRequest;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyHistogram;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyScanManager;
+import android.telephony.ThermalMitigationRequest;
 import android.telephony.UiccCardInfo;
 import android.telephony.UiccSlotInfo;
 import android.telephony.UssdResponse;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.gba.GbaAuthRequest;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.RcsClientConfiguration;
 import android.telephony.ims.RegistrationManager;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.feature.RcsFeature;
@@ -121,6 +131,7 @@
 
 import com.android.ims.ImsManager;
 import com.android.ims.internal.IImsServiceFeatureCallback;
+import com.android.ims.rcs.uce.eab.EabUtil;
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.CallStateException;
@@ -130,8 +141,10 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DefaultPhoneNotifier;
+import com.android.internal.telephony.GbaManager;
 import com.android.internal.telephony.HalVersion;
 import com.android.internal.telephony.IBooleanConsumer;
+import com.android.internal.telephony.ICallForwardingInfoCallback;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.INumberVerificationCallback;
 import com.android.internal.telephony.ITelephony;
@@ -146,7 +159,6 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.ProxyController;
 import com.android.internal.telephony.RIL;
-import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.SmsController;
 import com.android.internal.telephony.SmsPermissions;
@@ -172,15 +184,24 @@
 import com.android.internal.telephony.uicc.UiccSlot;
 import com.android.internal.telephony.util.LocaleUtils;
 import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
+import com.android.internal.util.FunctionalUtils;
 import com.android.internal.util.HexDump;
+import com.android.phone.callcomposer.CallComposerPictureManager;
+import com.android.phone.callcomposer.CallComposerPictureTransfer;
+import com.android.phone.callcomposer.ImageData;
 import com.android.phone.settings.PickSmsSubscriptionActivity;
 import com.android.phone.vvm.PhoneAccountHandleConverter;
 import com.android.phone.vvm.RemoteVvmTaskManager;
 import com.android.phone.vvm.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
+import com.android.services.telephony.TelecomAccountRegistry;
+import com.android.services.telephony.TelephonyConnectionService;
 import com.android.telephony.Rlog;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -190,7 +211,9 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 
@@ -219,10 +242,8 @@
     private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
     private static final int CMD_RESET_MODEM_CONFIG = 19;
     private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
-    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
-    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
-    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
-    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
+    private static final int CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK = 21;
+    private static final int EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE = 22;
     private static final int CMD_SEND_ENVELOPE = 25;
     private static final int EVENT_SEND_ENVELOPE_DONE = 26;
     private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
@@ -289,6 +310,24 @@
     private static final int EVENT_GET_CALL_WAITING_DONE = 88;
     private static final int CMD_SET_CALL_WAITING = 89;
     private static final int EVENT_SET_CALL_WAITING_DONE = 90;
+    private static final int CMD_ENABLE_NR_DUAL_CONNECTIVITY = 91;
+    private static final int EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE = 92;
+    private static final int CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED = 93;
+    private static final int EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE = 94;
+    private static final int CMD_GET_CDMA_SUBSCRIPTION_MODE = 95;
+    private static final int EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE = 96;
+    private static final int CMD_GET_SYSTEM_SELECTION_CHANNELS = 97;
+    private static final int EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE = 98;
+    private static final int CMD_SET_DATA_THROTTLING = 99;
+    private static final int EVENT_SET_DATA_THROTTLING_DONE = 100;
+    private static final int CMD_SET_SIM_POWER = 101;
+    private static final int EVENT_SET_SIM_POWER_DONE = 102;
+    private static final int CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST = 103;
+    private static final int EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 104;
+    private static final int CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST = 105;
+    private static final int EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 106;
+    private static final int CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON = 107;
+    private static final int EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE = 108;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -313,6 +352,8 @@
     private AtomicBoolean mNotifyUserActivity;
     private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
 
+    private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
+
     private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
     private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
     private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
@@ -329,6 +370,8 @@
     private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
     private static final int MANUFACTURER_CODE_LENGTH = 8;
 
+    private static final int SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS = -1;
+
     /**
      * Experiment flag to enable erase modem config on reset network, default value is false
      */
@@ -749,40 +792,132 @@
                     handleNullReturnEvent(msg, "resetModemConfig");
                     break;
 
-                case CMD_GET_PREFERRED_NETWORK_TYPE:
+                case CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED: {
                     request = (MainThreadRequest) msg.obj;
-                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
-                    getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
+                    onCompleted = obtainMessage(EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE,
+                            request);
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.isNrDualConnectivityEnabled(onCompleted, request.workSource);
+                    } else {
+                        loge("isNRDualConnectivityEnabled: No phone object");
+                        request.result = false;
+                        notifyRequester(request);
+                    }
                     break;
+                }
 
-                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
+                case EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE:
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     if (ar.exception == null && ar.result != null) {
-                        request.result = ar.result;     // Integer
+                        request.result = ar.result;
                     } else {
-                        request.result = null;
-                        if (ar.result == null) {
-                            loge("getPreferredNetworkType: Empty response");
-                        } else if (ar.exception instanceof CommandException) {
-                            loge("getPreferredNetworkType: CommandException: " +
-                                    ar.exception);
+                        // request.result must be set to something non-null
+                        // for the calling thread to unblock
+                        if (request.result != null) {
+                            request.result = ar.result;
                         } else {
-                            loge("getPreferredNetworkType: Unknown exception");
+                            request.result = false;
+                        }
+                        if (ar.result == null) {
+                            loge("isNRDualConnectivityEnabled: Empty response");
+                        } else if (ar.exception instanceof CommandException) {
+                            loge("isNRDualConnectivityEnabled: CommandException: "
+                                    + ar.exception);
+                        } else {
+                            loge("isNRDualConnectivityEnabled: Unknown exception");
                         }
                     }
                     notifyRequester(request);
                     break;
 
-                case CMD_SET_PREFERRED_NETWORK_TYPE:
+                case CMD_ENABLE_NR_DUAL_CONNECTIVITY: {
                     request = (MainThreadRequest) msg.obj;
-                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
-                    int networkType = (Integer) request.argument;
-                    getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
+                    onCompleted = obtainMessage(EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE, request);
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.setNrDualConnectivityState((int) request.argument, onCompleted,
+                                request.workSource);
+                    } else {
+                        loge("enableNrDualConnectivity: No phone object");
+                        request.result =
+                                TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
+                        notifyRequester(request);
+                    }
+                    break;
+                }
+
+                case EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE: {
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null) {
+                        request.result =
+                                TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_SUCCESS;
+                    } else {
+                        request.result =
+                                TelephonyManager
+                                        .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_ERROR;
+                        if (ar.exception instanceof CommandException) {
+                            CommandException.Error error =
+                                    ((CommandException) (ar.exception)).getCommandError();
+                            if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                                request.result =
+                                        TelephonyManager
+                                                .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
+                            }
+                            loge("enableNrDualConnectivity" + ": CommandException: "
+                                    + ar.exception);
+                        } else {
+                            loge("enableNrDualConnectivity" + ": Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
+                }
+
+                case CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE,
+                            request);
+                    getPhoneFromRequest(request).getAllowedNetworkTypesBitmask(onCompleted);
                     break;
 
-                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
-                    handleNullReturnEvent(msg, "setPreferredNetworkType");
+                case EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null && ar.result != null) {
+                        request.result = ar.result;     // Integer
+                    } else {
+                        // request.result must be set to something non-null
+                        // for the calling thread to unblock
+                        request.result = new int[]{-1};
+                        if (ar.result == null) {
+                            loge("getAllowedNetworkTypesBitmask: Empty response");
+                        } else if (ar.exception instanceof CommandException) {
+                            loge("getAllowedNetworkTypesBitmask: CommandException: "
+                                    + ar.exception);
+                        } else {
+                            loge("getAllowedNetworkTypesBitmask: Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
+
+                case CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE,
+                            request);
+                    Pair<Integer, Long> reasonWithNetworkTypes =
+                            (Pair<Integer, Long>) request.argument;
+                    getPhoneFromRequest(request).setAllowedNetworkTypes(
+                            reasonWithNetworkTypes.first,
+                            reasonWithNetworkTypes.second,
+                            onCompleted);
+                    break;
+
+                case EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE:
+                    handleNullReturnEvent(msg, "setAllowedNetworkTypesForReason");
                     break;
 
                 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
@@ -827,38 +962,43 @@
                     getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
                     break;
 
-                case CMD_GET_CALL_FORWARDING:
+                case CMD_GET_CALL_FORWARDING: {
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_GET_CALL_FORWARDING_DONE, request);
-                    int callForwardingReason = (Integer) request.argument;
-                    getPhoneFromRequest(request).getCallForwardingOption(
-                            callForwardingReason, onCompleted);
+                    Pair<Integer, TelephonyManager.CallForwardingInfoCallback> args =
+                            (Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
+                                    request.argument;
+                    int callForwardingReason = args.first;
+                    request.phone.getCallForwardingOption(callForwardingReason, onCompleted);
                     break;
-
-                case EVENT_GET_CALL_FORWARDING_DONE:
+                }
+                case EVENT_GET_CALL_FORWARDING_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
-                    CallForwardingInfo callForwardingInfo = null;
+                    TelephonyManager.CallForwardingInfoCallback callback =
+                            ((Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
+                                    request.argument).second;
                     if (ar.exception == null && ar.result != null) {
+                        CallForwardingInfo callForwardingInfo = null;
                         CallForwardInfo[] callForwardInfos = (CallForwardInfo[]) ar.result;
                         for (CallForwardInfo callForwardInfo : callForwardInfos) {
                             // Service Class is a bit mask per 3gpp 27.007. Search for
                             // any service for voice call.
                             if ((callForwardInfo.serviceClass
                                     & CommandsInterface.SERVICE_CLASS_VOICE) > 0) {
-                                callForwardingInfo = new CallForwardingInfo(
-                                        callForwardInfo.serviceClass, callForwardInfo.reason,
-                                                callForwardInfo.number,
-                                                        callForwardInfo.timeSeconds);
+                                callForwardingInfo = new CallForwardingInfo(true,
+                                        callForwardInfo.reason,
+                                        callForwardInfo.number,
+                                        callForwardInfo.timeSeconds);
                                 break;
                             }
                         }
                         // Didn't find a call forward info for voice call.
                         if (callForwardingInfo == null) {
-                            callForwardingInfo = new CallForwardingInfo(
-                                    CallForwardingInfo.STATUS_UNKNOWN_ERROR,
-                                            0 /* reason */, null /* number */, 0 /* timeout */);
+                            callForwardingInfo = new CallForwardingInfo(false /* enabled */,
+                                    0 /* reason */, null /* number */, 0 /* timeout */);
                         }
+                        callback.onCallForwardingInfoAvailable(callForwardingInfo);
                     } else {
                         if (ar.result == null) {
                             loge("EVENT_GET_CALL_FORWARDING_DONE: Empty response");
@@ -866,56 +1006,80 @@
                         if (ar.exception != null) {
                             loge("EVENT_GET_CALL_FORWARDING_DONE: Exception: " + ar.exception);
                         }
-                        int errorCode = CallForwardingInfo.STATUS_UNKNOWN_ERROR;
+                        int errorCode = TelephonyManager
+                                .CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN;
                         if (ar.exception instanceof CommandException) {
                             CommandException.Error error =
                                     ((CommandException) (ar.exception)).getCommandError();
                             if (error == CommandException.Error.FDN_CHECK_FAILURE) {
-                                errorCode = CallForwardingInfo.STATUS_FDN_CHECK_FAILURE;
+                                errorCode = TelephonyManager
+                                        .CallForwardingInfoCallback.RESULT_ERROR_FDN_CHECK_FAILURE;
                             } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
-                                errorCode = CallForwardingInfo.STATUS_NOT_SUPPORTED;
+                                errorCode = TelephonyManager
+                                        .CallForwardingInfoCallback.RESULT_ERROR_NOT_SUPPORTED;
                             }
                         }
-                        callForwardingInfo = new CallForwardingInfo(
-                                errorCode, 0 /* reason */, null /* number */, 0 /* timeout */);
+                        callback.onError(errorCode);
                     }
-                    request.result = callForwardingInfo;
-                    notifyRequester(request);
                     break;
+                }
 
-                case CMD_SET_CALL_FORWARDING:
+                case CMD_SET_CALL_FORWARDING: {
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_SET_CALL_FORWARDING_DONE, request);
+                    request = (MainThreadRequest) msg.obj;
                     CallForwardingInfo callForwardingInfoToSet =
-                            (CallForwardingInfo) request.argument;
-                    getPhoneFromRequest(request).setCallForwardingOption(
-                            callForwardingInfoToSet.getStatus(),
+                            ((Pair<CallForwardingInfo, Consumer<Integer>>)
+                                    request.argument).first;
+                    request.phone.setCallForwardingOption(
+                            callForwardingInfoToSet.isEnabled()
+                                    ? CommandsInterface.CF_ACTION_ENABLE
+                                    : CommandsInterface.CF_ACTION_DISABLE,
                             callForwardingInfoToSet.getReason(),
                             callForwardingInfoToSet.getNumber(),
                             callForwardingInfoToSet.getTimeoutSeconds(), onCompleted);
                     break;
+                }
 
-                case EVENT_SET_CALL_FORWARDING_DONE:
+                case EVENT_SET_CALL_FORWARDING_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
-                    if (ar.exception == null) {
-                        request.result = true;
-                    } else {
-                        request.result = false;
+                    Consumer<Integer> callback =
+                            ((Pair<CallForwardingInfo, Consumer<Integer>>)
+                                    request.argument).second;
+                    if (ar.exception != null) {
                         loge("setCallForwarding exception: " + ar.exception);
+                        int errorCode = TelephonyManager.CallForwardingInfoCallback
+                                .RESULT_ERROR_UNKNOWN;
+                        if (ar.exception instanceof CommandException) {
+                            CommandException.Error error =
+                                    ((CommandException) (ar.exception)).getCommandError();
+                            if (error == CommandException.Error.FDN_CHECK_FAILURE) {
+                                errorCode = TelephonyManager.CallForwardingInfoCallback
+                                        .RESULT_ERROR_FDN_CHECK_FAILURE;
+                            } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+                                errorCode = TelephonyManager.CallForwardingInfoCallback
+                                        .RESULT_ERROR_NOT_SUPPORTED;
+                            }
+                        }
+                        callback.accept(errorCode);
+                    } else {
+                        callback.accept(TelephonyManager.CallForwardingInfoCallback.RESULT_SUCCESS);
                     }
-                    notifyRequester(request);
                     break;
+                }
 
-                case CMD_GET_CALL_WAITING:
+                case CMD_GET_CALL_WAITING: {
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_GET_CALL_WAITING_DONE, request);
                     getPhoneFromRequest(request).getCallWaiting(onCompleted);
                     break;
+                }
 
-                case EVENT_GET_CALL_WAITING_DONE:
+                case EVENT_GET_CALL_WAITING_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
+                    Consumer<Integer> callback = (Consumer<Integer>) request.argument;
                     int callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
                     if (ar.exception == null && ar.result != null) {
                         int[] callForwardResults = (int[]) ar.result;
@@ -923,12 +1087,12 @@
                         // Search for any service for voice call.
                         if (callForwardResults.length > 1
                                 && ((callForwardResults[1]
-                                        & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
+                                & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
                             callForwardingStatus = callForwardResults[0] == 0
-                                    ? TelephonyManager.CALL_WAITING_STATUS_INACTIVE
-                                            : TelephonyManager.CALL_WAITING_STATUS_ACTIVE;
+                                    ? TelephonyManager.CALL_WAITING_STATUS_DISABLED
+                                    : TelephonyManager.CALL_WAITING_STATUS_ENABLED;
                         } else {
-                            callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_INACTIVE;
+                            callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_DISABLED;
                         }
                     } else {
                         if (ar.result == null) {
@@ -946,28 +1110,43 @@
                             }
                         }
                     }
-                    request.result = callForwardingStatus;
-                    notifyRequester(request);
+                    callback.accept(callForwardingStatus);
                     break;
+                }
 
-                case CMD_SET_CALL_WAITING:
+                case CMD_SET_CALL_WAITING: {
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_SET_CALL_WAITING_DONE, request);
-                    boolean isEnable = (Boolean) request.argument;
-                    getPhoneFromRequest(request).setCallWaiting(isEnable, onCompleted);
+                    boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
+                    getPhoneFromRequest(request).setCallWaiting(enable, onCompleted);
                     break;
+                }
 
-                case EVENT_SET_CALL_WAITING_DONE:
+                case EVENT_SET_CALL_WAITING_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
-                    if (ar.exception == null) {
-                        request.result = true;
-                    } else {
-                        request.result = false;
+                    boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
+                    Consumer<Integer> callback =
+                            ((Pair<Boolean, Consumer<Integer>>) request.argument).second;
+                    if (ar.exception != null) {
                         loge("setCallWaiting exception: " + ar.exception);
+                        if (ar.exception instanceof CommandException) {
+                            CommandException.Error error =
+                                    ((CommandException) (ar.exception)).getCommandError();
+                            if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+                                callback.accept(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
+                            } else {
+                                callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+                            }
+                        } else {
+                            callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+                        }
+                    } else {
+                        callback.accept(enable ? TelephonyManager.CALL_WAITING_STATUS_ENABLED
+                                : TelephonyManager.CALL_WAITING_STATUS_DISABLED);
                     }
-                    notifyRequester(request);
                     break;
+                }
 
                 case EVENT_PERFORM_NETWORK_SCAN_DONE:
                     ar = (AsyncResult) msg.obj;
@@ -1032,29 +1211,31 @@
                         ResultReceiver result = (ResultReceiver) request.argument;
                         Bundle bundle = new Bundle();
                         bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
-                                new ModemActivityInfo(0, 0, 0, new int[0], 0));
+                                new ModemActivityInfo(0, 0, 0,
+                                        new int[ModemActivityInfo.getNumTxPowerLevels()], 0));
                         result.send(0, bundle);
                     }
                     break;
 
-                case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
+                case EVENT_GET_MODEM_ACTIVITY_INFO_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     ResultReceiver result = (ResultReceiver) request.argument;
 
-                    ModemActivityInfo ret = new ModemActivityInfo(0, 0, 0, new int[0], 0);
+                    ModemActivityInfo ret = null;
+                    int error = 0;
                     if (ar.exception == null && ar.result != null) {
                         // Update the last modem activity info and the result of the request.
                         ModemActivityInfo info = (ModemActivityInfo) ar.result;
                         if (isModemActivityInfoValid(info)) {
-                            int[] mergedTxTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
+                            int[] mergedTxTimeMs = new int[ModemActivityInfo.getNumTxPowerLevels()];
                             int[] txTimeMs = info.getTransmitTimeMillis();
                             int[] lastModemTxTimeMs = mLastModemActivityInfo
                                     .getTransmitTimeMillis();
                             for (int i = 0; i < mergedTxTimeMs.length; i++) {
                                 mergedTxTimeMs[i] = txTimeMs[i] + lastModemTxTimeMs[i];
                             }
-                            mLastModemActivityInfo.setTimestamp(info.getTimestamp());
+                            mLastModemActivityInfo.setTimestamp(info.getTimestampMillis());
                             mLastModemActivityInfo.setSleepTimeMillis(info.getSleepTimeMillis()
                                     + mLastModemActivityInfo.getSleepTimeMillis());
                             mLastModemActivityInfo.setIdleTimeMillis(info.getIdleTimeMillis()
@@ -1064,7 +1245,7 @@
                                     info.getReceiveTimeMillis()
                                             + mLastModemActivityInfo.getReceiveTimeMillis());
                         }
-                        ret = new ModemActivityInfo(mLastModemActivityInfo.getTimestamp(),
+                        ret = new ModemActivityInfo(mLastModemActivityInfo.getTimestampMillis(),
                                 mLastModemActivityInfo.getSleepTimeMillis(),
                                 mLastModemActivityInfo.getIdleTimeMillis(),
                                 mLastModemActivityInfo.getTransmitTimeMillis(),
@@ -1072,18 +1253,29 @@
                     } else {
                         if (ar.result == null) {
                             loge("queryModemActivityInfo: Empty response");
+                            error = TelephonyManager.ModemActivityInfoException
+                                    .ERROR_INVALID_INFO_RECEIVED;
                         } else if (ar.exception instanceof CommandException) {
                             loge("queryModemActivityInfo: CommandException: " +
                                     ar.exception);
+                            error = TelephonyManager.ModemActivityInfoException
+                                    .ERROR_MODEM_RESPONSE_ERROR;
                         } else {
                             loge("queryModemActivityInfo: Unknown exception");
+                            error = TelephonyManager.ModemActivityInfoException
+                                    .ERROR_UNKNOWN;
                         }
                     }
                     Bundle bundle = new Bundle();
-                    bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, ret);
+                    if (ret != null) {
+                        bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, ret);
+                    } else {
+                        bundle.putInt(TelephonyManager.EXCEPTION_RESULT_KEY, error);
+                    }
                     result.send(0, bundle);
                     notifyRequester(request);
                     break;
+                }
 
                 case CMD_SET_ALLOWED_CARRIERS:
                     request = (MainThreadRequest) msg.obj;
@@ -1246,11 +1438,27 @@
                     request.result = ar.exception == null;
                     notifyRequester(request);
                     break;
+                case CMD_GET_CDMA_SUBSCRIPTION_MODE:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE, request);
+                    getPhoneFromRequest(request).queryCdmaSubscriptionMode(onCompleted);
+                    break;
+                case EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception != null) {
+                        request.result = TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM;
+                    } else {
+                        request.result = ((int[]) ar.result)[0];
+                    }
+                    notifyRequester(request);
+                    break;
                 case CMD_SET_CDMA_SUBSCRIPTION_MODE:
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
                     int subscriptionMode = (int) request.argument;
-                    getPhoneFromRequest(request).setCdmaSubscription(subscriptionMode, onCompleted);
+                    getPhoneFromRequest(request).setCdmaSubscriptionMode(
+                            subscriptionMode, onCompleted);
                     break;
                 case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
                     ar = (AsyncResult) msg.obj;
@@ -1300,19 +1508,20 @@
                         Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
                     }
                     break;
-                case CMD_GET_CELL_LOCATION:
+                case CMD_GET_CELL_LOCATION: {
                     request = (MainThreadRequest) msg.obj;
                     WorkSource ws = (WorkSource) request.argument;
                     Phone phone = getPhoneFromRequest(request);
                     phone.getCellIdentity(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
                     break;
-                case EVENT_GET_CELL_LOCATION_DONE:
+                }
+                case EVENT_GET_CELL_LOCATION_DONE: {
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     if (ar.exception == null) {
                         request.result = ar.result;
                     } else {
-                        phone = getPhoneFromRequest(request);
+                        Phone phone = getPhoneFromRequest(request);
                         request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
                                 ? new CellIdentityCdma() : new CellIdentityGsm();
                     }
@@ -1321,6 +1530,7 @@
                         request.notifyAll();
                     }
                     break;
+                }
                 case CMD_MODEM_REBOOT:
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
@@ -1396,6 +1606,35 @@
                     notifyRequester(request);
                     break;
                 }
+                case CMD_GET_SYSTEM_SELECTION_CHANNELS: {
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE, request);
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.getSystemSelectionChannels(onCompleted);
+                    } else {
+                        loge("getSystemSelectionChannels: No phone object");
+                        request.result = new ArrayList<RadioAccessSpecifier>();
+                        notifyRequester(request);
+                    }
+                    break;
+                }
+                case EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null && ar.result != null) {
+                        request.result = ar.result;
+                    } else {
+                        request.result = new IllegalArgumentException(
+                                "Failed to retrieve system selection channels");
+                        if (ar.result == null) {
+                            loge("getSystemSelectionChannels: Empty response");
+                        } else {
+                            loge("getSystemSelectionChannels: Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
                 case EVENT_SET_FORBIDDEN_PLMNS_DONE:
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
@@ -1492,6 +1731,156 @@
                     getDefaultPhone().getContext().sendBroadcastAsUser(
                             intent, UserHandle.ALL, permission.USER_ACTIVITY);
                     break;
+
+                case CMD_SET_DATA_THROTTLING: {
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_SET_DATA_THROTTLING_DONE, request);
+                    DataThrottlingRequest dataThrottlingRequest =
+                            (DataThrottlingRequest) request.argument;
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.setDataThrottling(onCompleted,
+                                request.workSource, dataThrottlingRequest.getDataThrottlingAction(),
+                                dataThrottlingRequest.getCompletionDurationMillis());
+                    } else {
+                        loge("setDataThrottling: No phone object");
+                        request.result =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                        notifyRequester(request);
+                    }
+
+                    break;
+                }
+                case EVENT_SET_DATA_THROTTLING_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+
+                    if (ar.exception == null) {
+                        request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+                    } else if (ar.exception instanceof CommandException) {
+                        loge("setDataThrottling: CommandException: " + ar.exception);
+                        CommandException.Error error =
+                                ((CommandException) (ar.exception)).getCommandError();
+
+                        if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                            request.result = TelephonyManager
+                                .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                        } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
+                            request.result = SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS;
+                        } else {
+                            request.result =
+                                    TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+                        }
+                    } else {
+                        request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+                    }
+                    Log.w(LOG_TAG, "DataThrottlingResult = " + request.result);
+                    notifyRequester(request);
+                    break;
+
+                case CMD_SET_SIM_POWER: {
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_SET_SIM_POWER_DONE, request);
+                    request = (MainThreadRequest) msg.obj;
+                    int stateToSet =
+                            ((Pair<Integer, IIntegerConsumer>)
+                                    request.argument).first;
+                    request.phone.setSimPowerState(stateToSet, onCompleted, request.workSource);
+                    break;
+                }
+                case EVENT_SET_SIM_POWER_DONE: {
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    IIntegerConsumer callback =
+                            ((Pair<Integer, IIntegerConsumer>) request.argument).second;
+                    if (ar.exception != null) {
+                        loge("setSimPower exception: " + ar.exception);
+                        int errorCode = TelephonyManager.CallForwardingInfoCallback
+                                .RESULT_ERROR_UNKNOWN;
+                        if (ar.exception instanceof CommandException) {
+                            CommandException.Error error =
+                                    ((CommandException) (ar.exception)).getCommandError();
+                            if (error == CommandException.Error.SIM_ERR) {
+                                errorCode = TelephonyManager.SET_SIM_POWER_STATE_SIM_ERROR;
+                            } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
+                                errorCode = TelephonyManager.SET_SIM_POWER_STATE_ALREADY_IN_STATE;
+                            } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+                                errorCode = TelephonyManager.SET_SIM_POWER_STATE_NOT_SUPPORTED;
+                            } else {
+                                errorCode = TelephonyManager.SET_SIM_POWER_STATE_MODEM_ERROR;
+                            }
+                        }
+                        try {
+                            callback.accept(errorCode);
+                        } catch (RemoteException e) {
+                            // Ignore if the remote process is no longer available to call back.
+                            Log.w(LOG_TAG, "setSimPower: callback not available.");
+                        }
+                    } else {
+                        try {
+                            callback.accept(TelephonyManager.SET_SIM_POWER_STATE_SUCCESS);
+                        } catch (RemoteException e) {
+                            // Ignore if the remote process is no longer available to call back.
+                            Log.w(LOG_TAG, "setSimPower: callback not available.");
+                        }
+                    }
+                    break;
+                }
+                case CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST: {
+                    request = (MainThreadRequest) msg.obj;
+
+                    final Phone phone = getPhoneFromRequest(request);
+                    if (phone == null || phone.getServiceStateTracker() == null) {
+                        request.result = new IllegalStateException("Phone or SST is null");
+                        notifyRequester(request);
+                        break;
+                    }
+
+                    Pair<Integer, SignalStrengthUpdateRequest> pair =
+                            (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
+                    onCompleted = obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
+                            request);
+                    phone.getServiceStateTracker().setSignalStrengthUpdateRequest(
+                                    request.subId, pair.first /*callingUid*/,
+                                    pair.second /*request*/, onCompleted);
+                    break;
+                }
+                case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    // request.result will be the exception of ar if present, true otherwise.
+                    // Be cautious not to leave result null which will wait() forever
+                    request.result = ar.exception != null ? ar.exception : true;
+                    notifyRequester(request);
+                    break;
+                }
+                case CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST: {
+                    request = (MainThreadRequest) msg.obj;
+
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone == null || phone.getServiceStateTracker() == null) {
+                        request.result = new IllegalStateException("Phone or SST is null");
+                        notifyRequester(request);
+                        break;
+                    }
+
+                    Pair<Integer, SignalStrengthUpdateRequest> pair =
+                            (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
+                    onCompleted = obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
+                            request);
+                    phone.getServiceStateTracker().clearSignalStrengthUpdateRequest(
+                                    request.subId, pair.first /*callingUid*/,
+                                    pair.second /*request*/, onCompleted);
+                    break;
+                }
+                case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    request.result = ar.exception != null ? ar.exception : true;
+                    notifyRequester(request);
+                    break;
+                }
+
                 default:
                     Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
                     break;
@@ -1881,6 +2270,11 @@
                                                 ((CommandException)(ar.exception)).getCommandError()
                                                 == CommandException.Error.PASSWORD_INCORRECT) {
                                             mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
+                                        } //When UiccCardApp dispose,handle message and return exception
+                                          else if (ar.exception instanceof CommandException &&
+                                                ((CommandException) (ar.exception)).getCommandError()
+                                                        == CommandException.Error.ABORTED) {
+                                            mResult = PhoneConstants.PIN_OPERATION_ABORTED;
                                         } else {
                                             mResult = PhoneConstants.PIN_GENERAL_FAILURE;
                                         }
@@ -1940,20 +2334,52 @@
         }
     }
 
+    /**
+     * This method has been removed due to privacy and stability concerns.
+     */
+    @Override
     public void updateServiceLocation() {
-        updateServiceLocationForSubscriber(getDefaultSubscription());
-
+        Log.e(LOG_TAG, "Call to unsupported method updateServiceLocation()");
+        return;
     }
 
-    public void updateServiceLocationForSubscriber(int subId) {
-        // No permission check needed here: this call is harmless, and it's
-        // needed for the ServiceState.requestStateUpdate() call (which is
-        // already intentionally exposed to 3rd parties.)
+    @Override
+    public void updateServiceLocationWithPackageName(String callingPackage) {
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
+
+        final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
+        if (targetSdk > android.os.Build.VERSION_CODES.R) {
+            // Callers targeting S have no business invoking this method.
+            return;
+        }
+
+        LocationAccessPolicy.LocationPermissionResult locationResult =
+                LocationAccessPolicy.checkLocationPermission(mApp,
+                        new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                                .setCallingPackage(callingPackage)
+                                .setCallingFeatureId(null)
+                                .setCallingPid(Binder.getCallingPid())
+                                .setCallingUid(Binder.getCallingUid())
+                                .setMethod("updateServiceLocation")
+                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
+                                .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                .build());
+        // Apps that lack location permission have no business calling this method;
+        // however, because no permission was declared in the public API, denials must
+        // all be "soft".
+        switch (locationResult) {
+            case DENIED_HARD: /* fall through */
+            case DENIED_SOFT:
+                return;
+        }
+
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
         final long identity = Binder.clearCallingIdentity();
         try {
-            final Phone phone = getPhone(subId);
+            final Phone phone = getPhone(getDefaultSubscription());
             if (phone != null) {
-                phone.updateServiceLocation();
+                phone.updateServiceLocation(workSource);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -2135,7 +2561,8 @@
             int subId = mSubscriptionController.getDefaultDataSubId();
             final Phone phone = getPhone(subId);
             if (phone != null) {
-                phone.getDataEnabledSettings().setUserDataEnabled(true);
+                phone.getDataEnabledSettings().setDataEnabled(
+                        TelephonyManager.DATA_ENABLED_REASON_USER, true);
                 return true;
             } else {
                 return false;
@@ -2155,7 +2582,8 @@
             int subId = mSubscriptionController.getDefaultDataSubId();
             final Phone phone = getPhone(subId);
             if (phone != null) {
-                phone.getDataEnabledSettings().setUserDataEnabled(false);
+                phone.getDataEnabledSettings().setDataEnabled(
+                        TelephonyManager.DATA_ENABLED_REASON_USER, false);
                 return true;
             } else {
                 return false;
@@ -2329,72 +2757,37 @@
         }
     }
 
+    /**
+     * This method was removed due to potential issues caused by performing partial
+     * updates of service state, and lack of a credible use case.
+     *
+     * This has the ability to break the telephony implementation by disabling notification of
+     * changes in device connectivity. DO NOT USE THIS!
+     */
     @Override
     public void enableLocationUpdates() {
-        enableLocationUpdatesForSubscriber(getDefaultSubscription());
-    }
-
-    @Override
-    public void enableLocationUpdatesForSubscriber(int subId) {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            final Phone phone = getPhone(subId);
-            if (phone != null) {
-                phone.enableLocationUpdates();
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    @Override
-    public void disableLocationUpdates() {
-        disableLocationUpdatesForSubscriber(getDefaultSubscription());
-    }
-
-    @Override
-    public void disableLocationUpdatesForSubscriber(int subId) {
-        mApp.enforceCallingOrSelfPermission(
-                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            final Phone phone = getPhone(subId);
-            if (phone != null) {
-                phone.disableLocationUpdates();
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
     }
 
     /**
-     * Returns the target SDK version number for a given package name.
+     * This method was removed due to potential issues caused by performing partial
+     * updates of service state, and lack of a credible use case.
      *
-     * This call MUST be invoked before clearing the calling UID.
-     *
-     * @return target SDK if the package is found or INT_MAX.
+     * This has the ability to break the telephony implementation by disabling notification of
+     * changes in device connectivity. DO NOT USE THIS!
      */
-    private int getTargetSdk(String packageName) {
-        try {
-            final ApplicationInfo ai = mApp.getPackageManager().getApplicationInfoAsUser(
-                    packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
-            if (ai != null) return ai.targetSdkVersion;
-        } catch (PackageManager.NameNotFoundException unexpected) {
-            loge("Failed to get package info for pkg="
-                    + packageName + ", uid=" + Binder.getCallingUid());
-        }
-        return Integer.MAX_VALUE;
+    @Override
+    public void disableLocationUpdates() {
+        mApp.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage,
             String callingFeatureId) {
-        final int targetSdk = getTargetSdk(callingPackage);
+        final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
             throw new SecurityException(
                     "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
@@ -2453,7 +2846,7 @@
                 return new ArrayList<>();
         }
 
-        final int targetSdk = getTargetSdk(callingPackage);
+        final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
             return getCachedCellInfo();
         }
@@ -2506,13 +2899,15 @@
                                 .build());
         switch (locationResult) {
             case DENIED_HARD:
-                if (getTargetSdk(callingPackage) < Build.VERSION_CODES.Q) {
+                if (TelephonyPermissions
+                        .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
                     // Safetynet logging for b/154934934
                     EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
                 }
                 throw new SecurityException("Not allowed to access cell info");
             case DENIED_SOFT:
-                if (getTargetSdk(callingPackage) < Build.VERSION_CODES.Q) {
+                if (TelephonyPermissions
+                        .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
                     // Safetynet logging for b/154934934
                     EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
                 }
@@ -2709,7 +3104,7 @@
      *
      * @throws SecurityException if the caller is not system.
      */
-    private void enforceSystemCaller() {
+    private static void enforceSystemCaller() {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
             throw new SecurityException("Caller must be system");
         }
@@ -2922,7 +3317,9 @@
 
         String authorizedPackage = NumberVerificationManager.getAuthorizedPackage(mApp);
         if (!TextUtils.equals(callingPackage, authorizedPackage)) {
-            throw new SecurityException("Calling package must be configured in the device config");
+            throw new SecurityException("Calling package must be configured in the device config: "
+                    + "calling package: " + callingPackage
+                    + ", configured package: " + authorizedPackage);
         }
 
         if (range == null) {
@@ -3288,7 +3685,7 @@
         }
         final long token = Binder.clearCallingIdentity();
         try {
-            // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
+            // TODO(b/159910732): Remove ImsManager dependence and query through ImsPhone directly.
             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
                     .removeRegistrationCallbackForSubscription(c, subId);
         } catch (ImsException e) {
@@ -3411,7 +3808,7 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
-            // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
+            // TODO(b/159910732): Remove ImsManager dependence and query through ImsPhone directly.
             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
                         .removeCapabilitiesCallbackForSubscription(c, subId);
         } catch (ImsException e) {
@@ -3604,6 +4001,50 @@
     }
 
     /**
+     * @return true if the user's setting for Voice over Cross SIM is enabled and false if it is not
+     * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
+     * @param subId The subscription to use to check the configuration.
+     */
+    @Override
+    public boolean isCrossSimCallingEnabledByUser(int subId) {
+        TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+                mApp, subId, "isCrossSimCallingEnabledByUser");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+            return ImsManager.getInstance(mApp,
+                    getSlotIndexOrException(subId)).isCrossSimCallingEnabledByUser();
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Sets the user's setting for whether or not Voice over Cross SIM is enabled.
+     * Requires MODIFY_PHONE_STATE permission.
+     * @param subId The subscription to use to check the configuration.
+     * @param isEnabled true if the user's setting for Voice over Cross SIM is enabled,
+     *                 false otherwise
+     */
+    @Override
+    public void setCrossSimCallingEnabled(int subId, boolean isEnabled) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
+                "setCrossSimCallingEnabled");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+            ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
+                    .setCrossSimCallingEnabled(isEnabled);
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
      * @param subId The subscription to use to check the configuration.
      */
@@ -4237,7 +4678,7 @@
     @Override
     public int getNetworkTypeForSubscriber(int subId, String callingPackage,
             String callingFeatureId) {
-        final int targetSdk = getTargetSdk(callingPackage);
+        final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
         if (targetSdk > android.os.Build.VERSION_CODES.Q) {
             return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
         } else if (targetSdk == android.os.Build.VERSION_CODES.Q
@@ -4376,7 +4817,8 @@
             if (phone == null) {
                 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
             } else {
-                return phone.getLteOnCdmaMode();
+                return TelephonyProperties.lte_on_cdma_device()
+                        .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -4983,58 +5425,35 @@
     }
 
     /**
-     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
-     * feature or {@link null} if the service is not available. If the feature is available, the
-     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+     * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
+     * callback.
      */
-    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
-            IImsServiceFeatureCallback callback) {
+    @Override
+    public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) {
-                // may happen if the device does not support IMS.
-                return null;
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "Device does not support IMS");
             }
-            return mImsResolver.getMmTelFeatureAndListen(slotId, callback);
+            mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
-
-    /**
-     * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
-     * feature during emergency calling or {@link null} if the service is not available. If the
-     * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
-     * listener for feature updates.
-     */
-    public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
-        enforceModifyPermission();
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            if (mImsResolver == null) {
-                // may happen if the device does not support IMS.
-                return null;
-            }
-            return mImsResolver.getRcsFeatureAndListen(slotId, callback);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     /**
      * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
      */
-    public void unregisterImsFeatureCallback(int slotId, int featureType,
-            IImsServiceFeatureCallback callback) {
+    @Override
+    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) return;
-            mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
+            mImsResolver.unregisterImsFeatureCallback(callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5115,6 +5534,36 @@
     }
 
     /**
+     * Clears any carrier ImsService overrides for the slot index specified that were previously
+     * set with {@link #setBoundImsServiceOverride(int, boolean, int[], String)}.
+     *
+     * This should only be used for testing.
+     *
+     * @param slotIndex the slot ID that the ImsService should bind for.
+     * @return true if clearing the carrier ImsService override succeeded or false if it did not.
+     */
+    @Override
+    public boolean clearCarrierImsServiceOverride(int slotIndex) {
+        int[] subIds = SubscriptionManager.getSubId(slotIndex);
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+                "clearCarrierImsServiceOverride");
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+                (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
+                "clearCarrierImsServiceOverride");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) {
+                // may happen if the device does not support IMS.
+                return false;
+            }
+            return mImsResolver.clearCarrierImsServiceConfiguration(slotIndex);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Return the package name of the currently bound ImsService.
      *
      * @param slotId The slot that the ImsService is associated with.
@@ -5179,12 +5628,20 @@
         }
     }
 
-    public void setImsRegistrationState(boolean registered) {
+    /**
+     * Sets the ims registration state on all valid {@link Phone}s.
+     */
+    public void setImsRegistrationState(final boolean registered) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            getDefaultPhone().setImsRegistrationState(registered);
+            // NOTE: Before S, this method only set the default phone.
+            for (final Phone phone : PhoneFactory.getPhones()) {
+                if (SubscriptionManager.isValidSubscriptionId(phone.getSubId())) {
+                    phone.setImsRegistrationState(registered);
+                }
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5211,7 +5668,7 @@
         }
     }
 
-   /**
+    /**
      * Ask the radio to connect to the input network and change selection mode to manual.
      *
      * @param subId the id of the subscription.
@@ -5261,12 +5718,12 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             if (!isActiveSubscription(subId)) {
-                return "";
+                throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
             }
 
             final Phone phone = getPhone(subId);
             if (phone == null) {
-                return "";
+                throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
             }
             OperatorInfo networkSelection = phone.getSavedNetworkSelection();
             return TextUtils.isEmpty(networkSelection.getOperatorNumeric())
@@ -5293,6 +5750,8 @@
                                 .setCallingUid(Binder.getCallingUid())
                                 .setMethod("getCellNetworkScanResults")
                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
                                 .build());
         switch (locationResult) {
             case DENIED_HARD:
@@ -5315,7 +5774,8 @@
      * Get the call forwarding info, given the call forwarding reason.
      */
     @Override
-    public CallForwardingInfo getCallForwarding(int subId, int callForwardingReason) {
+    public void getCallForwarding(int subId, int callForwardingReason,
+            ICallForwardingInfoCallback callback) {
         enforceReadPrivilegedPermission("getCallForwarding");
         long identity = Binder.clearCallingIdentity();
         try {
@@ -5323,8 +5783,39 @@
                 log("getCallForwarding: subId " + subId
                         + " callForwardingReason" + callForwardingReason);
             }
-            return (CallForwardingInfo) sendRequest(
-                    CMD_GET_CALL_FORWARDING, callForwardingReason, subId);
+
+            Phone phone = getPhone(subId);
+            if (phone == null) {
+                try {
+                    callback.onError(
+                            TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                return;
+            }
+
+            Pair<Integer, TelephonyManager.CallForwardingInfoCallback> argument = Pair.create(
+                    callForwardingReason, new TelephonyManager.CallForwardingInfoCallback() {
+                        @Override
+                        public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
+                            try {
+                                callback.onCallForwardingInfoAvailable(info);
+                            } catch (RemoteException e) {
+                                // ignore
+                            }
+                        }
+
+                        @Override
+                        public void onError(int error) {
+                            try {
+                                callback.onError(error);
+                            } catch (RemoteException e) {
+                                // ignore
+                            }
+                        }
+                    });
+            sendRequestAsync(CMD_GET_CALL_FORWARDING, argument, phone, null);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5335,7 +5826,8 @@
      * reason, the number to forward, and the timeout before the forwarding is attempted.
      */
     @Override
-    public boolean setCallForwarding(int subId, CallForwardingInfo callForwardingInfo) {
+    public void setCallForwarding(int subId, CallForwardingInfo callForwardingInfo,
+            IIntegerConsumer callback) {
         enforceModifyPermission();
         long identity = Binder.clearCallingIdentity();
         try {
@@ -5343,38 +5835,79 @@
                 log("setCallForwarding: subId " + subId
                         + " callForwardingInfo" + callForwardingInfo);
             }
-            return (Boolean) sendRequest(CMD_SET_CALL_FORWARDING, callForwardingInfo, subId);
+
+            Phone phone = getPhone(subId);
+            if (phone == null) {
+                try {
+                    callback.accept(
+                            TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                return;
+            }
+
+            Pair<CallForwardingInfo, Consumer<Integer>> arguments = Pair.create(callForwardingInfo,
+                    FunctionalUtils.ignoreRemoteException(callback::accept));
+
+            sendRequestAsync(CMD_SET_CALL_FORWARDING, arguments, phone, null);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * Get the call forwarding info, given the call forwarding reason.
+     * Get the call waiting status for a subId.
      */
     @Override
-    public int getCallWaitingStatus(int subId) {
+    public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
         enforceReadPrivilegedPermission("getCallForwarding");
         long identity = Binder.clearCallingIdentity();
         try {
+
+            Phone phone = getPhone(subId);
+            if (phone == null) {
+                try {
+                    callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                return;
+            }
+
+            Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(callback::accept);
+
             if (DBG) log("getCallWaitingStatus: subId " + subId);
-            return (Integer) sendRequest(CMD_GET_CALL_WAITING, null, subId);
+            sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * Sets the voice call forwarding info including status (enable/disable), call forwarding
-     * reason, the number to forward, and the timeout before the forwarding is attempted.
+     * Sets whether call waiting is enabled for a given subId.
      */
     @Override
-    public boolean setCallWaitingStatus(int subId, boolean isEnable) {
+    public void setCallWaitingStatus(int subId, boolean enable, IIntegerConsumer callback) {
         enforceModifyPermission();
         long identity = Binder.clearCallingIdentity();
         try {
-            if (DBG) log("setCallWaitingStatus: subId " + subId + " isEnable: " + isEnable);
-            return (Boolean) sendRequest(CMD_SET_CALL_WAITING, isEnable, subId);
+            if (DBG) log("setCallWaitingStatus: subId " + subId + " enable: " + enable);
+
+            Phone phone = getPhone(subId);
+            if (phone == null) {
+                try {
+                    callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                return;
+            }
+
+            Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
+                    FunctionalUtils.ignoreRemoteException(callback::accept));
+
+            sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5403,9 +5936,12 @@
                                 .setCallingUid(Binder.getCallingUid())
                                 .setMethod("requestNetworkScan")
                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
                                 .build());
         if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
-            SecurityException e = checkNetworkRequestForSanitizedLocationAccess(request, subId);
+            SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
+                    request, subId, callingPackage);
             if (e != null) {
                 if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
                     throw e;
@@ -5428,8 +5964,8 @@
     }
 
     private SecurityException checkNetworkRequestForSanitizedLocationAccess(
-            NetworkScanRequest request, int subId) {
-        boolean hasCarrierPriv = getCarrierPrivilegeStatusForUid(subId, Binder.getCallingUid())
+            NetworkScanRequest request, int subId, String callingPackage) {
+        boolean hasCarrierPriv = checkCarrierPrivilegesForPackage(subId, callingPackage)
                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
         boolean hasNetworkScanPermission =
                 mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
@@ -5473,121 +6009,29 @@
     }
 
     /**
-     * Get the calculated preferred network type.
-     * Used for debugging incorrect network type.
+     * Get the allowed network types bitmask.
      *
-     * @return the preferred network type, defined in RILConstants.java.
+     * @return the allowed network types bitmask, defined in RILConstants.java.
      */
     @Override
-    public int getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId) {
-        final Phone defaultPhone = getDefaultPhone();
-        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
-                callingPackage, callingFeatureId, "getCalculatedPreferredNetworkType")) {
-            return RILConstants.PREFERRED_NETWORK_MODE;
-        }
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            // FIXME: need to get SubId from somewhere.
-            return PhoneFactory.calculatePreferredNetworkType(defaultPhone.getContext(), 0);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
-     * Get the preferred network type.
-     * Used for device configuration by some CDMA operators.
-     *
-     * @return the preferred network type, defined in RILConstants.java.
-     */
-    @Override
-    public int getPreferredNetworkType(int subId) {
+    public int getAllowedNetworkTypesBitmask(int subId) {
         TelephonyPermissions
                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
-                        mApp, subId, "getPreferredNetworkType");
+                        mApp, subId, "getAllowedNetworkTypesBitmask");
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (DBG) log("getPreferredNetworkType");
-            int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
-            int networkType = (result != null ? result[0] : -1);
-            if (DBG) log("getPreferredNetworkType: " + networkType);
-            return networkType;
+            if (DBG) log("getAllowedNetworkTypesBitmask");
+            int[] result = (int[]) sendRequest(CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK, null, subId);
+            int networkTypesBitmask = (result != null ? result[0] : -1);
+            if (DBG) log("getAllowedNetworkTypesBitmask: " + networkTypesBitmask);
+            return networkTypesBitmask;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * Set the preferred network type.
-     *
-     * @param networkType the preferred network type, defined in RILConstants.java.
-     * @return true on success; false on any failure.
-     */
-    @Override
-    public boolean setPreferredNetworkType(int subId, int networkType) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "setPreferredNetworkType");
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            Settings.Global.putInt(mApp.getContentResolver(),
-                    Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
-
-            Boolean success = (Boolean) sendRequest(
-                    CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
-            if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
-            return success;
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
-     * Get the allowed network types that store in the telephony provider.
-     *
-     * @param subId the id of the subscription.
-     * @return allowedNetworkTypes the allowed network types.
-     */
-    @Override
-    public long getAllowedNetworkTypes(int subId) {
-        TelephonyPermissions
-                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
-                    mApp, subId, "getAllowedNetworkTypes");
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            return SubscriptionManager.getLongSubscriptionProperty(
-                    subId, SubscriptionManager.ALLOWED_NETWORK_TYPES, -1, mApp);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
-     * Set the allowed network types.
-     *
-     * @param subId the id of the subscription.
-     * @param allowedNetworkTypes the allowed network types.
-     * @return true on success; false on any failure.
-     */
-    @Override
-    public boolean setAllowedNetworkTypes(int subId, long allowedNetworkTypes) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "setAllowedNetworkTypes");
-
-        SubscriptionManager.setSubscriptionProperty(subId,
-                SubscriptionManager.ALLOWED_NETWORK_TYPES,
-                String.valueOf(allowedNetworkTypes));
-
-        int preferredNetworkMode = Settings.Global.getInt(mApp.getContentResolver(),
-                Settings.Global.PREFERRED_NETWORK_MODE + subId,
-                RILConstants.PREFERRED_NETWORK_MODE);
-        return setPreferredNetworkType(subId, preferredNetworkMode);
-    }
-
-    /**
      * Get the allowed network types for certain reason.
      *
      * @param subId the id of the subscription.
@@ -5609,21 +6053,74 @@
     }
 
     /**
-     * Get the effective allowed network types on the device.
-     * This API will return an intersection of allowed network types for all reasons,
-     * including the configuration done through setAllowedNetworkTypes
-     *
-     * @param subId the id of the subscription.
-     * @return the allowed network types
+     * Enable/Disable E-UTRA-NR Dual Connectivity
+     * @param subId subscription id of the sim card
+     * @param nrDualConnectivityState expected NR dual connectivity state
+     * This can be passed following states
+     * <ol>
+     * <li>Enable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_ENABLE}
+     * <li>Disable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE}
+     * <li>Disable NR dual connectivity and force secondary cell to be released
+     * {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE}
+     * </ol>
+     * @return operation result.
      */
     @Override
-    public long getEffectiveAllowedNetworkTypes(int subId) {
-        TelephonyPermissions
-                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
-                        mApp, subId, "getEffectiveAllowedNetworkTypes");
+    public int setNrDualConnectivityState(int subId,
+            @TelephonyManager.NrDualConnectivityState int nrDualConnectivityState) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "enableNRDualConnectivity");
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
         final long identity = Binder.clearCallingIdentity();
         try {
-            return getPhoneFromSubId(subId).getEffectiveAllowedNetworkTypes();
+            int result = (int) sendRequest(CMD_ENABLE_NR_DUAL_CONNECTIVITY,
+                    nrDualConnectivityState, subId,
+                    workSource);
+            if (DBG) log("enableNRDualConnectivity result: " + result);
+            return result;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Is E-UTRA-NR Dual Connectivity enabled
+     * @return true if dual connectivity is enabled else false
+     */
+    @Override
+    public boolean isNrDualConnectivityEnabled(int subId) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "isNRDualConnectivityEnabled");
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            boolean isEnabled = (boolean) sendRequest(CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED,
+                    null, subId, workSource);
+            if (DBG) log("isNRDualConnectivityEnabled: " + isEnabled);
+            return isEnabled;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * get carrier bandwidth per primary and secondary carrier
+     * @param subId subscription id of the sim card
+     * @return CarrierBandwidth with bandwidth of both primary and secondary carrier..
+     */
+    @Override
+    public CarrierBandwidth getCarrierBandwidth(int subId) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "isNRDualConnectivityEnabled");
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            CarrierBandwidth carrierBandwidth =
+                    getPhoneFromSubId(subId).getCarrierBandwidth();
+            if (DBG) log("getCarrierBandwidth: " + carrierBandwidth);
+            return carrierBandwidth;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5640,16 +6137,27 @@
      */
     @Override
     public boolean setAllowedNetworkTypesForReason(int subId,
-            @TelephonyManager.AllowedNetworkTypesReason int reason, long allowedNetworkTypes) {
+            @TelephonyManager.AllowedNetworkTypesReason int reason,
+            @TelephonyManager.NetworkTypeBitMask long allowedNetworkTypes) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "setAllowedNetworkTypesForReason");
+        if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
+            Rlog.e(LOG_TAG, "Invalid allowed network type reason: " + reason);
+            return false;
+        }
+
+        if (DBG) {
+            log("setAllowedNetworkTypesForReason: " + reason
+                    + " value: " + allowedNetworkTypes);
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
-            getPhoneFromSubId(subId).setAllowedNetworkTypes(reason, allowedNetworkTypes);
-            int preferredNetworkMode = Settings.Global.getInt(mApp.getContentResolver(),
-                    Settings.Global.PREFERRED_NETWORK_MODE + subId,
-                    RILConstants.PREFERRED_NETWORK_MODE);
-            return setPreferredNetworkType(subId, preferredNetworkMode);
+            Boolean success = (Boolean) sendRequest(
+                    CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON,
+                    new Pair<Integer, Long>(reason, allowedNetworkTypes), subId);
+
+            if (DBG) log("setAllowedNetworkTypesForReason: " + (success ? "ok" : "fail"));
+            return success;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5679,33 +6187,6 @@
     }
 
     /**
-     * Set mobile data enabled
-     * Used by the user through settings etc to turn on/off mobile data
-     *
-     * @param enable {@code true} turn turn data on, else {@code false}
-     */
-    @Override
-    public void setUserDataEnabled(int subId, boolean enable) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "setUserDataEnabled");
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            int phoneId = mSubscriptionController.getPhoneId(subId);
-            if (DBG) log("setUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
-            Phone phone = PhoneFactory.getPhone(phoneId);
-            if (phone != null) {
-                if (DBG) log("setUserDataEnabled: subId=" + subId + " enable=" + enable);
-                phone.getDataEnabledSettings().setUserDataEnabled(enable);
-            } else {
-                loge("setUserDataEnabled: no phone found. Invalid subId=" + subId);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
      * Enable or disable always reporting signal strength changes from radio.
      *
      * @param isEnable {@code true} for enabling; {@code false} for disabling.
@@ -5795,7 +6276,18 @@
      */
     @Override
     public boolean isDataEnabled(int subId) {
-        enforceReadPrivilegedPermission("isDataEnabled");
+        try {
+            try {
+                mApp.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.ACCESS_NETWORK_STATE,
+                        null);
+            } catch (Exception e) {
+                mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
+                        "isDataEnabled");
+            }
+        } catch (Exception e) {
+            enforceReadPrivilegedPermission("isDataEnabled");
+        }
 
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -5815,6 +6307,53 @@
         }
     }
 
+    /**
+     * Check if data is enabled for a specific reason
+     * @param subId Subscription index
+     * @param reason the reason the data enable change is taking place
+     * @return {@code true} if the overall data is enabled; {@code false} if not.
+     */
+    @Override
+    public boolean isDataEnabledForReason(int subId,
+            @TelephonyManager.DataEnabledReason int reason) {
+        try {
+            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
+                    null);
+        } catch (Exception e) {
+            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
+                    "isDataEnabledForReason");
+        }
+
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            int phoneId = mSubscriptionController.getPhoneId(subId);
+            if (DBG) {
+                log("isDataEnabledForReason: subId=" + subId + " phoneId=" + phoneId
+                        + " reason=" + reason);
+            }
+            Phone phone = PhoneFactory.getPhone(phoneId);
+            if (phone != null) {
+                boolean retVal;
+                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 {
+                if (DBG) {
+                    loge("isDataEnabledForReason: no phone subId="
+                            + subId + " retVal=false");
+                }
+                return false;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid,
             Phone phone) {
         if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) {
@@ -5832,7 +6371,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            int subId = phone.getSubId();
+            if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+                // A test override is in place for the privileges for this subId, so don't try to
+                // read the subscription privileges.
+                return privilegeFromSim;
+            }
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
             SubscriptionManager subManager = (SubscriptionManager)
                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
             for (String pkg : packages) {
@@ -5855,7 +6400,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            int subId = phone.getSubId();
+            if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+                // A test override is in place for the privileges for this subId, so don't try to
+                // read the subscription privileges.
+                return privilegeFromSim;
+            }
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
             SubscriptionManager subManager = (SubscriptionManager)
                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
             return subManager.canManageSubscription(subInfo, pkgName)
@@ -6007,18 +6558,59 @@
         final Phone phone = getPhone(subId);
         UiccCard card = phone == null ? null : phone.getUiccCard();
         if (card == null) {
-            loge("getIccId: No UICC");
             return null;
         }
         String iccId = card.getIccId();
         if (TextUtils.isEmpty(iccId)) {
-            loge("getIccId: ICC ID is null or empty.");
             return null;
         }
         return iccId;
     }
 
     @Override
+    public void setCallComposerStatus(int subId, int status) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Phone phone = getPhone(subId);
+            if (phone != null) {
+                Phone defaultPhone = phone.getImsPhone();
+                if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
+                    ImsPhone imsPhone = (ImsPhone) defaultPhone;
+                    imsPhone.setCallComposerStatus(status);
+                    ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
+                            .updateImsServiceConfig();
+                }
+            }
+        } catch (ImsException e) {
+            throw new ServiceSpecificException(e.getCode());
+        }  finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public int getCallComposerStatus(int subId) {
+        enforceReadPrivilegedPermission("getCallComposerStatus");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Phone phone = getPhone(subId);
+            if (phone != null) {
+                Phone defaultPhone = phone.getImsPhone();
+                if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
+                    ImsPhone imsPhone = (ImsPhone) defaultPhone;
+                    return imsPhone.getCallComposerStatus();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return TelephonyManager.CALL_COMPOSER_STATUS_OFF;
+    }
+
+    @Override
     public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
             String number) {
         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
@@ -6326,6 +6918,14 @@
     @Override
     public int getRadioAccessFamily(int phoneId, String callingPackage) {
         Phone phone = PhoneFactory.getPhone(phoneId);
+        try {
+            TelephonyPermissions
+                    .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                            mApp, phone.getSubId(), "getRadioAccessFamily");
+        } catch (SecurityException e) {
+            EventLog.writeEvent(0x534e4554, "150857259", -1, "Missing Permission");
+            throw e;
+        }
         int raf = RadioAccessFamily.RAF_UNKNOWN;
         if (phone == null) {
             return raf;
@@ -6343,6 +6943,99 @@
     }
 
     @Override
+    public void uploadCallComposerPicture(int subscriptionId, String callingPackage,
+            String contentType, ParcelFileDescriptor fd, ResultReceiver callback) {
+        try {
+            if (!Objects.equals(mApp.getPackageManager().getPackageUid(callingPackage, 0),
+                    Binder.getCallingUid())) {
+                throw new SecurityException("Package uid and package name do not match: "
+                        + "uid=" + Binder.getCallingUid() + ", packageName=" + callingPackage);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new SecurityException("Package name invalid:" + callingPackage);
+        }
+        RoleManager rm = mApp.getSystemService(RoleManager.class);
+        List<String> dialerRoleHolders = rm.getRoleHolders(RoleManager.ROLE_DIALER);
+        if (!dialerRoleHolders.contains(callingPackage)) {
+            throw new SecurityException("App must be the dialer role holder to"
+                    + " upload a call composer pic");
+        }
+
+        Executors.newSingleThreadExecutor().execute(() -> {
+            ByteArrayOutputStream output = new ByteArrayOutputStream(
+                    (int) TelephonyManager.getMaximumCallComposerPictureSize());
+            InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+            boolean readUntilEnd = false;
+            int totalBytesRead = 0;
+            byte[] buffer = new byte[16 * 1024];
+            while (true) {
+                int numRead;
+                try {
+                    numRead = input.read(buffer);
+                } catch (IOException e) {
+                    try {
+                        fd.checkError();
+                        callback.send(TelephonyManager.CallComposerException.ERROR_INPUT_CLOSED,
+                                null);
+                    } catch (IOException e1) {
+                        // This means that the other side closed explicitly with an error. If this
+                        // happens, log and ignore.
+                        loge("Remote end of call composer picture pipe closed: " + e1);
+                    }
+                    break;
+                }
+                if (numRead == -1) {
+                    readUntilEnd = true;
+                    break;
+                }
+                totalBytesRead += numRead;
+                if (totalBytesRead > TelephonyManager.getMaximumCallComposerPictureSize()) {
+                    loge("Too many bytes read for call composer picture: " + totalBytesRead);
+                    try {
+                        input.close();
+                    } catch (IOException e) {
+                        // ignore
+                    }
+                    break;
+                }
+                output.write(buffer, 0, numRead);
+            }
+            // Generally, the remote end will close the file descriptors. The only case where we
+            // close is above, where the picture size is too big.
+
+            try {
+                fd.checkError();
+            } catch (IOException e) {
+                loge("Remote end for call composer closed with an error: " + e);
+                return;
+            }
+
+            if (!readUntilEnd) {
+                loge("Did not finish reading entire image; aborting");
+                return;
+            }
+
+            ImageData imageData = new ImageData(output.toByteArray(), contentType, null);
+            CallComposerPictureManager.getInstance(mApp, subscriptionId).handleUploadToServer(
+                    new CallComposerPictureTransfer.Factory() {},
+                    imageData,
+                    (result) -> {
+                        if (result.first != null) {
+                            ParcelUuid parcelUuid = new ParcelUuid(result.first);
+                            Bundle outputResult = new Bundle();
+                            outputResult.putParcelable(
+                                    TelephonyManager.KEY_CALL_COMPOSER_PICTURE_HANDLE, parcelUuid);
+                            callback.send(TelephonyManager.CallComposerException.SUCCESS,
+                                    outputResult);
+                        } else {
+                            callback.send(result.second, null);
+                        }
+                    }
+            );
+        });
+    }
+
+    @Override
     public void enableVideoCalling(boolean enable) {
         final Phone defaultPhone = getDefaultPhone();
         enforceModifyPermission();
@@ -6553,6 +7246,8 @@
 
     @Override
     public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
+        enforceReadPrivilegedPermission("getPhoneAccountHandleForSubscriptionId, "
+                + "subscriptionId: " + subscriptionId);
         final long identity = Binder.clearCallingIdentity();
         try {
             Phone phone = getPhone(subscriptionId);
@@ -6629,9 +7324,18 @@
         try {
             if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
-                setUserDataEnabled(subId, getDefaultDataEnabled());
+                setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_USER,
+                        getDefaultDataEnabled());
                 setNetworkSelectionModeAutomatic(subId);
-                setPreferredNetworkType(subId, getDefaultNetworkType(subId));
+                setAllowedNetworkTypesForReason(subId,
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
+                        RadioAccessFamily.getRafFromNetworkType(getDefaultNetworkType(subId)));
+                setAllowedNetworkTypesForReason(subId,
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
+                        RadioAccessFamily.getRafFromNetworkType(getDefaultNetworkType(subId)));
+                setAllowedNetworkTypesForReason(subId,
+                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
+                        RadioAccessFamily.getRafFromNetworkType(getDefaultNetworkType(subId)));
                 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
                 CarrierInfoManager.deleteAllCarrierKeysForImsiEncryption(mApp);
             }
@@ -6725,7 +7429,7 @@
     }
 
     private final ModemActivityInfo mLastModemActivityInfo =
-            new ModemActivityInfo(0, 0, 0, new int[0], 0);
+            new ModemActivityInfo(0, 0, 0, new int[ModemActivityInfo.getNumTxPowerLevels()], 0);
 
     /**
      * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
@@ -6755,12 +7459,9 @@
             return false;
         }
         int activityDurationMs =
-            (int) (info.getTimestamp() - mLastModemActivityInfo.getTimestamp());
-        int totalTxTimeMs = 0;
-        int[] txTimeMs = info.getTransmitTimeMillis();
-        for (int i = 0; i < info.getTransmitPowerInfo().size(); i++) {
-            totalTxTimeMs += txTimeMs[i];
-        }
+                (int) (info.getTimestampMillis() - mLastModemActivityInfo.getTimestampMillis());
+        int totalTxTimeMs = Arrays.stream(info.getTransmitTimeMillis()).sum();
+
         return (info.isValid()
             && (info.getSleepTimeMillis() <= activityDurationMs)
             && (info.getIdleTimeMillis() <= activityDurationMs)
@@ -6790,6 +7491,8 @@
                                 .setMethod("getServiceStateForSubscriber")
                                 .setLogAsInfo(true)
                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
                                 .build());
 
         LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
@@ -6802,6 +7505,8 @@
                                 .setMethod("getServiceStateForSubscriber")
                                 .setLogAsInfo(true)
                                 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                .setMinSdkVersionForFine(Integer.MAX_VALUE)
+                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
                                 .build());
         // We don't care about hard or soft here -- all we need to know is how much info to scrub.
         boolean hasFinePermission =
@@ -6809,10 +7514,20 @@
         boolean hasCoarsePermission =
                 coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
 
+        final Phone phone = getPhone(subId);
+        if (phone == null) {
+            return null;
+        }
+
         final long identity = Binder.clearCallingIdentity();
+
+        boolean isCallingPackageDataService = phone.getDataServicePackages()
+                .contains(callingPackage);
         try {
-            final Phone phone = getPhone(subId);
-            if (phone == null) {
+            // isActiveSubId requires READ_PHONE_STATE, which we already check for above
+            if (!mSubscriptionController.isActiveSubId(subId, callingPackage, callingFeatureId)) {
+                Rlog.d(LOG_TAG,
+                        "getServiceStateForSubscriber returning null for inactive subId=" + subId);
                 return null;
             }
 
@@ -6820,7 +7535,7 @@
 
             // Scrub out the location info in ServiceState depending on what level of access
             // the caller has.
-            if (hasFinePermission) return ss;
+            if (hasFinePermission || isCallingPackageDataService) return ss;
             if (hasCoarsePermission) return ss.createLocationInfoSanitizedCopy(false);
             return ss.createLocationInfoSanitizedCopy(true);
         } finally {
@@ -7149,31 +7864,6 @@
     }
 
     /**
-     * Action set from carrier signalling broadcast receivers to enable/disable metered apns
-     * @param subId the subscription ID that this action applies to.
-     * @param enabled control enable or disable metered apns.
-     * {@hide}
-     */
-    @Override
-    public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
-        enforceModifyPermission();
-        final Phone phone = getPhone(subId);
-
-        final long identity = Binder.clearCallingIdentity();
-        if (phone == null) {
-            loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
-            return;
-        }
-        try {
-            phone.carrierActionSetMeteredApnsEnabled(enabled);
-        } catch (Exception e) {
-            Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
      * Action set from carrier signalling broadcast receivers to enable/disable radio
      * @param subId the subscription ID that this action applies to.
      * @param enabled control enable or disable radio.
@@ -7274,20 +7964,36 @@
     }
 
     /**
-     * Policy control of data connection. Usually used when data limit is passed.
-     * @param enabled True if enabling the data, otherwise disabling.
+     * Policy control of data connection with reason {@@TelephonyManager.DataEnabledReason}
      * @param subId Subscription index
-     * {@hide}
+     * @param reason the reason the data enable change is taking place
+     * @param enabled True if enabling the data, otherwise disabling.
+     * @hide
      */
     @Override
-    public void setPolicyDataEnabled(boolean enabled, int subId) {
-        enforceModifyPermission();
+    public void setDataEnabledForReason(int subId, @TelephonyManager.DataEnabledReason int reason,
+            boolean enabled) {
+        if (reason == TelephonyManager.DATA_ENABLED_REASON_USER
+                || reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
+            try {
+                TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+                        mApp, subId, "setDataEnabledForReason");
+            } catch (SecurityException se) {
+                enforceModifyPermission();
+            }
+        } else {
+            enforceModifyPermission();
+        }
 
         final long identity = Binder.clearCallingIdentity();
         try {
             Phone phone = getPhone(subId);
             if (phone != null) {
-                phone.getDataEnabledSettings().setPolicyDataEnabled(enabled);
+                if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
+                    phone.carrierActionSetMeteredApnsEnabled(enabled);
+                } else {
+                    phone.getDataEnabledSettings().setDataEnabled(reason, enabled);
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -7345,7 +8051,37 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             if (phone != null) {
-                phone.setSimPowerState(state, workSource);
+                phone.setSimPowerState(state, null, workSource);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Set SIM card power state.
+     *
+     * @param slotIndex SIM slot id.
+     * @param state  State of SIM (power down, power up, pass through)
+     * @param callback  callback to trigger after success or failure
+     * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
+     * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
+     * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
+     *
+     **/
+    @Override
+    public void setSimPowerStateForSlotWithCallback(int slotIndex, int state,
+            IIntegerConsumer callback) {
+        enforceModifyPermission();
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (phone != null) {
+                Pair<Integer, IIntegerConsumer> arguments = Pair.create(state, callback);
+                sendRequestAsync(CMD_SET_SIM_POWER, arguments, phone, workSource);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -7450,17 +8186,19 @@
      */
     @Override
     public boolean isDataRoamingEnabled(int subId) {
-        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
-                null /* message */);
+        try {
+            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
+                    null);
+        } catch (Exception e) {
+            TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
+                    mApp, subId, "isDataRoamingEnabled");
+        }
 
         boolean isEnabled = false;
         final long identity = Binder.clearCallingIdentity();
         try {
             Phone phone = getPhone(subId);
             isEnabled =  phone != null ? phone.getDataRoamingEnabled() : false;
-        } catch (Exception e) {
-            TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
-                    mApp, subId, "isDataRoamingEnabled");
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -7703,7 +8441,7 @@
     private boolean getDefaultDataRoamingEnabled(int subId) {
         final CarrierConfigManager configMgr = (CarrierConfigManager)
                 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(true);
+        boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
         isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
                 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
         return isDataRoamingEnabled;
@@ -7736,6 +8474,11 @@
             }
             phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
                     carrierPrivilegeRules, apn);
+            if (carrierPrivilegeRules == null) {
+                mCarrierPrivilegeTestOverrideSubIds.remove(subId);
+            } else {
+                mCarrierPrivilegeTestOverrideSubIds.add(subId);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -7803,6 +8546,20 @@
     }
 
     @Override
+    public int getCdmaSubscriptionMode(int subId) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "getCdmaSubscriptionMode");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return (int) sendRequest(CMD_GET_CDMA_SUBSCRIPTION_MODE, null /* argument */, subId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public boolean setCdmaSubscriptionMode(int subId, int mode) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "setCdmaSubscriptionMode");
@@ -7852,11 +8609,9 @@
         try {
             for (Phone phone: PhoneFactory.getPhones()) {
                 if (phone.getEmergencyNumberTracker() != null
-                        && phone.getEmergencyNumberTracker() != null) {
-                    if (phone.getEmergencyNumberTracker().isEmergencyNumber(
-                            number, exactMatch)) {
-                        return true;
-                    }
+                        && phone.getEmergencyNumberTracker()
+                                .isEmergencyNumber(number, exactMatch)) {
+                    return true;
                 }
             }
             return false;
@@ -8093,7 +8848,7 @@
             loge("isMultiSimSupportedInternal: no static configuration available");
             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
-        if (staticCapability.logicalModemList.size() < 2) {
+        if (staticCapability.getLogicalModemList().size() < 2) {
             loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
@@ -8237,7 +8992,7 @@
      *  1) user data is turned on, or
      *  2) APN is un-metered for this subscription, or
      *  3) APN type is whitelisted. E.g. MMS is whitelisted if
-     *  {@link TelephonyManager#setAlwaysAllowMmsData} is turned on.
+     *  {@link TelephonyManager#MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled.
      *
      * @return whether data is allowed for a apn type.
      *
@@ -8311,6 +9066,24 @@
     }
 
     @Override
+    public List<RadioAccessSpecifier> getSystemSelectionChannels(int subId) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "getSystemSelectionChannels");
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            List<RadioAccessSpecifier> specifiers =
+                    (List<RadioAccessSpecifier>) sendRequest(CMD_GET_SYSTEM_SELECTION_CHANNELS,
+                    null, subId, workSource);
+            if (DBG) log("getSystemSelectionChannels: " + specifiers);
+            return specifiers;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public boolean isMvnoMatched(int subId, int mvnoType, @NonNull String mvnoMatchData) {
         enforceReadPrivilegedPermission("isMvnoMatched");
         IccRecords iccRecords = UiccController.getInstance().getIccRecords(
@@ -8349,6 +9122,11 @@
         //TODO investigate if this API should require proper permission check in R b/133791609
         final long identity = Binder.clearCallingIdentity();
         try {
+            String carrierUAProfUrl = mApp.getCarrierConfigForSubId(subId).getString(
+                    CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING);
+            if (!TextUtils.isEmpty(carrierUAProfUrl)) {
+                return carrierUAProfUrl;
+            }
             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
                     .getString(com.android.internal.R.string.config_mms_user_agent_profile_url);
         } finally {
@@ -8361,6 +9139,11 @@
         //TODO investigate if this API should require proper permission check in R b/133791609
         final long identity = Binder.clearCallingIdentity();
         try {
+            String carrierUserAgent = mApp.getCarrierConfigForSubId(subId).getString(
+                    CarrierConfigManager.KEY_MMS_USER_AGENT_STRING);
+            if (!TextUtils.isEmpty(carrierUserAgent)) {
+                return carrierUserAgent;
+            }
             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
                     .getString(com.android.internal.R.string.config_mms_user_agent);
         } finally {
@@ -8369,55 +9152,54 @@
     }
 
     @Override
-    public boolean setDataAllowedDuringVoiceCall(int subId, boolean allow) {
-        enforceModifyPermission();
+    public boolean isMobileDataPolicyEnabled(int subscriptionId, int policy) {
+        enforceReadPrivilegedPermission("isMobileDataPolicyEnabled");
 
-        // Now that all security checks passes, perform the operation as ourselves.
         final long identity = Binder.clearCallingIdentity();
         try {
-            Phone phone = getPhone(subId);
+            Phone phone = getPhone(subscriptionId);
             if (phone == null) return false;
 
-            return phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(allow);
+            switch (policy) {
+                case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
+                    return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
+                case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
+                    return phone.getDataEnabledSettings().isMmsAlwaysAllowed();
+                default:
+                    throw new IllegalArgumentException(policy + " is not a valid policy");
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     @Override
-    public boolean isDataAllowedInVoiceCall(int subId) {
-        enforceReadPrivilegedPermission("isDataAllowedInVoiceCall");
-
-        // Now that all security checks passes, perform the operation as ourselves.
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            Phone phone = getPhone(subId);
-            if (phone == null) return false;
-
-            return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    @Override
-    public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
+    public void setMobileDataPolicyEnabled(int subscriptionId, int policy,
+            boolean enabled) {
         enforceModifyPermission();
 
-        // Now that all security checks passes, perform the operation as ourselves.
         final long identity = Binder.clearCallingIdentity();
         try {
-            Phone phone = getPhone(subId);
-            if (phone == null) return false;
+            Phone phone = getPhone(subscriptionId);
+            if (phone == null) return;
 
-            return phone.getDataEnabledSettings().setAlwaysAllowMmsData(alwaysAllow);
+            switch (policy) {
+                case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
+                    phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(enabled);
+                    break;
+                case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
+                    phone.getDataEnabledSettings().setAlwaysAllowMmsData(enabled);
+                    break;
+                default:
+                    throw new IllegalArgumentException(policy + " is not a valid policy");
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * Updates whether conference event pacakge handling is enabled.
+     * Updates whether conference event package handling is enabled.
      * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
      *                                 otherwise.
      */
@@ -8456,15 +9238,19 @@
             isCompressed) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "notifyRcsAutoConfigurationReceived");
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+        if (!isImsAvailableOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "IMS not available on device.");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
         try {
-            IImsConfig configBinder = getImsConfig(getSlotIndex(subId), ImsFeature.FEATURE_RCS);
-            if (configBinder == null) {
-                Rlog.e(LOG_TAG, "null result for getImsConfig");
-            } else {
-                configBinder.notifyRcsAutoConfigurationReceived(config, isCompressed);
-            }
-        } catch (RemoteException e) {
-            Rlog.e(LOG_TAG, "fail to getImsConfig " + e.getMessage());
+            RcsProvisioningMonitor.getInstance().updateConfig(subId, config, isCompressed);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -8594,4 +9380,691 @@
     public boolean canConnectTo5GInDsdsMode() {
         return mApp.getResources().getBoolean(R.bool.config_5g_connection_in_dsds_mode);
     }
+
+    @Override
+    public @NonNull List<String> getEquivalentHomePlmns(int subId, String callingPackage,
+            String callingFeatureId) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, callingFeatureId, "getEquivalentHomePlmns")) {
+            throw new SecurityException("Requires READ_PHONE_STATE permission.");
+        }
+
+        Phone phone = getPhone(subId);
+        if (phone == null) {
+            throw new RuntimeException("phone is not available");
+        }
+        // Now that all security checks passes, perform the operation as ourselves.
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return phone.getEquivalentHomePlmns();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean isRadioInterfaceCapabilitySupported(
+            @NonNull @TelephonyManager.RadioInterfaceCapability String capability) {
+        RadioInterfaceCapabilities radioInterfaceCapabilities =
+                mPhoneConfigurationManager.getRadioInterfaceCapabilities();
+        if (radioInterfaceCapabilities == null) {
+            throw new RuntimeException("radio interface capabilities are not available");
+        } else {
+            return radioInterfaceCapabilities.isSupported(capability);
+        }
+    }
+
+    @Override
+    public void bootstrapAuthenticationRequest(int subId, int appType, Uri nafUrl,
+            UaSecurityProtocolIdentifier securityProtocol,
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback)
+            throws RemoteException {
+        enforceModifyPermission();
+        if (DBG) {
+            log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
+                    + appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
+                    + ", forceBootStrapping:" + forceBootStrapping + ", callback:" + callback);
+        }
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)
+                || appType < TelephonyManager.APPTYPE_UNKNOWN
+                || appType > TelephonyManager.APPTYPE_ISIM
+                || nafUrl == null || securityProtocol == null || callback == null) {
+            Log.d(LOG_TAG, "bootstrapAuthenticationRequest failed due to invalid parameters");
+            if (callback != null) {
+                try {
+                    callback.onAuthenticationFailure(
+                            0, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED);
+                } catch (RemoteException exception) {
+                    log("Fail to notify onAuthenticationFailure due to " + exception);
+                }
+                return;
+            }
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            getGbaManager(subId).bootstrapAuthenticationRequest(
+                    new GbaAuthRequest(subId, appType, nafUrl, securityProtocol.toByteArray(),
+                    forceBootStrapping, callback));
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Attempts to set the radio power state for thermal reason. This does not guarantee that the
+     * requested radio power state will actually be set. See {@link
+     * PhoneInternalInterface#setRadioPowerForReason} for more details.
+     *
+     * @param subId the subscription ID of the phone requesting to set the radio power state.
+     * @param enable {@code true} if trying to turn radio on.
+     * @return {@code true} if phone setRadioPowerForReason was called. Otherwise, returns {@code
+     * false}.
+     */
+    private boolean setRadioPowerForThermal(int subId, boolean enable) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            phone.setRadioPowerForReason(enable, Phone.RADIO_POWER_REASON_THERMAL);
+            return true;
+        }
+        return false;
+    }
+
+    private int handleDataThrottlingRequest(int subId,
+            DataThrottlingRequest dataThrottlingRequest) {
+        // Ensure that radio is on. If not able to power on due to phone being unavailable, return
+        // THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+        if (!setRadioPowerForThermal(subId, true)) {
+            return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+        }
+
+        setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true);
+
+        int thermalMitigationResult =
+                (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
+        if (thermalMitigationResult == SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS) {
+            throw new IllegalArgumentException("modem returned INVALID_ARGUMENTS");
+        }
+        return thermalMitigationResult;
+    }
+
+    /**
+     * Thermal mitigation request to control functionalities at modem.
+     *
+     * @param subId the id of the subscription.
+     * @param thermalMitigationRequest holds all necessary information to be passed down to modem.
+     *
+     * @return thermalMitigationResult enum as defined in android.telephony.Annotation.
+     */
+    @Override
+    @ThermalMitigationResult
+    public int sendThermalMitigationRequest(
+            int subId,
+            ThermalMitigationRequest thermalMitigationRequest) throws IllegalArgumentException {
+        enforceModifyPermission();
+
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        final long identity = Binder.clearCallingIdentity();
+
+        int thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
+        try {
+            int thermalMitigationAction = thermalMitigationRequest.getThermalMitigationAction();
+            switch (thermalMitigationAction) {
+                case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
+                    thermalMitigationResult =
+                        handleDataThrottlingRequest(subId,
+                                thermalMitigationRequest.getDataThrottlingRequest());
+                    break;
+                case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
+                    if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
+                        throw new IllegalArgumentException("dataThrottlingRequest must be null for "
+                                + "ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY");
+                    }
+
+                    // Ensure that radio is on. If not able to power on due to phone being
+                    // unavailable, return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+                    if (!setRadioPowerForThermal(subId, true)) {
+                        thermalMitigationResult =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                        break;
+                    }
+
+                    setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL,
+                            false);
+                    thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+                    break;
+                case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF:
+                    if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
+                        throw new IllegalArgumentException("dataThrottlingRequest  must be null for"
+                                + " ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF");
+                    }
+
+                    TelecomAccountRegistry registry = TelecomAccountRegistry.getInstance(null);
+                    if (registry != null) {
+                        TelephonyConnectionService service =
+                                registry.getTelephonyConnectionService();
+                        Phone phone = getPhone(subId);
+                        if (phone == null) {
+                            thermalMitigationResult =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                            break;
+                        }
+
+                        if (PhoneConstantConversions.convertCallState(phone.getState())
+                                    != TelephonyManager.CALL_STATE_IDLE
+                                    || phone.isInEmergencySmsMode() || phone.isInEcm()
+                                    || (service != null && service.isEmergencyCallPending())) {
+                            String errorMessage = "Phone state is not valid. call state = "
+                                    + PhoneConstantConversions.convertCallState(phone.getState())
+                                    + " isInEmergencySmsMode = " + phone.isInEmergencySmsMode()
+                                    + " isInEmergencyCallbackMode = " + phone.isInEcm();
+                            errorMessage += service == null
+                                    ? " TelephonyConnectionService is null"
+                                    : " isEmergencyCallPending = "
+                                            + service.isEmergencyCallPending();
+                            Log.e(LOG_TAG, errorMessage);
+                            thermalMitigationResult =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
+                            break;
+                        }
+                    } else {
+                        thermalMitigationResult =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                        break;
+                    }
+
+                    // Turn radio off. If not able to power off due to phone being unavailable,
+                    // return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+                    if (!setRadioPowerForThermal(subId, false)) {
+                        thermalMitigationResult =
+                                TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+                        break;
+                    }
+                    thermalMitigationResult =
+                        TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+                    break;
+                default:
+                    throw new IllegalArgumentException("the requested thermalMitigationAction does "
+                            + "not exist. Requested action: " + thermalMitigationAction);
+            }
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "thermalMitigationRequest. Exception e =" + e);
+            thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        if (DBG) {
+            log("thermalMitigationRequest returning with thermalMitigationResult: "
+                    + thermalMitigationResult);
+        }
+
+        return thermalMitigationResult;
+    }
+
+    /**
+     * Set the GbaService Package Name that Telephony will bind to.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @param packageName The name of the package to be replaced with.
+     * @return true if setting the GbaService to bind to succeeded, false if it did not.
+     */
+    @Override
+    public boolean setBoundGbaServiceOverride(int subId, String packageName) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).overrideServicePackage(packageName);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Return the package name of the currently bound GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @return the package name of the GbaService configuration, null if GBA is not supported.
+     */
+    @Override
+    public String getBoundGbaService(int subId) {
+        enforceReadPrivilegedPermission("getBoundGbaServicePackage");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).getServicePackage();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Set the release time for telephony to unbind GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @param interval The release time to unbind GbaService by millisecond.
+     * @return true if setting the GbaService to bind to succeeded, false if it did not.
+     */
+    @Override
+    public boolean setGbaReleaseTimeOverride(int subId, int interval) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).overrideReleaseTime(interval);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Return the release time for telephony to unbind GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @return The release time to unbind GbaService by millisecond.
+     */
+    @Override
+    public int getGbaReleaseTime(int subId) {
+        enforceReadPrivilegedPermission("getGbaReleaseTime");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).getReleaseTime();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private GbaManager getGbaManager(int subId) {
+        GbaManager instance = GbaManager.getInstance(subId);
+        if (instance == null) {
+            String packageName = mApp.getResources().getString(R.string.config_gba_package);
+            int releaseTime = mApp.getResources().getInteger(R.integer.config_gba_release_time);
+            instance = GbaManager.make(mApp, subId, packageName, releaseTime);
+        }
+        return instance;
+    }
+
+    /**
+     * indicate whether the device and the carrier can support
+     * RCS VoLTE single registration.
+     */
+    @Override
+    public boolean isRcsVolteSingleRegistrationCapable(int subId) {
+        enforceReadPrivilegedPermission("isRcsVolteSingleRegistrationCapable");
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            RcsProvisioningMonitor rpm = RcsProvisioningMonitor.getInstance();
+            if (rpm != null) {
+                return rpm.isRcsVolteSingleRegistrationEnabled(subId);
+            }
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Register RCS provisioning callback.
+     */
+    @Override
+    public void registerRcsProvisioningChangedCallback(int subId,
+            IRcsConfigCallback callback) {
+        enforceReadPrivilegedPermission("registerRcsProvisioningChangedCallback");
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+        if (!isImsAvailableOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "IMS not available on device.");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (!RcsProvisioningMonitor.getInstance()
+                    .registerRcsProvisioningChangedCallback(subId, callback)) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "Service not available for the subscription.");
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Unregister RCS provisioning callback.
+     */
+    @Override
+    public void unregisterRcsProvisioningChangedCallback(int subId,
+            IRcsConfigCallback callback) {
+        enforceReadPrivilegedPermission("unregisterRcsProvisioningChangedCallback");
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+        if (!isImsAvailableOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "IMS not available on device.");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            RcsProvisioningMonitor.getInstance()
+                    .unregisterRcsProvisioningChangedCallback(subId, callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * trigger RCS reconfiguration.
+     */
+    public void triggerRcsReconfiguration(int subId) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "triggerRcsReconfiguration");
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+        if (!isImsAvailableOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "IMS not available on device.");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            RcsProvisioningMonitor.getInstance().requestReconfig(subId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Provide the client configuration parameters of the RCS application.
+     */
+    public void setRcsClientConfiguration(int subId, RcsClientConfiguration rcc) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setRcsClientConfiguration");
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+        }
+        if (!isImsAvailableOnDevice()) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "IMS not available on device.");
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+
+        try {
+            IImsConfig configBinder = getImsConfig(getSlotIndex(subId), ImsFeature.FEATURE_RCS);
+            if (configBinder == null) {
+                Rlog.e(LOG_TAG, "null result for setRcsClientConfiguration");
+            } else {
+                configBinder.setRcsClientConfiguration(rcc);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(LOG_TAG, "fail to setRcsClientConfiguration " + e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Overrides the config of RCS VoLTE single registration enabled for the device.
+     */
+    @Override
+    public void setDeviceSingleRegistrationEnabledOverride(String enabledStr) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+                "setDeviceSingleRegistrationEnabledOverride");
+        enforceModifyPermission();
+
+        Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
+                : Boolean.parseBoolean(enabledStr);
+        RcsProvisioningMonitor.getInstance().overrideDeviceSingleRegistrationEnabled(enabled);
+        mApp.imsRcsController.setDeviceSingleRegistrationSupportOverride(enabled);
+    }
+
+    /**
+     * Sends a device to device communication message.  Only usable via shell.
+     * @param message message to send.
+     * @param value message value.
+     */
+    @Override
+    public void sendDeviceToDeviceMessage(int message, int value) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+                "setCarrierSingleRegistrationEnabledOverride");
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            TelephonyConnectionService service =
+                    TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
+            if (service == null) {
+                Rlog.e(LOG_TAG, "sendDeviceToDeviceMessage: not in a call.");
+                return;
+            }
+            service.sendTestDeviceToDeviceMessage(message, value);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+
+    /**
+     * Gets the config of RCS VoLTE single registration enabled for the device.
+     */
+    @Override
+    public boolean getDeviceSingleRegistrationEnabled() {
+        enforceReadPrivilegedPermission("getDeviceSingleRegistrationEnabled");
+        return RcsProvisioningMonitor.getInstance().getDeviceSingleRegistrationEnabled();
+    }
+
+    /**
+     * Overrides the config of RCS VoLTE single registration enabled for the carrier/subscription.
+     */
+    @Override
+    public boolean setCarrierSingleRegistrationEnabledOverride(int subId, String enabledStr) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+                "setCarrierSingleRegistrationEnabledOverride");
+        enforceModifyPermission();
+
+        Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
+                : Boolean.parseBoolean(enabledStr);
+        return RcsProvisioningMonitor.getInstance().overrideCarrierSingleRegistrationEnabled(
+                subId, enabled);
+    }
+
+    /**
+     * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
+     */
+    @Override
+    public boolean getCarrierSingleRegistrationEnabled(int subId) {
+        enforceReadPrivilegedPermission("getCarrierSingleRegistrationEnabled");
+        return RcsProvisioningMonitor.getInstance().getCarrierSingleRegistrationEnabled(subId);
+    }
+
+    /**
+     * Get the mobile provisioning url that is used to launch a browser to allow users to manage
+     * their mobile plan.
+     */
+    @Override
+    public String getMobileProvisioningUrl() {
+        enforceReadPrivilegedPermission("getMobileProvisioningUrl");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getDefaultPhone().getMobileProvisioningUrl();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Get the EAB contact from the EAB database.
+     */
+    @Override
+    public String getContactFromEab(String contact) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getContactFromEab");
+        enforceModifyPermission();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return EabUtil.getContactFromEab(getDefaultPhone().getContext(), contact);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Remove the EAB contacts from the EAB database.
+     */
+    @Override
+    public int removeContactFromEab(int subId, String contacts) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "removeCapabilitiesFromEab");
+        enforceModifyPermission();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return EabUtil.removeContactFromEab(subId, contacts, getDefaultPhone().getContext());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean getDeviceUceEnabled() {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDeviceUceEnabled");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mApp.getDeviceUceEnabled();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void setDeviceUceEnabled(boolean isEnabled) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDeviceUceEnabled");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mApp.setDeviceUceEnabled(isEnabled);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void setSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
+            String callingPackage) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setSignalStrengthUpdateRequest");
+
+        final int callingUid = Binder.getCallingUid();
+        // Verify that tha callingPackage belongs to the calling UID
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(callingUid, callingPackage);
+
+        validateSignalStrengthUpdateRequest(request, callingUid);
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Object result = sendRequest(CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST,
+                    new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
+
+            if (result instanceof IllegalStateException) {
+                throw (IllegalStateException) result;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void clearSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
+            String callingPackage) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "clearSignalStrengthUpdateRequest");
+
+        final int callingUid = Binder.getCallingUid();
+        // Verify that tha callingPackage belongs to the calling UID
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(callingUid, callingPackage);
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Object result = sendRequest(CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST,
+                    new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
+
+            if (result instanceof IllegalStateException) {
+                throw (IllegalStateException) result;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private static void validateSignalStrengthUpdateRequest(SignalStrengthUpdateRequest request,
+            int callingUid) {
+        if (callingUid == Process.PHONE_UID || callingUid == Process.SYSTEM_UID) {
+            // phone/system process do not have further restriction on request
+            return;
+        }
+
+        // Applications has restrictions on how to use the request:
+        // Only system caller can set mIsSystemThresholdReportingRequestedWhileIdle
+        if (request.isSystemThresholdReportingRequestedWhileIdle()) {
+            // This is not system caller which has been checked above
+            throw new IllegalArgumentException(
+                    "Only system can set isSystemThresholdReportingRequestedWhileIdle");
+        }
+
+        for (SignalThresholdInfo info : request.getSignalThresholdInfos()) {
+            // Only system caller can set mHysteresisMs/mHysteresisDb/mIsEnabled.
+            if (info.getHysteresisMs() != SignalThresholdInfo.HYSTERESIS_MS_DISABLED
+                    || info.getHysteresisDb() != SignalThresholdInfo.HYSTERESIS_DB_DISABLED
+                    || info.isEnabled()) {
+                throw new IllegalArgumentException(
+                        "Only system can set hide fields in SignalThresholdInfo");
+            }
+
+            // Thresholds length for each RAN need in range. This has been validated in
+            // SignalThresholdInfo#Builder#setThreshold. Here we prevent apps calling hide method
+            // setThresholdUnlimited (e.g. through reflection) with too short or too long thresholds
+            final int[] thresholds = info.getThresholds();
+            Objects.requireNonNull(thresholds);
+            if (thresholds.length < SignalThresholdInfo.getMinimumNumberOfThresholdsAllowed()
+                    || thresholds.length
+                    > SignalThresholdInfo.getMaximumNumberOfThresholdsAllowed()) {
+                throw new IllegalArgumentException(
+                        "thresholds length is out of range: " + thresholds.length);
+            }
+        }
+    }
+
+    /**
+     * Gets the current phone capability.
+     *
+     * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
+     * @return the PhoneCapability which describes the data connection capability of modem.
+     * It's used to evaluate possible phone config change, for example from single
+     * SIM device to multi-SIM device.
+     */
+    @Override
+    public PhoneCapability getPhoneCapability() {
+        enforceReadPrivilegedPermission("getPhoneCapability");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mPhoneConfigurationManager.getCurrentPhoneCapability();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
 }
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
new file mode 100644
index 0000000..79310ef
--- /dev/null
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -0,0 +1,699 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyRegistryManager;
+import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.RcsConfig;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IRcsConfigCallback;
+import android.telephony.ims.feature.ImsFeature;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.CollectionUtils;
+import com.android.telephony.Rlog;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+
+/**
+ * Class to monitor RCS Provisioning Status
+ */
+public class RcsProvisioningMonitor {
+    private static final String TAG = "RcsProvisioningMonitor";
+    private static final boolean DBG = Build.IS_ENG;
+
+    private static final int EVENT_SUB_CHANGED = 1;
+    private static final int EVENT_DMA_CHANGED = 2;
+    private static final int EVENT_CC_CHANGED  = 3;
+    private static final int EVENT_CONFIG_RECEIVED = 4;
+    private static final int EVENT_RECONFIG_REQUEST = 5;
+    private static final int EVENT_DEVICE_CONFIG_OVERRIDE = 6;
+    private static final int EVENT_CARRIER_CONFIG_OVERRIDE = 7;
+
+    private final PhoneGlobals mPhone;
+    private final Handler mHandler;
+    // Cache the RCS provsioning info and related sub id
+    private final ConcurrentHashMap<Integer, RcsProvisioningInfo> mRcsProvisioningInfos =
+            new ConcurrentHashMap<>();
+    private Boolean mDeviceSingleRegistrationEnabledOverride;
+    private final HashMap<Integer, Boolean> mCarrierSingleRegistrationEnabledOverride =
+            new HashMap<>();
+    private String mDmaPackageName;
+
+    private final CarrierConfigManager mCarrierConfigManager;
+    private final DmaChangedListener mDmaChangedListener;
+    private final SubscriptionManager mSubscriptionManager;
+    private final TelephonyRegistryManager mTelephonyRegistryManager;
+    private final RoleManagerAdapter mRoleManager;
+
+    private static RcsProvisioningMonitor sInstance;
+
+    private final SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener =
+            new SubscriptionManager.OnSubscriptionsChangedListener() {
+        @Override
+        public void onSubscriptionsChanged() {
+            if (!mHandler.hasMessages(EVENT_SUB_CHANGED)) {
+                mHandler.sendEmptyMessage(EVENT_SUB_CHANGED);
+            }
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(
+                    intent.getAction())) {
+                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                logv("Carrier-config changed for sub : " + subId);
+                if (SubscriptionManager.isValidSubscriptionId(subId)
+                        && !mHandler.hasMessages(EVENT_CC_CHANGED)) {
+                    mHandler.sendEmptyMessage(EVENT_CC_CHANGED);
+                }
+            }
+        }
+    };
+
+    private final class DmaChangedListener implements OnRoleHoldersChangedListener {
+        @Override
+        public void onRoleHoldersChanged(String role, UserHandle user) {
+            if (RoleManager.ROLE_SMS.equals(role)) {
+                logv("default messaging application changed.");
+                String packageName = getDmaPackageName();
+                mHandler.sendEmptyMessage(EVENT_DMA_CHANGED);
+            }
+        }
+
+        public void register() {
+            try {
+                mRoleManager.addOnRoleHoldersChangedListenerAsUser(
+                        mPhone.getMainExecutor(), this, UserHandle.SYSTEM);
+            } catch (RuntimeException e) {
+                loge("Could not register dma change listener due to " + e);
+            }
+        }
+
+        public void unregister() {
+            try {
+                mRoleManager.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM);
+            } catch (RuntimeException e) {
+                loge("Could not unregister dma change listener due to " + e);
+            }
+        }
+    }
+
+    private final class MyHandler extends Handler {
+        MyHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_SUB_CHANGED:
+                    onSubChanged();
+                    break;
+                case EVENT_DMA_CHANGED:
+                    onDefaultMessagingApplicationChanged();
+                    break;
+                case EVENT_CC_CHANGED:
+                    onCarrierConfigChange();
+                    break;
+                case EVENT_CONFIG_RECEIVED:
+                    onConfigReceived(msg.arg1, (byte[]) msg.obj, msg.arg2 == 1);
+                    break;
+                case EVENT_RECONFIG_REQUEST:
+                    onReconfigRequest(msg.arg1);
+                    break;
+                case EVENT_DEVICE_CONFIG_OVERRIDE:
+                    Boolean deviceEnabled = (Boolean) msg.obj;
+                    if (!booleanEquals(deviceEnabled, mDeviceSingleRegistrationEnabledOverride)) {
+                        mDeviceSingleRegistrationEnabledOverride = deviceEnabled;
+                        onCarrierConfigChange();
+                    }
+                    break;
+                case EVENT_CARRIER_CONFIG_OVERRIDE:
+                    Boolean carrierEnabledOverride = (Boolean) msg.obj;
+                    Boolean carrierEnabled = mCarrierSingleRegistrationEnabledOverride.put(
+                            msg.arg1, carrierEnabledOverride);
+                    if (!booleanEquals(carrierEnabledOverride, carrierEnabled)) {
+                        onCarrierConfigChange();
+                    }
+                    break;
+                default:
+                    loge("Unhandled event " + msg.what);
+            }
+        }
+    }
+
+    private final class RcsProvisioningInfo {
+        private int mSubId;
+        private volatile int mSingleRegistrationCapability;
+        private volatile byte[] mConfig;
+        private HashSet<IRcsConfigCallback> mRcsConfigCallbacks;
+
+        RcsProvisioningInfo(int subId, int singleRegistrationCapability, byte[] config) {
+            mSubId = subId;
+            mSingleRegistrationCapability = singleRegistrationCapability;
+            mConfig = config;
+            mRcsConfigCallbacks = new HashSet<>();
+        }
+
+        void setSingleRegistrationCapability(int singleRegistrationCapability) {
+            mSingleRegistrationCapability = singleRegistrationCapability;
+        }
+
+        int getSingleRegistrationCapability() {
+            return mSingleRegistrationCapability;
+        }
+
+        void setConfig(byte[] config) {
+            mConfig = config;
+        }
+
+        byte[] getConfig() {
+            return mConfig;
+        }
+
+        boolean addRcsConfigCallback(IRcsConfigCallback cb) {
+            IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
+            if (imsConfig == null) {
+                logd("fail to addRcsConfigCallback as imsConfig is null");
+                return false;
+            }
+
+            synchronized (mRcsConfigCallbacks) {
+                try {
+                    imsConfig.addRcsConfigCallback(cb);
+                } catch (RemoteException e) {
+                    loge("fail to addRcsConfigCallback due to " + e);
+                    return false;
+                }
+                mRcsConfigCallbacks.add(cb);
+            }
+            return true;
+        }
+
+        boolean removeRcsConfigCallback(IRcsConfigCallback cb) {
+            boolean result = true;
+            IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
+
+            synchronized (mRcsConfigCallbacks) {
+                if (imsConfig != null) {
+                    try {
+                        imsConfig.removeRcsConfigCallback(cb);
+                    } catch (RemoteException e) {
+                        loge("fail to removeRcsConfigCallback due to " + e);
+                    }
+                } else {
+                    // Return false but continue to remove the callback
+                    result = false;
+                }
+
+                try {
+                    cb.onRemoved();
+                } catch (RemoteException e) {
+                    logd("Failed to notify onRemoved due to dead binder of " + cb);
+                }
+                mRcsConfigCallbacks.remove(cb);
+            }
+            return result;
+        }
+
+        void clear() {
+            setConfig(null);
+            synchronized (mRcsConfigCallbacks) {
+                IImsConfig imsConfig = getIImsConfig(mSubId, ImsFeature.FEATURE_RCS);
+                Iterator<IRcsConfigCallback> it = mRcsConfigCallbacks.iterator();
+                while (it.hasNext()) {
+                    IRcsConfigCallback cb = it.next();
+                    if (imsConfig != null) {
+                        try {
+                            imsConfig.removeRcsConfigCallback(cb);
+                        } catch (RemoteException e) {
+                            loge("fail to removeRcsConfigCallback due to " + e);
+                        }
+                    }
+                    try {
+                        cb.onRemoved();
+                    } catch (RemoteException e) {
+                        logd("Failed to notify onRemoved due to dead binder of " + cb);
+                    }
+                    it.remove();
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager) {
+        mPhone = app;
+        mHandler = new MyHandler(looper);
+        mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class);
+        mSubscriptionManager = mPhone.getSystemService(SubscriptionManager.class);
+        mTelephonyRegistryManager = mPhone.getSystemService(TelephonyRegistryManager.class);
+        mRoleManager = roleManager;
+        mDmaPackageName = getDmaPackageName();
+        logv("DMA is " + mDmaPackageName);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        mPhone.registerReceiver(mReceiver, filter);
+        mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
+                mSubChangedListener, mSubChangedListener.getHandlerExecutor());
+        mDmaChangedListener = new DmaChangedListener();
+        mDmaChangedListener.register();
+        //initialize configs for all active sub
+        onSubChanged();
+    }
+
+    /**
+     * create an instance
+     */
+    public static RcsProvisioningMonitor make(PhoneGlobals app) {
+        if (sInstance == null) {
+            logd("RcsProvisioningMonitor created.");
+            HandlerThread handlerThread = new HandlerThread(TAG);
+            handlerThread.start();
+            sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(),
+                    new RoleManagerAdapterImpl(app));
+        }
+        return sInstance;
+    }
+
+    /**
+     * get the instance
+     */
+    public static RcsProvisioningMonitor getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * destroy the instance
+     */
+    @VisibleForTesting
+    public void destroy() {
+        logd("destroy it.");
+        mDmaChangedListener.unregister();
+        mTelephonyRegistryManager.removeOnSubscriptionsChangedListener(mSubChangedListener);
+        mPhone.unregisterReceiver(mReceiver);
+        mHandler.getLooper().quit();
+    }
+
+    /**
+     * get the handler
+     */
+    @VisibleForTesting
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    /**
+     * Gets the config for a subscription
+     */
+    @VisibleForTesting
+    public byte[] getConfig(int subId) {
+        if (mRcsProvisioningInfos.containsKey(subId)) {
+            return mRcsProvisioningInfos.get(subId).getConfig();
+        }
+        return null;
+    }
+
+    /**
+     * Returns whether Rcs Volte single registration is enabled for the sub.
+     */
+    public boolean isRcsVolteSingleRegistrationEnabled(int subId) {
+        if (mRcsProvisioningInfos.containsKey(subId)) {
+            return mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability()
+                    == ProvisioningManager.STATUS_CAPABLE;
+        }
+        return false;
+    }
+
+    /**
+     * Called when the new rcs config is received
+     */
+    public void updateConfig(int subId, byte[] config, boolean isCompressed) {
+        mHandler.sendMessage(mHandler.obtainMessage(
+                EVENT_CONFIG_RECEIVED, subId, isCompressed ? 1 : 0, config));
+    }
+
+    /**
+     * Called when the application needs rcs re-config
+     */
+    public void requestReconfig(int subId) {
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_RECONFIG_REQUEST, subId, 0));
+    }
+
+    /**
+     * Called when the application registers rcs provisioning changed callback
+     */
+    public boolean registerRcsProvisioningChangedCallback(int subId, IRcsConfigCallback cb) {
+        RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
+        // should not happen in normal case
+        if (info == null) {
+            logd("fail to register rcs provisioning changed due to subscription unavailable");
+            return false;
+        }
+
+        return info.addRcsConfigCallback(cb);
+    }
+
+    /**
+     * Called when the application unregisters rcs provisioning changed callback
+     */
+    public boolean unregisterRcsProvisioningChangedCallback(int subId, IRcsConfigCallback cb) {
+        RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
+        // should not happen in normal case
+        if (info == null) {
+            logd("fail to unregister rcs provisioning changed due to subscription unavailable");
+            return false;
+        }
+
+        return info.removeRcsConfigCallback(cb);
+    }
+
+    /**
+     * override the device config whether single registration is enabled
+     */
+    public void overrideDeviceSingleRegistrationEnabled(Boolean enabled) {
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_DEVICE_CONFIG_OVERRIDE, enabled));
+    }
+
+    /**
+     * Overrides the carrier config whether single registration is enabled
+     */
+    public boolean overrideCarrierSingleRegistrationEnabled(int subId, Boolean enabled) {
+        if (!mRcsProvisioningInfos.containsKey(subId)) {
+            return false;
+        }
+        mHandler.sendMessage(mHandler.obtainMessage(
+                EVENT_CARRIER_CONFIG_OVERRIDE, subId, 0, enabled));
+        return true;
+    }
+
+    /**
+     * Returns the device config whether single registration is enabled
+     */
+    public boolean getDeviceSingleRegistrationEnabled() {
+        for (RcsProvisioningInfo info : mRcsProvisioningInfos.values()) {
+            return (info.getSingleRegistrationCapability()
+                    & ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE) == 0;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the carrier config whether single registration is enabled
+     */
+    public boolean getCarrierSingleRegistrationEnabled(int subId) {
+        if (mRcsProvisioningInfos.containsKey(subId)) {
+            return (mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability()
+                    & ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE) == 0;
+        }
+        return false;
+    }
+
+    private void onDefaultMessagingApplicationChanged() {
+        final String packageName = getDmaPackageName();
+        if (!TextUtils.equals(mDmaPackageName, packageName)) {
+            mDmaPackageName = packageName;
+            logv("new default messaging application " + mDmaPackageName);
+
+            mRcsProvisioningInfos.forEach((k, v) -> {
+                byte[] cachedConfig = v.getConfig();
+                //clear old callbacks
+                v.clear();
+                if (isAcsUsed(k)) {
+                    logv("acs used, trigger to re-configure.");
+                    notifyRcsAutoConfigurationRemoved(k);
+                    triggerRcsReconfiguration(k);
+                } else {
+                    v.setConfig(cachedConfig);
+                    logv("acs not used, notify.");
+                    notifyRcsAutoConfigurationReceived(k, v.getConfig(), false);
+                }
+            });
+        }
+    }
+
+    private void notifyRcsAutoConfigurationReceived(int subId, byte[] config,
+            boolean isCompressed) {
+        if (config == null) {
+            logd("Rcs config is null for sub : " + subId);
+            return;
+        }
+
+        IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
+        if (imsConfig != null) {
+            try {
+                imsConfig.notifyRcsAutoConfigurationReceived(config, isCompressed);
+            } catch (RemoteException e) {
+                loge("fail to notify rcs configuration received!");
+            }
+        } else {
+            logd("getIImsConfig returns null.");
+        }
+    }
+
+    private void notifyRcsAutoConfigurationRemoved(int subId) {
+        RcsConfig.updateConfigForSub(mPhone, subId, null, true);
+        IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
+        if (imsConfig != null) {
+            try {
+                imsConfig.notifyRcsAutoConfigurationRemoved();
+            } catch (RemoteException e) {
+                loge("fail to notify rcs configuration removed!");
+            }
+        } else {
+            logd("getIImsConfig returns null.");
+        }
+    }
+
+    private void triggerRcsReconfiguration(int subId) {
+        IImsConfig imsConfig = getIImsConfig(subId, ImsFeature.FEATURE_RCS);
+        if (imsConfig != null) {
+            try {
+                imsConfig.triggerRcsReconfiguration();
+            } catch (RemoteException e) {
+                loge("fail to trigger rcs reconfiguration!");
+            }
+        } else {
+            logd("getIImsConfig returns null.");
+        }
+    }
+
+    private boolean isAcsUsed(int subId) {
+        PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId);
+        if (b == null) {
+            return false;
+        }
+        return b.getBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL);
+    }
+
+    private boolean isSingleRegistrationRequiredByCarrier(int subId) {
+        Boolean enabledByOverride = mCarrierSingleRegistrationEnabledOverride.get(subId);
+        if (enabledByOverride != null) {
+            return enabledByOverride;
+        }
+
+        PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId);
+        if (b == null) {
+            return false;
+        }
+        return b.getBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+    }
+
+    private int getSingleRegistrationCapableValue(int subId) {
+        boolean isSingleRegistrationEnabledOnDevice =
+                mDeviceSingleRegistrationEnabledOverride != null
+                ? mDeviceSingleRegistrationEnabledOverride
+                : mPhone.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
+
+        int value = (isSingleRegistrationEnabledOnDevice ? 0
+                : ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE) | (
+                isSingleRegistrationRequiredByCarrier(subId) ? 0
+                : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE);
+        logv("SingleRegistrationCapableValue : " + value);
+        return value;
+    }
+
+    private void onCarrierConfigChange() {
+        logv("onCarrierConfigChange");
+        mRcsProvisioningInfos.forEach((subId, info) -> {
+            int value = getSingleRegistrationCapableValue(subId);
+            if (value != info.getSingleRegistrationCapability()) {
+                info.setSingleRegistrationCapability(value);
+                notifyDmaForSub(subId, value);
+            }
+        });
+    }
+
+    private void onSubChanged() {
+        final int[] activeSubs = mSubscriptionManager.getActiveSubscriptionIdList();
+        final HashSet<Integer> subsToBeDeactivated = new HashSet<>(mRcsProvisioningInfos.keySet());
+
+        for (int i : activeSubs) {
+            subsToBeDeactivated.remove(i);
+            if (!mRcsProvisioningInfos.containsKey(i)) {
+                byte[] data = RcsConfig.loadRcsConfigForSub(mPhone, i, false);
+                int capability = getSingleRegistrationCapableValue(i);
+                logv("new info is created for sub : " + i + ", single registration capability :"
+                        + capability + ", rcs config : " + data);
+                mRcsProvisioningInfos.put(i, new RcsProvisioningInfo(i, capability, data));
+                notifyRcsAutoConfigurationReceived(i, data, false);
+                notifyDmaForSub(i, capability);
+            }
+        }
+
+        subsToBeDeactivated.forEach(i -> {
+            RcsProvisioningInfo info = mRcsProvisioningInfos.remove(i);
+            notifyRcsAutoConfigurationRemoved(i);
+            if (info != null) {
+                info.clear();
+            }
+        });
+    }
+
+    private void onConfigReceived(int subId, byte[] config, boolean isCompressed) {
+        logv("onConfigReceived, subId:" + subId + ", config:"
+                + config + ", isCompressed:" + isCompressed);
+        RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
+        if (info != null) {
+            info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config);
+        }
+        RcsConfig.updateConfigForSub(mPhone, subId, config, isCompressed);
+        notifyRcsAutoConfigurationReceived(subId, config, isCompressed);
+    }
+
+    private void onReconfigRequest(int subId) {
+        logv("onReconfigRequest, subId:" + subId);
+        RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
+        if (info != null) {
+            info.setConfig(null);
+        }
+        notifyRcsAutoConfigurationRemoved(subId);
+        triggerRcsReconfiguration(subId);
+    }
+
+    private void notifyDmaForSub(int subId, int capability) {
+        final Intent intent = new Intent(
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
+        intent.setPackage(mDmaPackageName);
+        intent.putExtra(ProvisioningManager.EXTRA_SUBSCRIPTION_ID, subId);
+        intent.putExtra(ProvisioningManager.EXTRA_STATUS, capability);
+        logv("notify " + intent);
+        mPhone.sendBroadcast(intent);
+    }
+
+    private IImsConfig getIImsConfig(int subId, int feature) {
+        return mPhone.getImsResolver().getImsConfig(
+                SubscriptionManager.getSlotIndex(subId), feature);
+    }
+
+    private String getDmaPackageName() {
+        try {
+            return CollectionUtils.firstOrNull(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS));
+        } catch (RuntimeException e) {
+            loge("Could not get dma name due to " + e);
+            return null;
+        }
+    }
+
+    private static boolean booleanEquals(Boolean val1, Boolean val2) {
+        return (val1 == null && val2 == null)
+                || (Boolean.TRUE.equals(val1) && Boolean.TRUE.equals(val2))
+                || (Boolean.FALSE.equals(val1) && Boolean.FALSE.equals(val2));
+    }
+
+    private static void logv(String msg) {
+        if (DBG) {
+            Rlog.d(TAG, msg);
+        }
+    }
+
+    private static void logd(String msg) {
+        Rlog.d(TAG, msg);
+    }
+
+    private static void loge(String msg) {
+        Rlog.e(TAG, msg);
+    }
+
+    /**
+     * {@link RoleManager} is final so we have to wrap the implementation for testing.
+     */
+    @VisibleForTesting
+    public interface RoleManagerAdapter {
+        /** See {@link RoleManager#getRoleHolders(String)} */
+        List<String> getRoleHolders(String roleName);
+        /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */
+        void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user);
+        /** See {@link RoleManager#removeOnRoleHoldersChangedListenerAsUser} */
+        void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user);
+    }
+
+    private static class RoleManagerAdapterImpl implements RoleManagerAdapter {
+        private final RoleManager mRoleManager;
+
+        private RoleManagerAdapterImpl(Context context) {
+            mRoleManager = context.getSystemService(RoleManager.class);
+        }
+
+        @Override
+        public List<String> getRoleHolders(String roleName) {
+            return mRoleManager.getRoleHolders(roleName);
+        }
+
+        @Override
+        public void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user) {
+            mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user);
+        }
+
+        @Override
+        public void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user) {
+            mRoleManager.removeOnRoleHoldersChangedListenerAsUser(listener, user);
+        }
+    }
+}
diff --git a/src/com/android/phone/SimPhonebookProvider.java b/src/com/android/phone/SimPhonebookProvider.java
new file mode 100644
index 0000000..8307672
--- /dev/null
+++ b/src/com/android/phone/SimPhonebookProvider.java
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.Manifest;
+import android.annotation.TestApi;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.RemoteException;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.ElementaryFiles;
+import android.provider.SimPhonebookContract.SimRecords;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.IIccPhoneBook;
+import com.android.internal.telephony.uicc.AdnRecord;
+import com.android.internal.telephony.uicc.IccConstants;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
+
+/**
+ * Provider for contact records stored on the SIM card.
+ *
+ * @see SimPhonebookContract
+ */
+public class SimPhonebookProvider extends ContentProvider {
+
+    @VisibleForTesting
+    static final String[] ELEMENTARY_FILES_ALL_COLUMNS = {
+            ElementaryFiles.SLOT_INDEX,
+            ElementaryFiles.SUBSCRIPTION_ID,
+            ElementaryFiles.EF_TYPE,
+            ElementaryFiles.MAX_RECORDS,
+            ElementaryFiles.RECORD_COUNT,
+            ElementaryFiles.NAME_MAX_LENGTH,
+            ElementaryFiles.PHONE_NUMBER_MAX_LENGTH
+    };
+    @VisibleForTesting
+    static final String[] SIM_RECORDS_ALL_COLUMNS = {
+            SimRecords.SUBSCRIPTION_ID,
+            SimRecords.ELEMENTARY_FILE_TYPE,
+            SimRecords.RECORD_NUMBER,
+            SimRecords.NAME,
+            SimRecords.PHONE_NUMBER
+    };
+    private static final String TAG = "SimPhonebookProvider";
+    private static final Set<String> ELEMENTARY_FILES_COLUMNS_SET =
+            ImmutableSet.copyOf(ELEMENTARY_FILES_ALL_COLUMNS);
+    private static final Set<String> SIM_RECORDS_WRITABLE_COLUMNS = ImmutableSet.of(
+            SimRecords.NAME, SimRecords.PHONE_NUMBER
+    );
+
+    private static final int WRITE_TIMEOUT_SECONDS = 30;
+
+    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
+
+    private static final int ELEMENTARY_FILES = 100;
+    private static final int ELEMENTARY_FILES_ITEM = 101;
+    private static final int SIM_RECORDS = 200;
+    private static final int SIM_RECORDS_ITEM = 201;
+    private static final int VALIDATE_NAME = 300;
+
+    static {
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                ElementaryFiles.ELEMENTARY_FILES_PATH_SEGMENT, ELEMENTARY_FILES);
+        URI_MATCHER.addURI(
+                SimPhonebookContract.AUTHORITY,
+                ElementaryFiles.ELEMENTARY_FILES_PATH_SEGMENT + "/"
+                        + SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*",
+                ELEMENTARY_FILES_ITEM);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*", SIM_RECORDS);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/#", SIM_RECORDS_ITEM);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/"
+                        + SimRecords.VALIDATE_NAME_PATH_SEGMENT,
+                VALIDATE_NAME);
+    }
+
+    // Only allow 1 write at a time to prevent races; the mutations are based on reads of the
+    // existing list of records which means concurrent writes would be problematic.
+    private final Lock mWriteLock = new ReentrantLock(true);
+    private SubscriptionManager mSubscriptionManager;
+    private Supplier<IIccPhoneBook> mIccPhoneBookSupplier;
+    private ContentNotifier mContentNotifier;
+
+    static int efIdForEfType(@ElementaryFiles.EfType int efType) {
+        switch (efType) {
+            case ElementaryFiles.EF_ADN:
+                return IccConstants.EF_ADN;
+            case ElementaryFiles.EF_FDN:
+                return IccConstants.EF_FDN;
+            case ElementaryFiles.EF_SDN:
+                return IccConstants.EF_SDN;
+            default:
+                return 0;
+        }
+    }
+
+    private static void validateProjection(Set<String> allowed, String[] projection) {
+        if (projection == null || allowed.containsAll(Arrays.asList(projection))) {
+            return;
+        }
+        Set<String> invalidColumns = new LinkedHashSet<>(Arrays.asList(projection));
+        invalidColumns.removeAll(allowed);
+        throw new IllegalArgumentException(
+                "Unsupported columns: " + Joiner.on(",").join(invalidColumns));
+    }
+
+    private static int getRecordSize(int[] recordsSize) {
+        return recordsSize[0];
+    }
+
+    private static int getRecordCount(int[] recordsSize) {
+        return recordsSize[2];
+    }
+
+    /** Returns the IccPhoneBook used to load the AdnRecords. */
+    private static IIccPhoneBook getIccPhoneBook() {
+        return IIccPhoneBook.Stub.asInterface(TelephonyFrameworkInitializer
+                .getTelephonyServiceManager().getIccPhoneBookServiceRegisterer().get());
+    }
+
+    @Override
+    public boolean onCreate() {
+        ContentResolver resolver = getContext().getContentResolver();
+        return onCreate(getContext().getSystemService(SubscriptionManager.class),
+                SimPhonebookProvider::getIccPhoneBook,
+                uri -> resolver.notifyChange(uri, null));
+    }
+
+    @TestApi
+    boolean onCreate(SubscriptionManager subscriptionManager,
+            Supplier<IIccPhoneBook> iccPhoneBookSupplier, ContentNotifier notifier) {
+        if (subscriptionManager == null) {
+            return false;
+        }
+        mSubscriptionManager = subscriptionManager;
+        mIccPhoneBookSupplier = iccPhoneBookSupplier;
+        mContentNotifier = notifier;
+
+        mSubscriptionManager.addOnSubscriptionsChangedListener(MoreExecutors.directExecutor(),
+                new SubscriptionManager.OnSubscriptionsChangedListener() {
+                    boolean mFirstCallback = true;
+                    private int[] mNotifiedSubIds = {};
+
+                    @Override
+                    public void onSubscriptionsChanged() {
+                        if (mFirstCallback) {
+                            mFirstCallback = false;
+                            return;
+                        }
+                        int[] activeSubIds = mSubscriptionManager.getActiveSubscriptionIdList();
+                        if (!Arrays.equals(mNotifiedSubIds, activeSubIds)) {
+                            notifier.notifyChange(SimPhonebookContract.AUTHORITY_URI);
+                            mNotifiedSubIds = Arrays.copyOf(activeSubIds, activeSubIds.length);
+                        }
+                    }
+                });
+        return true;
+    }
+
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs,
+            @Nullable CancellationSignal cancellationSignal) {
+        if (queryArgs != null && (queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_SELECTION)
+                || queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS)
+                || queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_LIMIT))) {
+            throw new IllegalArgumentException(
+                    "A SQL selection was provided but it is not supported by this provider.");
+        }
+        switch (URI_MATCHER.match(uri)) {
+            case ELEMENTARY_FILES:
+                return queryElementaryFiles(projection);
+            case ELEMENTARY_FILES_ITEM:
+                return queryElementaryFilesItem(PhonebookArgs.forElementaryFilesItem(uri),
+                        projection);
+            case SIM_RECORDS:
+                return querySimRecords(PhonebookArgs.forSimRecords(uri, queryArgs), projection);
+            case SIM_RECORDS_ITEM:
+                return querySimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, queryArgs),
+                        projection);
+            case VALIDATE_NAME:
+                return queryValidateName(PhonebookArgs.forValidateName(uri, queryArgs), queryArgs);
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder,
+            @Nullable CancellationSignal cancellationSignal) {
+        throw new UnsupportedOperationException("Only query with Bundle is supported");
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        throw new UnsupportedOperationException("Only query with Bundle is supported");
+    }
+
+    private Cursor queryElementaryFiles(String[] projection) {
+        validateProjection(ELEMENTARY_FILES_COLUMNS_SET, projection);
+        if (projection == null) {
+            projection = ELEMENTARY_FILES_ALL_COLUMNS;
+        }
+
+        MatrixCursor result = new MatrixCursor(projection);
+
+        List<SubscriptionInfo> activeSubscriptions = getActiveSubscriptionInfoList();
+        for (SubscriptionInfo subInfo : activeSubscriptions) {
+            try {
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_ADN);
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_FDN);
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_SDN);
+            } catch (RemoteException e) {
+                // Return an empty cursor. If service to access it is throwing remote
+                // exceptions then it's basically the same as not having a SIM.
+                return new MatrixCursor(projection, 0);
+            }
+        }
+        return result;
+    }
+
+    private Cursor queryElementaryFilesItem(PhonebookArgs args, String[] projection) {
+        validateProjection(ELEMENTARY_FILES_COLUMNS_SET, projection);
+
+        MatrixCursor result = new MatrixCursor(projection);
+        try {
+            addEfToCursor(
+                    result, getActiveSubscriptionInfo(args.subscriptionId), args.efType);
+        } catch (RemoteException e) {
+            // Return an empty cursor. If service to access it is throwing remote
+            // exceptions then it's basically the same as not having a SIM.
+            return new MatrixCursor(projection, 0);
+        }
+        return result;
+    }
+
+    private void addEfToCursor(MatrixCursor result, SubscriptionInfo subscriptionInfo,
+            int efType) throws RemoteException {
+        int[] recordsSize = mIccPhoneBookSupplier.get().getAdnRecordsSizeForSubscriber(
+                subscriptionInfo.getSubscriptionId(), efIdForEfType(efType));
+        addEfToCursor(result, subscriptionInfo, efType, recordsSize);
+    }
+
+    private void addEfToCursor(MatrixCursor result, SubscriptionInfo subscriptionInfo,
+            int efType, int[] recordsSize) throws RemoteException {
+        // If the record count is zero then the SIM doesn't support the elementary file so just
+        // omit it.
+        if (recordsSize == null || getRecordCount(recordsSize) == 0) {
+            return;
+        }
+        MatrixCursor.RowBuilder row = result.newRow()
+                .add(ElementaryFiles.SLOT_INDEX, subscriptionInfo.getSimSlotIndex())
+                .add(ElementaryFiles.SUBSCRIPTION_ID, subscriptionInfo.getSubscriptionId())
+                .add(ElementaryFiles.EF_TYPE, efType)
+                .add(ElementaryFiles.MAX_RECORDS, getRecordCount(recordsSize))
+                .add(ElementaryFiles.NAME_MAX_LENGTH,
+                        AdnRecord.getMaxAlphaTagBytes(getRecordSize(recordsSize)))
+                .add(ElementaryFiles.PHONE_NUMBER_MAX_LENGTH,
+                        AdnRecord.getMaxPhoneNumberDigits());
+        if (result.getColumnIndex(ElementaryFiles.RECORD_COUNT) != -1) {
+            int efid = efIdForEfType(efType);
+            List<AdnRecord> existingRecords = mIccPhoneBookSupplier.get()
+                    .getAdnRecordsInEfForSubscriber(subscriptionInfo.getSubscriptionId(), efid);
+            int nonEmptyCount = 0;
+            for (AdnRecord record : existingRecords) {
+                if (!record.isEmpty()) {
+                    nonEmptyCount++;
+                }
+            }
+            row.add(ElementaryFiles.RECORD_COUNT, nonEmptyCount);
+        }
+    }
+
+    private Cursor querySimRecords(PhonebookArgs args, String[] projection) {
+        validateSubscriptionAndEf(args);
+        if (projection == null) {
+            projection = SIM_RECORDS_ALL_COLUMNS;
+        }
+
+        List<AdnRecord> records = loadRecordsForEf(args);
+        if (records == null) {
+            return new MatrixCursor(projection, 0);
+        }
+        MatrixCursor result = new MatrixCursor(projection, records.size());
+        List<Pair<AdnRecord, MatrixCursor.RowBuilder>> rowBuilders = new ArrayList<>(
+                records.size());
+        for (AdnRecord record : records) {
+            if (!record.isEmpty()) {
+                rowBuilders.add(Pair.create(record, result.newRow()));
+            }
+        }
+        // This is kind of ugly but avoids looking up columns in an inner loop.
+        for (String column : projection) {
+            switch (column) {
+                case SimRecords.SUBSCRIPTION_ID:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(args.subscriptionId);
+                    }
+                    break;
+                case SimRecords.ELEMENTARY_FILE_TYPE:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(args.efType);
+                    }
+                    break;
+                case SimRecords.RECORD_NUMBER:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getRecId());
+                    }
+                    break;
+                case SimRecords.NAME:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getAlphaTag());
+                    }
+                    break;
+                case SimRecords.PHONE_NUMBER:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getNumber());
+                    }
+                    break;
+                default:
+                    Rlog.w(TAG, "Column " + column + " is unsupported for " + args.uri);
+                    break;
+            }
+        }
+        return result;
+    }
+
+    private Cursor querySimRecordsItem(PhonebookArgs args, String[] projection) {
+        if (projection == null) {
+            projection = SIM_RECORDS_ALL_COLUMNS;
+        }
+        validateSubscriptionAndEf(args);
+        AdnRecord record = loadRecord(args);
+
+        MatrixCursor result = new MatrixCursor(projection, 1);
+        if (record == null || record.isEmpty()) {
+            return result;
+        }
+        result.newRow()
+                .add(SimRecords.SUBSCRIPTION_ID, args.subscriptionId)
+                .add(SimRecords.ELEMENTARY_FILE_TYPE, args.efType)
+                .add(SimRecords.RECORD_NUMBER, record.getRecId())
+                .add(SimRecords.NAME, record.getAlphaTag())
+                .add(SimRecords.PHONE_NUMBER, record.getNumber());
+        return result;
+    }
+
+    private Cursor queryValidateName(PhonebookArgs args, @Nullable Bundle queryArgs) {
+        if (queryArgs == null) {
+            throw new IllegalArgumentException(SimRecords.NAME + " is required.");
+        }
+        validateSubscriptionAndEf(args);
+        String name = queryArgs.getString(SimRecords.NAME);
+
+        // Cursor extras are used to return the result.
+        Cursor result = new MatrixCursor(new String[0], 0);
+        Bundle extras = new Bundle();
+        extras.putParcelable(SimRecords.EXTRA_NAME_VALIDATION_RESULT, validateName(args, name));
+        result.setExtras(extras);
+        return result;
+    }
+
+    @Nullable
+    @Override
+    public String getType(@NonNull Uri uri) {
+        switch (URI_MATCHER.match(uri)) {
+            case ELEMENTARY_FILES:
+                return ElementaryFiles.CONTENT_TYPE;
+            case ELEMENTARY_FILES_ITEM:
+                return ElementaryFiles.CONTENT_ITEM_TYPE;
+            case SIM_RECORDS:
+                return SimRecords.CONTENT_TYPE;
+            case SIM_RECORDS_ITEM:
+                return SimRecords.CONTENT_ITEM_TYPE;
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return insert(uri, values, null);
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS:
+                return insertSimRecord(PhonebookArgs.forSimRecords(uri, extras), values);
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS_ITEM:
+                throw new UnsupportedOperationException(uri + " does not support insert");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    private Uri insertSimRecord(PhonebookArgs args, ContentValues values) {
+        validateWritableEf(args, "insert");
+        validateSubscriptionAndEf(args);
+
+        if (values == null || values.isEmpty()) {
+            return null;
+        }
+        validateValues(args, values);
+        String newName = Strings.nullToEmpty(values.getAsString(SimRecords.NAME));
+        String newPhoneNumber = Strings.nullToEmpty(values.getAsString(SimRecords.PHONE_NUMBER));
+
+        acquireWriteLockOrThrow();
+        try {
+            List<AdnRecord> records = loadRecordsForEf(args);
+            if (records == null) {
+                Rlog.e(TAG, "Failed to load existing records for " + args.uri);
+                return null;
+            }
+            AdnRecord emptyRecord = null;
+            for (AdnRecord record : records) {
+                if (record.isEmpty()) {
+                    emptyRecord = record;
+                    break;
+                }
+            }
+            if (emptyRecord == null) {
+                // When there are no empty records that means the EF is full.
+                throw new IllegalStateException(
+                        args.uri + " is full. Please delete records to add new ones.");
+            }
+            boolean success = updateRecord(args, emptyRecord, args.pin2, newName, newPhoneNumber);
+            if (!success) {
+                Rlog.e(TAG, "Insert failed for " + args.uri);
+                // Something didn't work but since we don't have any more specific
+                // information to provide to the caller it's better to just return null
+                // rather than throwing and possibly crashing their process.
+                return null;
+            }
+            notifyChange();
+            return SimRecords.getItemUri(args.subscriptionId, args.efType, emptyRecord.getRecId());
+        } finally {
+            releaseWriteLock();
+        }
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        throw new UnsupportedOperationException("Only delete with Bundle is supported");
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS_ITEM:
+                return deleteSimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, extras));
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS:
+                throw new UnsupportedOperationException(uri + " does not support delete");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    private int deleteSimRecordsItem(PhonebookArgs args) {
+        validateWritableEf(args, "delete");
+        validateSubscriptionAndEf(args);
+
+        acquireWriteLockOrThrow();
+        try {
+            AdnRecord record = loadRecord(args);
+            if (record == null || record.isEmpty()) {
+                return 0;
+            }
+            if (!updateRecord(args, record, args.pin2, "", "")) {
+                Rlog.e(TAG, "Failed to delete " + args.uri);
+            }
+            notifyChange();
+        } finally {
+            releaseWriteLock();
+        }
+        return 1;
+    }
+
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS_ITEM:
+                return updateSimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, extras), values);
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS:
+                throw new UnsupportedOperationException(uri + " does not support update");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        throw new UnsupportedOperationException("Only Update with bundle is supported");
+    }
+
+    private int updateSimRecordsItem(PhonebookArgs args, ContentValues values) {
+        validateWritableEf(args, "update");
+        validateSubscriptionAndEf(args);
+
+        if (values == null || values.isEmpty()) {
+            return 0;
+        }
+        validateValues(args, values);
+        String newName = Strings.nullToEmpty(values.getAsString(SimRecords.NAME));
+        String newPhoneNumber = Strings.nullToEmpty(values.getAsString(SimRecords.PHONE_NUMBER));
+
+        acquireWriteLockOrThrow();
+
+        try {
+            AdnRecord record = loadRecord(args);
+
+            // Note we allow empty records to be updated. This is a bit weird because they are
+            // not returned by query methods but this allows a client application assign a name
+            // to a specific record number. This may be desirable in some phone app use cases since
+            // the record number is often used as a quick dial index.
+            if (record == null) {
+                return 0;
+            }
+            if (!updateRecord(args, record, args.pin2, newName, newPhoneNumber)) {
+                Rlog.e(TAG, "Failed to update " + args.uri);
+                return 0;
+            }
+            notifyChange();
+        } finally {
+            releaseWriteLock();
+        }
+        return 1;
+    }
+
+    void validateSubscriptionAndEf(PhonebookArgs args) {
+        SubscriptionInfo info =
+                args.subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                        ? getActiveSubscriptionInfo(args.subscriptionId)
+                        : null;
+        if (info == null) {
+            throw new IllegalArgumentException("No active SIM with subscription ID "
+                    + args.subscriptionId);
+        }
+
+        int[] recordsSize = getRecordsSizeForEf(args);
+        if (recordsSize == null || recordsSize[1] == 0) {
+            throw new IllegalArgumentException(args.efName
+                    + " is not supported for SIM with subscription ID " + args.subscriptionId);
+        }
+    }
+
+    private void acquireWriteLockOrThrow() {
+        try {
+            if (!mWriteLock.tryLock(WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+                throw new IllegalStateException("Timeout waiting to write");
+            }
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("Write failed");
+        }
+    }
+
+    private void releaseWriteLock() {
+        mWriteLock.unlock();
+    }
+
+    private void validateWritableEf(PhonebookArgs args, String operationName) {
+        if (args.efType == ElementaryFiles.EF_FDN) {
+            if (hasPermissionsForFdnWrite(args)) {
+                return;
+            }
+        }
+        if (args.efType != ElementaryFiles.EF_ADN) {
+            throw new UnsupportedOperationException(
+                    args.uri + " does not support " + operationName);
+        }
+    }
+
+    private boolean hasPermissionsForFdnWrite(PhonebookArgs args) {
+        TelephonyManager telephonyManager = getContext().getSystemService(
+                TelephonyManager.class);
+        String callingPackage = getCallingPackage();
+        int granted = PackageManager.PERMISSION_DENIED;
+        if (callingPackage != null) {
+            granted = getContext().getPackageManager().checkPermission(
+                    Manifest.permission.MODIFY_PHONE_STATE, callingPackage);
+        }
+        return granted == PackageManager.PERMISSION_GRANTED
+                || telephonyManager.hasCarrierPrivileges(args.subscriptionId);
+
+    }
+
+
+    private boolean updateRecord(PhonebookArgs args, AdnRecord existingRecord, String pin2,
+            String newName, String newPhone) {
+        try {
+            return mIccPhoneBookSupplier.get().updateAdnRecordsInEfByIndexForSubscriber(
+                    args.subscriptionId, existingRecord.getEfid(), newName, newPhone,
+                    existingRecord.getRecId(),
+                    pin2);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    private SimRecords.NameValidationResult validateName(
+            PhonebookArgs args, @Nullable String name) {
+        name = Strings.nullToEmpty(name);
+        int recordSize = getRecordSize(getRecordsSizeForEf(args));
+        // Validating the name consists of encoding the record in the binary format that it is
+        // stored on the SIM then decoding it and checking whether the decoded name is the same.
+        // The AOSP implementation of AdnRecord replaces unsupported characters with spaces during
+        // encoding.
+        // TODO: It would be good to update AdnRecord to support UCS-2 on the encode path (it
+        //  supports it on the decode path). Right now it's not supported and so any non-latin
+        //  characters will not be valid (at least in the AOSP implementation).
+        byte[] encodedName = AdnRecord.encodeAlphaTag(name);
+        String sanitizedName = AdnRecord.decodeAlphaTag(encodedName, 0, encodedName.length);
+        return new SimRecords.NameValidationResult(name, sanitizedName,
+                encodedName.length, AdnRecord.getMaxAlphaTagBytes(recordSize));
+    }
+
+    private void validatePhoneNumber(@Nullable String phoneNumber) {
+        if (phoneNumber == null || phoneNumber.isEmpty()) {
+            throw new IllegalArgumentException(SimRecords.PHONE_NUMBER + " is required.");
+        }
+        int actualLength = phoneNumber.length();
+        // When encoded the "+" prefix sets a bit and so doesn't count against the maximum length
+        if (phoneNumber.startsWith("+")) {
+            actualLength--;
+        }
+        if (actualLength > AdnRecord.getMaxPhoneNumberDigits()) {
+            throw new IllegalArgumentException(SimRecords.PHONE_NUMBER + " is too long.");
+        }
+        for (int i = 0; i < phoneNumber.length(); i++) {
+            char c = phoneNumber.charAt(i);
+            if (!PhoneNumberUtils.isNonSeparator(c)) {
+                throw new IllegalArgumentException(
+                        SimRecords.PHONE_NUMBER + " contains unsupported characters.");
+            }
+        }
+    }
+
+    private void validateValues(PhonebookArgs args, ContentValues values) {
+        if (!SIM_RECORDS_WRITABLE_COLUMNS.containsAll(values.keySet())) {
+            Set<String> unsupportedColumns = new ArraySet<>(values.keySet());
+            unsupportedColumns.removeAll(SIM_RECORDS_WRITABLE_COLUMNS);
+            throw new IllegalArgumentException("Unsupported columns: " + Joiner.on(',')
+                    .join(unsupportedColumns));
+        }
+
+        String phoneNumber = values.getAsString(SimRecords.PHONE_NUMBER);
+        validatePhoneNumber(phoneNumber);
+
+        String name = values.getAsString(SimRecords.NAME);
+        SimRecords.NameValidationResult result = validateName(args, name);
+
+        if (result.getEncodedLength() > result.getMaxEncodedLength()) {
+            throw new IllegalArgumentException(SimRecords.NAME + " is too long.");
+        } else if (!Objects.equals(result.getName(), result.getSanitizedName())) {
+            throw new IllegalArgumentException(
+                    SimRecords.NAME + " contains unsupported characters.");
+        }
+    }
+
+    private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
+        // Getting the SubscriptionInfo requires READ_PHONE_STATE but we're only returning
+        // the subscription ID and slot index which are not sensitive information.
+        CallingIdentity identity = clearCallingIdentity();
+        try {
+            return mSubscriptionManager.getActiveSubscriptionInfoList();
+        } finally {
+            restoreCallingIdentity(identity);
+        }
+    }
+
+    private SubscriptionInfo getActiveSubscriptionInfo(int subId) {
+        // Getting the SubscriptionInfo requires READ_PHONE_STATE.
+        CallingIdentity identity = clearCallingIdentity();
+        try {
+            return mSubscriptionManager.getActiveSubscriptionInfo(subId);
+        } finally {
+            restoreCallingIdentity(identity);
+        }
+    }
+
+    private List<AdnRecord> loadRecordsForEf(PhonebookArgs args) {
+        try {
+            return mIccPhoneBookSupplier.get().getAdnRecordsInEfForSubscriber(
+                    args.subscriptionId, args.efid);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    private AdnRecord loadRecord(PhonebookArgs args) {
+        List<AdnRecord> records = loadRecordsForEf(args);
+        if (args.recordNumber > records.size()) {
+            return null;
+        }
+        AdnRecord result = records.get(args.recordNumber - 1);
+        // This should be true but the service could have a different implementation.
+        if (result.getRecId() == args.recordNumber) {
+            return result;
+        }
+        for (AdnRecord record : records) {
+            if (record.getRecId() == args.recordNumber) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+
+    private int[] getRecordsSizeForEf(PhonebookArgs args) {
+        try {
+            return mIccPhoneBookSupplier.get().getAdnRecordsSizeForSubscriber(
+                    args.subscriptionId, args.efid);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    void notifyChange() {
+        mContentNotifier.notifyChange(SimPhonebookContract.AUTHORITY_URI);
+    }
+
+    /** Testable wrapper around {@link ContentResolver#notifyChange(Uri, ContentObserver)} */
+    @TestApi
+    interface ContentNotifier {
+        void notifyChange(Uri uri);
+    }
+
+    /**
+     * Holds the arguments extracted from the Uri and query args for accessing the referenced
+     * phonebook data on a SIM.
+     */
+    private static class PhonebookArgs {
+        public final Uri uri;
+        public final int subscriptionId;
+        public final String efName;
+        public final int efType;
+        public final int efid;
+        public final int recordNumber;
+        public final String pin2;
+
+        PhonebookArgs(Uri uri, int subscriptionId, String efName,
+                @ElementaryFiles.EfType int efType, int efid, int recordNumber,
+                @Nullable Bundle queryArgs) {
+            this.uri = uri;
+            this.subscriptionId = subscriptionId;
+            this.efName = efName;
+            this.efType = efType;
+            this.efid = efid;
+            this.recordNumber = recordNumber;
+            pin2 = efType == ElementaryFiles.EF_FDN && queryArgs != null
+                    ? queryArgs.getString(SimRecords.QUERY_ARG_PIN2)
+                    : null;
+        }
+
+        static PhonebookArgs createFromEfName(Uri uri, int subscriptionId,
+                String efName, int recordNumber, @Nullable Bundle queryArgs) {
+            int efType;
+            int efid;
+            if (efName != null) {
+                switch (efName) {
+                    case ElementaryFiles.EF_ADN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_ADN;
+                        efid = IccConstants.EF_ADN;
+                        break;
+                    case ElementaryFiles.EF_FDN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_FDN;
+                        efid = IccConstants.EF_FDN;
+                        break;
+                    case ElementaryFiles.EF_SDN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_SDN;
+                        efid = IccConstants.EF_SDN;
+                        break;
+                    default:
+                        throw new IllegalArgumentException(
+                                "Unrecognized elementary file " + efName);
+                }
+            } else {
+                efType = ElementaryFiles.EF_UNKNOWN;
+                efid = 0;
+            }
+            return new PhonebookArgs(uri, subscriptionId, efName, efType, efid, recordNumber,
+                    queryArgs);
+        }
+
+        /**
+         * Pattern: elementary_files/subid/${subscriptionId}/${efName}
+         *
+         * e.g. elementary_files/subid/1/adn
+         *
+         * @see ElementaryFiles#getItemUri(int, int)
+         * @see #ELEMENTARY_FILES_ITEM
+         */
+        static PhonebookArgs forElementaryFilesItem(Uri uri) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 2);
+            String efName = uri.getPathSegments().get(3);
+            return PhonebookArgs.createFromEfName(
+                    uri, subscriptionId, efName, -1, null);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}
+         *
+         * <p>e.g. subid/1/adn
+         *
+         * @see SimRecords#getContentUri(int, int)
+         * @see #SIM_RECORDS
+         */
+        static PhonebookArgs forSimRecords(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            return PhonebookArgs.createFromEfName(uri, subscriptionId, efName, -1, queryArgs);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}/${recordNumber}
+         *
+         * <p>e.g. subid/1/adn/10
+         *
+         * @see SimRecords#getItemUri(int, int, int)
+         * @see #SIM_RECORDS_ITEM
+         */
+        static PhonebookArgs forSimRecordsItem(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            int recordNumber = parseRecordNumberFromUri(uri, 3);
+            return PhonebookArgs.createFromEfName(uri, subscriptionId, efName, recordNumber,
+                    queryArgs);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}/validate_name
+         *
+         * @see SimRecords#validateName(ContentResolver, int, int, String)
+         * @see #VALIDATE_NAME
+         */
+        static PhonebookArgs forValidateName(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            return PhonebookArgs.createFromEfName(
+                    uri, subscriptionId, efName, -1, queryArgs);
+        }
+
+        private static int parseSubscriptionIdFromUri(Uri uri, int pathIndex) {
+            if (pathIndex == -1) {
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+            }
+            String segment = uri.getPathSegments().get(pathIndex);
+            try {
+                return Integer.parseInt(segment);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Invalid subscription ID: " + segment);
+            }
+        }
+
+        private static int parseRecordNumberFromUri(Uri uri, int pathIndex) {
+            try {
+                return Integer.parseInt(uri.getPathSegments().get(pathIndex));
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException(
+                        "Invalid record index: " + uri.getLastPathSegment());
+            }
+        }
+    }
+}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 0348389..9676e59 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -16,22 +16,35 @@
 
 package com.android.phone;
 
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
+
+import android.Manifest;
 import android.content.Context;
-import android.os.BasicShellCommandHandler;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
+import android.provider.BlockedNumberContract;
 import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.feature.ImsFeature;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.d2d.Communicator;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.phone.callcomposer.CallComposerPictureManager;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -39,6 +52,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
 
 /**
  * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
@@ -53,18 +68,24 @@
     private static final boolean VDBG = true;
     private static final int DEFAULT_PHONE_ID = 0;
 
+    private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
     private static final String IMS_SUBCOMMAND = "ims";
     private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
     private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
+    private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
+    private static final String RESTART_MODEM = "restart-modem";
     private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
     private static final String DATA_TEST_MODE = "data";
-    private static final String DATA_ENABLE = "enable";
-    private static final String DATA_DISABLE = "disable";
+    private static final String ENABLE = "enable";
+    private static final String DISABLE = "disable";
+    private static final String QUERY = "query";
 
-    private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service";
-    private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
-    private static final String IMS_ENABLE = "enable";
-    private static final String IMS_DISABLE = "disable";
+    private static final String CALL_COMPOSER_TEST_MODE = "test_mode";
+    private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
+
+    private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
+    private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
+    private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
     // Used to disable or enable processing of conference event package data from the network.
     // This is handy for testing scenarios where CEP data does not exist on a network which does
     // support CEP data.
@@ -77,11 +98,33 @@
     private static final String CC_SET_VALUE = "set-value";
     private static final String CC_CLEAR_VALUES = "clear-values";
 
+    private static final String GBA_SUBCOMMAND = "gba";
+    private static final String GBA_SET_SERVICE = "set-service";
+    private static final String GBA_GET_SERVICE = "get-service";
+    private static final String GBA_SET_RELEASE_TIME = "set-release";
+    private static final String GBA_GET_RELEASE_TIME = "get-release";
+
+    private static final String SINGLE_REGISTATION_CONFIG = "src";
+    private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
+    private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
+    private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
+    private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
+
+    private static final String D2D_SUBCOMMAND = "d2d";
+    private static final String D2D_SEND = "send";
+
+    private static final String RCS_UCE_COMMAND = "uce";
+    private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
+    private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
+    private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
+    private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
+
     // Take advantage of existing methods that already contain permissions checks when possible.
     private final ITelephony mInterface;
 
     private SubscriptionManager mSubscriptionManager;
     private CarrierConfigManager mCarrierConfigManager;
+    private Context mContext;
 
     private enum CcType {
         BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
@@ -132,6 +175,7 @@
                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         mSubscriptionManager = (SubscriptionManager)
                 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mContext = context;
     }
 
     @Override
@@ -144,6 +188,8 @@
             case IMS_SUBCOMMAND: {
                 return handleImsCommand();
             }
+            case RCS_UCE_COMMAND:
+                return handleRcsUceCommand();
             case NUMBER_VERIFICATION_SUBCOMMAND:
                 return handleNumberVerificationCommand();
             case EMERGENCY_NUMBER_TEST_MODE:
@@ -153,6 +199,18 @@
             }
             case DATA_TEST_MODE:
                 return handleDataTestModeCommand();
+            case END_BLOCK_SUPPRESSION:
+                return handleEndBlockSuppressionCommand();
+            case GBA_SUBCOMMAND:
+                return handleGbaCommand();
+            case D2D_SUBCOMMAND:
+                return handleD2dCommand();
+            case SINGLE_REGISTATION_CONFIG:
+                return handleSingleRegistrationConfigCommand();
+            case RESTART_MODEM:
+                return handleRestartModemCommand();
+            case CALL_COMPOSER_SUBCOMMAND:
+                return handleCallComposerCommand();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -167,16 +225,47 @@
         pw.println("    Print this help text.");
         pw.println("  ims");
         pw.println("    IMS Commands.");
+        pw.println("  uce");
+        pw.println("    RCS User Capability Exchange Commands.");
         pw.println("  emergency-number-test-mode");
         pw.println("    Emergency Number Test Mode Commands.");
+        pw.println("  end-block-suppression");
+        pw.println("    End Block Suppression command.");
         pw.println("  data");
         pw.println("    Data Test Mode Commands.");
         pw.println("  cc");
         pw.println("    Carrier Config Commands.");
+        pw.println("  gba");
+        pw.println("    GBA Commands.");
+        pw.println("  src");
+        pw.println("    RCS VoLTE Single Registration Config Commands.");
+        pw.println("  restart-modem");
+        pw.println("    Restart modem command.");
         onHelpIms();
+        onHelpUce();
         onHelpEmergencyNumber();
+        onHelpEndBlockSupperssion();
         onHelpDataTestMode();
         onHelpCc();
+        onHelpGba();
+        onHelpSrc();
+        onHelpD2D();
+    }
+
+    private void onHelpD2D() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("D2D Comms Commands:");
+        pw.println("  d2d send TYPE VALUE");
+        pw.println("    Sends a D2D message of specified type and value.");
+        pw.println("    Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
+                + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
+        pw.println("    Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
+                MESSAGE_CALL_AUDIO_CODEC));
+        pw.println("    Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
+                        + Communicator.messageToString(
+                        MESSAGE_DEVICE_BATTERY_STATE));
+        pw.println("    Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
+                + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
     }
 
     private void onHelpIms() {
@@ -197,9 +286,14 @@
         pw.println("      -s: The SIM slot ID for the registered ImsService. If no option");
         pw.println("          is specified, it will choose the default voice SIM slot.");
         pw.println("      -c: The ImsService defined as the carrier configured ImsService.");
-        pw.println("      -c: The ImsService defined as the device default ImsService.");
+        pw.println("      -d: The ImsService defined as the device default ImsService.");
         pw.println("      -f: The feature type that the query will be requested for. If none is");
         pw.println("          specified, the returned package name will correspond to MMTEL.");
+        pw.println("  ims clear-ims-service-override [-s SLOT_ID]");
+        pw.println("    Clear all carrier ImsService overrides. This does not work for device ");
+        pw.println("    configuration overrides. Options are:");
+        pw.println("      -s: The SIM slot ID for the registered ImsService. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
         pw.println("  ims enable [-s SLOT_ID]");
         pw.println("    enables IMS for the SIM slot specified, or for the default voice SIM slot");
         pw.println("    if none is specified.");
@@ -210,6 +304,28 @@
         pw.println("    enables or disables handling or network conference event package data.");
     }
 
+    private void onHelpUce() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("User Capability Exchange Commands:");
+        pw.println("  uce get-eab-contact [PHONE_NUMBER]");
+        pw.println("    Get the EAB contacts from the EAB database.");
+        pw.println("    Options are:");
+        pw.println("      PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
+        pw.println("    Expected output format :");
+        pw.println("      [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
+        pw.println("  uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
+        pw.println("    Remove the EAB contacts from the EAB database.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("      PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
+        pw.println("  uce get-device-enabled");
+        pw.println("    Get the config to check whether the device supports RCS UCE or not.");
+        pw.println("  uce set-device-enabled true|false");
+        pw.println("    Set the device config for RCS User Capability Exchange to the value.");
+        pw.println("    The value could be true, false.");
+    }
+
     private void onHelpNumberVerification() {
         PrintWriter pw = getOutPrintWriter();
         pw.println("Number verification commands");
@@ -242,6 +358,13 @@
         pw.println("      -p: get the full emergency number list in the test mode.");
     }
 
+    private void onHelpEndBlockSupperssion() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("End Block Suppression command:");
+        pw.println("  end-block-suppression: disable suppressing blocking by contact");
+        pw.println("                         with emergency services.");
+    }
+
     private void onHelpCc() {
         PrintWriter pw = getOutPrintWriter();
         pw.println("Carrier Config Commands:");
@@ -270,6 +393,53 @@
         pw.println("          is specified, it will choose the default voice SIM slot.");
     }
 
+    private void onHelpGba() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Gba Commands:");
+        pw.println("  gba set-service [-s SLOT_ID] PACKAGE_NAME");
+        pw.println("    Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba get-service [-s SLOT_ID]");
+        pw.println("    Gets the package name of the currently defined GbaService.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba set-release [-s SLOT_ID] n");
+        pw.println("    Sets the time to release/unbind GbaService in n milli-second.");
+        pw.println("    Do not release/unbind if n is -1.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba get-release [-s SLOT_ID]");
+        pw.println("    Gets the time to release/unbind GbaService in n milli-sencond.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+    }
+
+    private void onHelpSrc() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("RCS VoLTE Single Registration Config Commands:");
+        pw.println("  src set-device-enabled true|false|null");
+        pw.println("    Sets the device config for RCS VoLTE single registration to the value.");
+        pw.println("    The value could be true, false, or null(undefined).");
+        pw.println("  src get-device-enabled");
+        pw.println("    Gets the device config for RCS VoLTE single registration.");
+        pw.println("  src set-carrier-enabled [-s SLOT_ID] true|false|null");
+        pw.println("    Sets the carrier config for RCS VoLTE single registration to the value.");
+        pw.println("    The value could be true, false, or null(undefined).");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to set the config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  src get-carrier-enabled [-s SLOT_ID]");
+        pw.println("    Gets the carrier config for RCS VoLTE single registration.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read the config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+    }
+
     private int handleImsCommand() {
         String arg = getNextArg();
         if (arg == null) {
@@ -278,16 +448,19 @@
         }
 
         switch (arg) {
-            case IMS_SET_CARRIER_SERVICE: {
+            case IMS_SET_IMS_SERVICE: {
                 return handleImsSetServiceCommand();
             }
-            case IMS_GET_CARRIER_SERVICE: {
+            case IMS_GET_IMS_SERVICE: {
                 return handleImsGetServiceCommand();
             }
-            case IMS_ENABLE: {
+            case IMS_CLEAR_SERVICE_OVERRIDE: {
+                return handleImsClearCarrierServiceCommand();
+            }
+            case ENABLE: {
                 return handleEnableIms();
             }
-            case IMS_DISABLE: {
+            case DISABLE: {
                 return handleDisableIms();
             }
             case IMS_CEP: {
@@ -306,7 +479,7 @@
             return 0;
         }
         switch (arg) {
-            case DATA_ENABLE: {
+            case ENABLE: {
                 try {
                     mInterface.enableDataConnectivity();
                 } catch (RemoteException ex) {
@@ -316,7 +489,7 @@
                 }
                 break;
             }
-            case DATA_DISABLE: {
+            case DISABLE: {
                 try {
                     mInterface.disableDataConnectivity();
                 } catch (RemoteException ex) {
@@ -445,6 +618,64 @@
         return -1;
     }
 
+    private int handleD2dCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpD2D();
+            return 0;
+        }
+
+        switch (arg) {
+            case D2D_SEND: {
+                return handleD2dSendCommand();
+            }
+        }
+
+        return -1;
+    }
+
+    private int handleD2dSendCommand() {
+        PrintWriter errPw = getErrPrintWriter();
+        String opt;
+        int messageType = -1;
+        int messageValue = -1;
+
+
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpD2D();
+            return 0;
+        }
+        try {
+            messageType = Integer.parseInt(arg);
+        } catch (NumberFormatException e) {
+            errPw.println("message type must be a valid integer");
+            return -1;
+        }
+
+        arg = getNextArg();
+        if (arg == null) {
+            onHelpD2D();
+            return 0;
+        }
+        try {
+            messageValue = Integer.parseInt(arg);
+        } catch (NumberFormatException e) {
+            errPw.println("message value must be a valid integer");
+            return -1;
+        }
+        
+        try {
+            mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+
+        return 0;
+    }
+
     // ims set-ims-service
     private int handleImsSetServiceCommand() {
         PrintWriter errPw = getErrPrintWriter();
@@ -530,6 +761,42 @@
         return 0;
     }
 
+    // ims clear-ims-service-override
+    private int handleImsClearCarrierServiceCommand() {
+        PrintWriter errPw = getErrPrintWriter();
+        int slotId = getDefaultSlot();
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-s": {
+                    try {
+                        slotId = Integer.parseInt(getNextArgRequired());
+                    } catch (NumberFormatException e) {
+                        errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
+                        return -1;
+                    }
+                    break;
+                }
+            }
+        }
+
+        try {
+            boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
+            if (VDBG) {
+                Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
+                        + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
+                    + ", error" + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
     // ims get-ims-service
     private int handleImsGetServiceCommand() {
         PrintWriter errPw = getErrPrintWriter();
@@ -723,17 +990,21 @@
         try {
             slotId = Integer.parseInt(slotString);
         } catch (NumberFormatException e) {
+            getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+
+        if (!SubscriptionManager.isValidPhoneId(slotId)) {
             getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
 
-        SubscriptionInfo subInfo =
-                mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(slotId);
-        if (subInfo == null) {
+        Phone phone = PhoneFactory.getPhone(slotId);
+        if (phone == null) {
             getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
-        return subInfo.getSubscriptionId();
+        return phone.getSubId();
     }
 
     private boolean checkShellUid() {
@@ -1169,4 +1440,431 @@
         }
         return bundle;
     }
+
+    private int handleEndBlockSuppressionCommand() {
+        if (!checkShellUid()) {
+            return -1;
+        }
+
+        if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
+            BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
+        }
+        return 0;
+    }
+
+    private int handleRestartModemCommand() {
+        // Verify that the user is allowed to run the command. Only allowed in rooted device in a
+        // non user build.
+        if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
+            getErrPrintWriter().println("RestartModem: Permission denied.");
+            return -1;
+        }
+
+        boolean result = TelephonyManager.getDefault().rebootRadio();
+        getOutPrintWriter().println(result);
+
+        return result ? 0 : -1;
+    }
+
+    private int handleGbaCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpGba();
+            return 0;
+        }
+
+        switch (arg) {
+            case GBA_SET_SERVICE: {
+                return handleGbaSetServiceCommand();
+            }
+            case GBA_GET_SERVICE: {
+                return handleGbaGetServiceCommand();
+            }
+            case GBA_SET_RELEASE_TIME: {
+                return handleGbaSetReleaseCommand();
+            }
+            case GBA_GET_RELEASE_TIME: {
+                return handleGbaGetReleaseCommand();
+            }
+        }
+
+        return -1;
+    }
+
+    private int getSubId(String cmd) {
+        int slotId = getDefaultSlot();
+        String opt = getNextOption();
+        if (opt != null && opt.equals("-s")) {
+            try {
+                slotId = Integer.parseInt(getNextArgRequired());
+            } catch (NumberFormatException e) {
+                getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+            }
+        }
+        int[] subIds = SubscriptionManager.getSubId(slotId);
+        return subIds[0];
+    }
+
+    private int handleGbaSetServiceCommand() {
+        int subId = getSubId("gba set-service");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String packageName = getNextArg();
+        try {
+            if (packageName == null) {
+                packageName = "";
+            }
+            boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
+            if (VDBG) {
+                Log.v(LOG_TAG, "gba set-service -s " + subId + " "
+                        + packageName + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "gba set-service " + subId + " "
+                    + packageName + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleGbaGetServiceCommand() {
+        String result;
+
+        int subId = getSubId("gba get-service");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        try {
+            result = mInterface.getBoundGbaService(subId);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private int handleGbaSetReleaseCommand() {
+        //the release time value could be -1
+        int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
+                : SubscriptionManager.getDefaultSubscriptionId();
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String intervalStr = getNextArg();
+        if (intervalStr == null) {
+            return -1;
+        }
+
+        try {
+            int interval = Integer.parseInt(intervalStr);
+            boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
+            if (VDBG) {
+                Log.v(LOG_TAG, "gba set-release -s " + subId + " "
+                        + intervalStr + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (NumberFormatException | RemoteException e) {
+            Log.w(LOG_TAG, "gba set-release -s " + subId + " "
+                    + intervalStr + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleGbaGetReleaseCommand() {
+        int subId = getSubId("gba get-release");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        int result = 0;
+        try {
+            result = mInterface.getGbaReleaseTime(subId);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private int handleSingleRegistrationConfigCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpSrc();
+            return 0;
+        }
+
+        switch (arg) {
+            case SRC_SET_DEVICE_ENABLED: {
+                return handleSrcSetDeviceEnabledCommand();
+            }
+            case SRC_GET_DEVICE_ENABLED: {
+                return handleSrcGetDeviceEnabledCommand();
+            }
+            case SRC_SET_CARRIER_ENABLED: {
+                return handleSrcSetCarrierEnabledCommand();
+            }
+            case SRC_GET_CARRIER_ENABLED: {
+                return handleSrcGetCarrierEnabledCommand();
+            }
+        }
+
+        return -1;
+    }
+
+    private int handleRcsUceCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            Log.w(LOG_TAG, "cannot get uce parameter");
+            return -1;
+        }
+
+        switch (arg) {
+            case UCE_REMOVE_EAB_CONTACT:
+                return handleRemovingEabContactCommand();
+            case UCE_GET_EAB_CONTACT:
+                return handleGettingEabContactCommand();
+            case UCE_GET_DEVICE_ENABLED:
+                return handleUceGetDeviceEnabledCommand();
+            case UCE_SET_DEVICE_ENABLED:
+                return handleUceSetDeviceEnabledCommand();
+        }
+        return -1;
+    }
+
+    private int handleRemovingEabContactCommand() {
+        int subId = getSubId("uce remove-eab-contact");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String phoneNumber = getNextArgRequired();
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return -1;
+        }
+        int result = 0;
+        try {
+            result = mInterface.removeContactFromEab(subId, phoneNumber);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+
+        if (VDBG) {
+            Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
+        }
+        return result;
+    }
+
+    private int handleGettingEabContactCommand() {
+        String phoneNumber = getNextArgRequired();
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return -1;
+        }
+        String result = "";
+        try {
+            result = mInterface.getContactFromEab(phoneNumber);
+
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+
+        if (VDBG) {
+            Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
+        }
+        return 0;
+    }
+
+    private int handleUceGetDeviceEnabledCommand() {
+        boolean result = false;
+        try {
+            result = mInterface.getDeviceUceEnabled();
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private int handleUceSetDeviceEnabledCommand() {
+        String enabledStr = getNextArg();
+        if (TextUtils.isEmpty(enabledStr)) {
+            return -1;
+        }
+
+        try {
+            boolean isEnabled = Boolean.parseBoolean(enabledStr);
+            mInterface.setDeviceUceEnabled(isEnabled);
+            if (VDBG) {
+                Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
+            }
+        } catch (NumberFormatException | RemoteException e) {
+            Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleSrcSetDeviceEnabledCommand() {
+        String enabledStr = getNextArg();
+        if (enabledStr == null) {
+            return -1;
+        }
+
+        try {
+            mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
+            if (VDBG) {
+                Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
+            }
+            getOutPrintWriter().println("Done");
+        } catch (NumberFormatException | RemoteException e) {
+            Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleSrcGetDeviceEnabledCommand() {
+        boolean result = false;
+        try {
+            result = mInterface.getDeviceSingleRegistrationEnabled();
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private int handleSrcSetCarrierEnabledCommand() {
+        //the release time value could be -1
+        int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
+                : SubscriptionManager.getDefaultSubscriptionId();
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String enabledStr = getNextArg();
+        if (enabledStr == null) {
+            return -1;
+        }
+
+        try {
+            boolean result =
+                    mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
+            if (VDBG) {
+                Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
+                        + enabledStr + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (NumberFormatException | RemoteException e) {
+            Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
+                    + enabledStr + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleSrcGetCarrierEnabledCommand() {
+        int subId = getSubId("src get-carrier-enabled");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        boolean result = false;
+        try {
+            result = mInterface.getCarrierSingleRegistrationEnabled(subId);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private void onHelpCallComposer() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Call composer commands");
+        pw.println("  callcomposer test-mode enable|disable|query");
+        pw.println("    Enables or disables test mode for call composer. In test mode, picture");
+        pw.println("    upload/download from carrier servers is disabled, and operations are");
+        pw.println("    performed using emulated local files instead.");
+        pw.println("  callcomposer simulate-outgoing-call [subId] [UUID]");
+        pw.println("    Simulates an outgoing call being placed with the picture ID as");
+        pw.println("    the provided UUID. This triggers storage to the call log.");
+    }
+
+    private int handleCallComposerCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpCallComposer();
+            return 0;
+        }
+
+        mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
+                "MODIFY_PHONE_STATE required for call composer shell cmds");
+        switch (arg) {
+            case CALL_COMPOSER_TEST_MODE: {
+                String enabledStr = getNextArg();
+                if (ENABLE.equals(enabledStr)) {
+                    CallComposerPictureManager.sTestMode = true;
+                } else if (DISABLE.equals(enabledStr)) {
+                    CallComposerPictureManager.sTestMode = false;
+                } else if (QUERY.equals(enabledStr)) {
+                    getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
+                } else {
+                    onHelpCallComposer();
+                    return 1;
+                }
+                break;
+            }
+            case CALL_COMPOSER_SIMULATE_CALL: {
+                int subscriptionId = Integer.valueOf(getNextArg());
+                String uuidString = getNextArg();
+                UUID uuid = UUID.fromString(uuidString);
+                CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
+                Binder.withCleanCallingIdentity(() -> {
+                    CallComposerPictureManager.getInstance(mContext, subscriptionId)
+                            .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
+                });
+                try {
+                    Uri uri = storageUriFuture.get();
+                    getOutPrintWriter().println(String.valueOf(uri));
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+                break;
+            }
+        }
+
+        return 0;
+    }
 }
diff --git a/src/com/android/phone/TimeConsumingPreferenceActivity.java b/src/com/android/phone/TimeConsumingPreferenceActivity.java
index 3b5fe21..8c5ae6d 100644
--- a/src/com/android/phone/TimeConsumingPreferenceActivity.java
+++ b/src/com/android/phone/TimeConsumingPreferenceActivity.java
@@ -187,11 +187,6 @@
     @Override
     public void onError(Preference preference, int error) {
         if (DBG) dumpState();
-        if (!preference.isEnabled()) {
-            Log.i(LOG_TAG, "onError, skipped duplicated error popup");
-            return;
-        }
-
         Log.i(LOG_TAG, "onError, preference=" + preference.getKey() + ", error=" + error);
 
         if (mIsForeground) {
diff --git a/src/com/android/phone/callcomposer/CallComposerPictureManager.java b/src/com/android/phone/callcomposer/CallComposerPictureManager.java
new file mode 100644
index 0000000..b27a27c
--- /dev/null
+++ b/src/com/android/phone/callcomposer/CallComposerPictureManager.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.callcomposer;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.OutcomeReceiver;
+import android.os.UserHandle;
+import android.provider.CallLog;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.callcomposer.CallComposerPictureTransfer.PictureCallback;
+import com.android.phone.R;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
+public class CallComposerPictureManager {
+    private static final String TAG = CallComposerPictureManager.class.getSimpleName();
+    private static final SparseArray<CallComposerPictureManager> sInstances = new SparseArray<>();
+
+    public static CallComposerPictureManager getInstance(Context context, int subscriptionId) {
+        synchronized (sInstances) {
+            if (sExecutorService == null) {
+                sExecutorService = Executors.newSingleThreadScheduledExecutor();
+            }
+            if (!sInstances.contains(subscriptionId)) {
+                sInstances.put(subscriptionId,
+                        new CallComposerPictureManager(context, subscriptionId));
+            }
+            return sInstances.get(subscriptionId);
+        }
+    }
+
+    @VisibleForTesting
+    public static void clearInstances() {
+        synchronized (sInstances) {
+            sInstances.clear();
+            if (sExecutorService != null) {
+                sExecutorService.shutdown();
+                sExecutorService = null;
+            }
+        }
+    }
+
+    // disabled provisionally until the auth stack is fully operational
+    @VisibleForTesting
+    public static boolean sTestMode = false;
+    public static final String FAKE_SERVER_URL = "https://example.com/FAKE.png";
+
+    public interface CallLogProxy {
+        default void storeCallComposerPictureAsUser(Context context,
+                UserHandle user,
+                InputStream input,
+                Executor executor,
+                OutcomeReceiver<Uri, CallLog.CallComposerLoggingException> callback) {
+            CallLog.storeCallComposerPictureAsUser(context, user, input, executor, callback);
+        }
+    }
+
+    private static ScheduledExecutorService sExecutorService = null;
+
+    private final HashMap<UUID, String> mCachedServerUrls = new HashMap<>();
+    private final HashMap<UUID, ImageData> mCachedImages = new HashMap<>();
+    private final Map<String, GbaCredentials> mCachedCredentials = new HashMap<>();
+    private final int mSubscriptionId;
+    private final TelephonyManager mTelephonyManager;
+    private final Context mContext;
+    private CallLogProxy mCallLogProxy = new CallLogProxy() {};
+
+    private CallComposerPictureManager(Context context, int subscriptionId) {
+        mContext = context;
+        mSubscriptionId = subscriptionId;
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+                .createForSubscriptionId(mSubscriptionId);
+    }
+
+    public void handleUploadToServer(CallComposerPictureTransfer.Factory transferFactory,
+            ImageData imageData, Consumer<Pair<UUID, Integer>> callback) {
+        if (sTestMode) {
+            UUID id = UUID.randomUUID();
+            mCachedImages.put(id, imageData);
+            mCachedServerUrls.put(id, FAKE_SERVER_URL);
+            callback.accept(Pair.create(id, TelephonyManager.CallComposerException.SUCCESS));
+            return;
+        }
+
+        String uploadUrl = mTelephonyManager.getCarrierConfig().getString(
+                CarrierConfigManager.KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING);
+        if (TextUtils.isEmpty(uploadUrl)) {
+            Log.e(TAG, "Call composer upload URL not configured in carrier config");
+            callback.accept(Pair.create(null,
+                    TelephonyManager.CallComposerException.ERROR_UNKNOWN));
+        }
+        UUID id = UUID.randomUUID();
+        imageData.setId(id.toString());
+
+        CallComposerPictureTransfer transfer = transferFactory.create(mContext,
+                mSubscriptionId, uploadUrl, sExecutorService);
+
+        AtomicBoolean hasRetried = new AtomicBoolean(false);
+        transfer.setCallback(new PictureCallback() {
+            @Override
+            public void onError(int error) {
+                callback.accept(Pair.create(null, error));
+            }
+
+            @Override
+            public void onRetryNeeded(boolean credentialRefresh, long backoffMillis) {
+                if (hasRetried.getAndSet(true)) {
+                    Log.e(TAG, "Giving up on image upload after one retry.");
+                    callback.accept(Pair.create(null,
+                            TelephonyManager.CallComposerException.ERROR_NETWORK_UNAVAILABLE));
+                    return;
+                }
+                GbaCredentialsSupplier supplier =
+                        (realm, executor) ->
+                                getGbaCredentials(credentialRefresh, realm, executor);
+
+                sExecutorService.schedule(() -> transfer.uploadPicture(imageData, supplier),
+                        backoffMillis, TimeUnit.MILLISECONDS);
+            }
+
+            @Override
+            public void onUploadSuccessful(String serverUrl) {
+                mCachedServerUrls.put(id, serverUrl);
+                mCachedImages.put(id, imageData);
+                Log.i(TAG, "Successfully received url: " + serverUrl + " associated with "
+                        + id.toString());
+                callback.accept(Pair.create(id, TelephonyManager.CallComposerException.SUCCESS));
+            }
+        });
+
+        transfer.uploadPicture(imageData,
+                (realm, executor) -> getGbaCredentials(false, realm, executor));
+    }
+
+    public void handleDownloadFromServer(CallComposerPictureTransfer.Factory transferFactory,
+            String remoteUrl, Consumer<Pair<Uri, Integer>> callback) {
+        if (sTestMode) {
+            ImageData imageData = new ImageData(getPlaceholderPictureAsBytes(), "image/png", null);
+            UUID id = UUID.randomUUID();
+            mCachedImages.put(id, imageData);
+            storeUploadedPictureToCallLog(id, uri -> callback.accept(Pair.create(uri, -1)));
+            return;
+        }
+
+        CallComposerPictureTransfer transfer = transferFactory.create(mContext,
+                mSubscriptionId, remoteUrl, sExecutorService);
+
+        AtomicBoolean hasRetried = new AtomicBoolean(false);
+        transfer.setCallback(new PictureCallback() {
+            @Override
+            public void onError(int error) {
+                callback.accept(Pair.create(null, error));
+            }
+
+            @Override
+            public void onRetryNeeded(boolean credentialRefresh, long backoffMillis) {
+                if (hasRetried.getAndSet(true)) {
+                    Log.e(TAG, "Giving up on image download after one retry.");
+                    callback.accept(Pair.create(null,
+                            TelephonyManager.CallComposerException.ERROR_NETWORK_UNAVAILABLE));
+                    return;
+                }
+                GbaCredentialsSupplier supplier =
+                        (realm, executor) ->
+                                getGbaCredentials(credentialRefresh, realm, executor);
+
+                sExecutorService.schedule(() -> transfer.downloadPicture(supplier),
+                        backoffMillis, TimeUnit.MILLISECONDS);
+            }
+
+            @Override
+            public void onDownloadSuccessful(ImageData data) {
+                ByteArrayInputStream imageDataInput =
+                        new ByteArrayInputStream(data.getImageBytes());
+                mCallLogProxy.storeCallComposerPictureAsUser(
+                        mContext, UserHandle.CURRENT, imageDataInput,
+                        sExecutorService,
+                        new OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>() {
+                            @Override
+                            public void onResult(@NonNull Uri result) {
+                                callback.accept(Pair.create(
+                                        result, TelephonyManager.CallComposerException.SUCCESS));
+                            }
+
+                            @Override
+                            public void onError(CallLog.CallComposerLoggingException e) {
+                                // Just report an error to the client for now.
+                                callback.accept(Pair.create(null,
+                                        TelephonyManager.CallComposerException.ERROR_UNKNOWN));
+                            }
+                        });
+            }
+        });
+
+        transfer.downloadPicture(((realm, executor) -> getGbaCredentials(false, realm, executor)));
+    }
+
+    public void storeUploadedPictureToCallLog(UUID id, Consumer<Uri> callback) {
+        ImageData data = mCachedImages.get(id);
+        if (data == null) {
+            Log.e(TAG, "No picture associated with uuid " + id);
+            callback.accept(null);
+            return;
+        }
+        ByteArrayInputStream imageDataInput =
+                new ByteArrayInputStream(data.getImageBytes());
+        mCallLogProxy.storeCallComposerPictureAsUser(mContext, UserHandle.CURRENT, imageDataInput,
+                sExecutorService,
+                new OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>() {
+                    @Override
+                    public void onResult(@NonNull Uri result) {
+                        callback.accept(result);
+                        clearCachedData();
+                    }
+
+                    @Override
+                    public void onError(CallLog.CallComposerLoggingException e) {
+                        // Just report an error to the client for now.
+                        Log.e(TAG, "Error logging uploaded image: " + e.getErrorCode());
+                        callback.accept(null);
+                        clearCachedData();
+                    }
+                });
+    }
+
+    public String getServerUrlForImageId(UUID id) {
+        return mCachedServerUrls.get(id);
+    }
+
+    public void clearCachedData() {
+        mCachedServerUrls.clear();
+        mCachedImages.clear();
+    }
+
+    private byte[] getPlaceholderPictureAsBytes() {
+        InputStream resourceInput = mContext.getResources().openRawResource(R.drawable.cupcake);
+        try {
+            return readBytes(resourceInput);
+        } catch (Exception e) {
+            return new byte[] {};
+        }
+    }
+
+    private static byte[] readBytes(InputStream inputStream) throws Exception {
+        byte[] buffer = new byte[1024];
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        int numRead;
+        do {
+            numRead = inputStream.read(buffer);
+            if (numRead > 0) output.write(buffer, 0, numRead);
+        } while (numRead > 0);
+        return output.toByteArray();
+    }
+
+    private CompletableFuture<GbaCredentials> getGbaCredentials(
+            boolean forceRefresh, String nafId, Executor executor) {
+        synchronized (mCachedCredentials) {
+            if (!forceRefresh && mCachedCredentials.containsKey(nafId)) {
+                return CompletableFuture.completedFuture(mCachedCredentials.get(nafId));
+            }
+            if (forceRefresh) {
+                mCachedCredentials.remove(nafId);
+            }
+        }
+
+        UaSecurityProtocolIdentifier securityProtocolIdentifier =
+                new UaSecurityProtocolIdentifier.Builder()
+                        .setOrg(UaSecurityProtocolIdentifier.ORG_3GPP)
+                        .setProtocol(UaSecurityProtocolIdentifier
+                                .UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION)
+                        .build();
+        CompletableFuture<GbaCredentials> resultFuture = new CompletableFuture<>();
+
+        mTelephonyManager.bootstrapAuthenticationRequest(TelephonyManager.APPTYPE_UNKNOWN,
+                Uri.parse(nafId), securityProtocolIdentifier, forceRefresh, executor,
+                new TelephonyManager.BootstrapAuthenticationCallback() {
+                    @Override
+                    public void onKeysAvailable(byte[] gbaKey, String transactionId) {
+                        GbaCredentials creds = new GbaCredentials(transactionId, gbaKey);
+                        synchronized (mCachedCredentials) {
+                            mCachedCredentials.put(nafId, creds);
+                        }
+                        resultFuture.complete(creds);
+                    }
+
+                    @Override
+                    public void onAuthenticationFailure(int reason) {
+                        Log.e(TAG, "GBA auth failed: reason=" + reason);
+                        resultFuture.complete(null);
+                    }
+                });
+
+        return resultFuture;
+    }
+
+    @VisibleForTesting
+    static ScheduledExecutorService getExecutor() {
+        return sExecutorService;
+    }
+
+    @VisibleForTesting
+    void setCallLogProxy(CallLogProxy proxy) {
+        mCallLogProxy = proxy;
+    }
+}
diff --git a/src/com/android/phone/callcomposer/CallComposerPictureTransfer.java b/src/com/android/phone/callcomposer/CallComposerPictureTransfer.java
new file mode 100644
index 0000000..1a176dd
--- /dev/null
+++ b/src/com/android/phone/callcomposer/CallComposerPictureTransfer.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.callcomposer;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.http.multipart.MultipartEntity;
+import com.android.internal.http.multipart.Part;
+
+import com.google.common.net.MediaType;
+
+import gov.nist.javax.sip.header.WWWAuthenticate;
+
+import org.xml.sax.InputSource;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+public class CallComposerPictureTransfer {
+    private static final String TAG = CallComposerPictureTransfer.class.getSimpleName();
+    private static final int HTTP_TIMEOUT_MILLIS = 20000;
+    private static final int DEFAULT_BACKOFF_MILLIS = 1000;
+    private static final String THREE_GPP_GBA = "3gpp-gba";
+
+    private static final int ERROR_UNKNOWN = 0;
+    private static final int ERROR_HTTP_TIMEOUT = 1;
+    private static final int ERROR_NO_AUTH_REQUIRED = 2;
+    private static final int ERROR_FORBIDDEN = 3;
+
+    public interface Factory {
+        default CallComposerPictureTransfer create(Context context, int subscriptionId, String url,
+                ExecutorService executorService) {
+            return new CallComposerPictureTransfer(context, subscriptionId, url, executorService);
+        }
+    }
+
+    public interface PictureCallback {
+        default void onError(@TelephonyManager.CallComposerException.CallComposerError int error) {}
+        default void onRetryNeeded(boolean credentialRefresh, long backoffMillis) {}
+        default void onUploadSuccessful(String serverUrl) {}
+        default void onDownloadSuccessful(ImageData data) {}
+    }
+
+    private static class NetworkAccessException extends RuntimeException {
+        final int errorCode;
+
+        NetworkAccessException(int errorCode) {
+            this.errorCode = errorCode;
+        }
+    }
+
+    private final Context mContext;
+    private final int mSubscriptionId;
+    private final String mUrl;
+    private final ExecutorService mExecutorService;
+
+    private PictureCallback mCallback;
+
+    private CallComposerPictureTransfer(Context context, int subscriptionId, String url,
+            ExecutorService executorService) {
+        mContext = context;
+        mSubscriptionId = subscriptionId;
+        mExecutorService = executorService;
+        mUrl = url;
+    }
+
+    @VisibleForTesting
+    public void setCallback(PictureCallback callback) {
+        mCallback = callback;
+    }
+
+    public void uploadPicture(ImageData image,
+            GbaCredentialsSupplier credentialsSupplier) {
+        CompletableFuture<Network> networkFuture = getNetworkForCallComposer();
+        CompletableFuture<WWWAuthenticate> authorizationHeaderFuture = networkFuture
+                .thenApplyAsync((network) -> prepareInitialPost(network, mUrl), mExecutorService)
+                .thenComposeAsync(this::obtainAuthenticateHeader, mExecutorService)
+                .thenApplyAsync(DigestAuthUtils::parseAuthenticateHeader);
+        CompletableFuture<GbaCredentials> credsFuture = authorizationHeaderFuture
+                .thenComposeAsync((header) ->
+                        credentialsSupplier.getCredentials(header.getRealm(), mExecutorService),
+                        mExecutorService);
+
+        CompletableFuture<String> authorizationFuture =
+                authorizationHeaderFuture.thenCombineAsync(credsFuture,
+                        (authHeader, credentials) ->
+                                DigestAuthUtils.generateAuthorizationHeader(
+                                        authHeader, credentials, "POST", mUrl),
+                        mExecutorService)
+                        .whenCompleteAsync(
+                                (authorization, error) -> handleExceptionalCompletion(error),
+                                mExecutorService);
+
+        CompletableFuture<String> networkUrlFuture =
+                networkFuture.thenCombineAsync(authorizationFuture,
+                        (network, auth) -> sendActualImageUpload(network, auth, image),
+                        mExecutorService);
+        networkUrlFuture.thenAcceptAsync((result) -> {
+            if (result != null) mCallback.onUploadSuccessful(result);
+        }, mExecutorService);
+    }
+
+    public void downloadPicture(GbaCredentialsSupplier credentialsSupplier) {
+        CompletableFuture<Network> networkFuture = getNetworkForCallComposer();
+        CompletableFuture<HttpURLConnection> getConnectionFuture =
+                networkFuture.thenApplyAsync((network) ->
+                        prepareImageDownloadRequest(network, mUrl), mExecutorService);
+
+        CompletableFuture<ImageData> immediatelyDownloadableImage = getConnectionFuture
+                .thenComposeAsync((conn) -> {
+                    try {
+                        if (conn.getResponseCode() != 200) {
+                            return CompletableFuture.completedFuture(null);
+                        }
+                    } catch (IOException e) {
+                        logException("IOException obtaining return code: ", e);
+                        throw new NetworkAccessException(ERROR_HTTP_TIMEOUT);
+                    }
+                    return CompletableFuture.completedFuture(downloadImageFromConnection(conn));
+                }, mExecutorService);
+
+        CompletableFuture<ImageData> authRequiredImage = getConnectionFuture
+                .thenComposeAsync((conn) -> {
+                    try {
+                        if (conn.getResponseCode() == 200) {
+                            // handled by above case
+                            return CompletableFuture.completedFuture(null);
+                        }
+                    } catch (IOException e) {
+                        logException("IOException obtaining return code: ", e);
+                        throw new NetworkAccessException(ERROR_HTTP_TIMEOUT);
+                    }
+                    CompletableFuture<WWWAuthenticate> authenticateHeaderFuture =
+                            obtainAuthenticateHeader(conn)
+                                    .thenApply(DigestAuthUtils::parseAuthenticateHeader);
+                    CompletableFuture<GbaCredentials> credsFuture = authenticateHeaderFuture
+                            .thenComposeAsync((header) ->
+                                    credentialsSupplier.getCredentials(header.getRealm(),
+                                            mExecutorService), mExecutorService);
+
+                    CompletableFuture<String> authorizationFuture = authenticateHeaderFuture
+                            .thenCombineAsync(credsFuture, (authHeader, credentials) ->
+                                    DigestAuthUtils.generateAuthorizationHeader(
+                                            authHeader, credentials, "GET", mUrl),
+                                    mExecutorService)
+                            .whenCompleteAsync((authorization, error) ->
+                                    handleExceptionalCompletion(error), mExecutorService);
+
+                    return networkFuture.thenCombineAsync(authorizationFuture,
+                            this::downloadImageWithAuth, mExecutorService);
+                }, mExecutorService);
+
+        CompletableFuture.allOf(immediatelyDownloadableImage, authRequiredImage).thenRun(() -> {
+            ImageData fromImmediate = immediatelyDownloadableImage.getNow(null);
+            ImageData fromAuth = authRequiredImage.getNow(null);
+            // If both of these are null, that means an error happened somewhere in the chain.
+            // in that case, the error has already been transmitted to the callback, so ignore it.
+            if (fromAuth == null && fromImmediate == null) {
+                Log.w(TAG, "No result from download -- error happened sometime earlier");
+            }
+            if (fromAuth != null) mCallback.onDownloadSuccessful(fromAuth);
+            mCallback.onDownloadSuccessful(fromImmediate);
+        });
+    }
+
+    private CompletableFuture<Network> getNetworkForCallComposer() {
+        ConnectivityManager connectivityManager =
+                mContext.getSystemService(ConnectivityManager.class);
+        NetworkRequest pictureNetworkRequest = new NetworkRequest.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                .build();
+        CompletableFuture<Network> resultFuture = new CompletableFuture<>();
+        connectivityManager.requestNetwork(pictureNetworkRequest,
+                new ConnectivityManager.NetworkCallback() {
+                    @Override
+                    public void onAvailable(@NonNull Network network) {
+                        resultFuture.complete(network);
+                    }
+                });
+        return resultFuture;
+    }
+
+    private static HttpURLConnection prepareInitialPost(Network network, String uploadUrl) {
+        try {
+            HttpURLConnection connection =
+                    (HttpURLConnection) network.openConnection(new URL(uploadUrl));
+            connection.setRequestMethod("POST");
+            connection.setInstanceFollowRedirects(false);
+            connection.setConnectTimeout(HTTP_TIMEOUT_MILLIS);
+            connection.setReadTimeout(HTTP_TIMEOUT_MILLIS);
+            connection.setRequestProperty("User-Agent", THREE_GPP_GBA);
+            return connection;
+        } catch (MalformedURLException e) {
+            Log.e(TAG, "Malformed URL: " + uploadUrl);
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            logException("IOException opening network: ", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static HttpURLConnection prepareImageDownloadRequest(Network network, String imageUrl) {
+        try {
+            HttpURLConnection connection =
+                    (HttpURLConnection) network.openConnection(new URL(imageUrl));
+            connection.setRequestMethod("GET");
+            connection.setConnectTimeout(HTTP_TIMEOUT_MILLIS);
+            connection.setReadTimeout(HTTP_TIMEOUT_MILLIS);
+            connection.setRequestProperty("User-Agent", THREE_GPP_GBA);
+            return connection;
+        } catch (MalformedURLException e) {
+            Log.e(TAG, "Malformed URL: " + imageUrl);
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            logException("IOException opening network: ", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    // Attempts to connect via the supplied connection, expecting a HTTP 401 in response. Throws
+    // an IOException if the connection times out.
+    // After the response is received, returns the WWW-Authenticate header in the following form:
+    // "WWW-Authenticate:<method> <params>"
+    private CompletableFuture<String> obtainAuthenticateHeader(
+            HttpURLConnection connection) {
+        return CompletableFuture.supplyAsync(() -> {
+            int responseCode;
+            try {
+                responseCode = connection.getResponseCode();
+            } catch (IOException e) {
+                logException("IOException obtaining auth header: ", e);
+                throw new NetworkAccessException(ERROR_HTTP_TIMEOUT);
+            }
+            if (responseCode == 204) {
+                throw new NetworkAccessException(ERROR_NO_AUTH_REQUIRED);
+            } else if (responseCode == 403) {
+                throw new NetworkAccessException(ERROR_FORBIDDEN);
+            } else if (responseCode != 401) {
+                Log.w(TAG, "Received unexpected response in auth request, code= "
+                        + responseCode);
+                throw new NetworkAccessException(ERROR_UNKNOWN);
+            }
+
+            return connection.getHeaderField(DigestAuthUtils.WWW_AUTHENTICATE);
+        }, mExecutorService);
+    }
+
+    private ImageData downloadImageWithAuth(Network network, String authorization) {
+        HttpURLConnection connection = prepareImageDownloadRequest(network, mUrl);
+        connection.addRequestProperty("Authorization", authorization);
+        return downloadImageFromConnection(connection);
+    }
+
+    private ImageData downloadImageFromConnection(HttpURLConnection conn) {
+        try {
+            if (conn.getResponseCode() != 200) {
+                Log.w(TAG, "Got response code " + conn.getResponseCode() + " when trying"
+                        + " to download image");
+                if (conn.getResponseCode() == 401) {
+                    Log.i(TAG, "Got 401 even with auth -- key refresh needed?");
+                    mCallback.onRetryNeeded(true, 0);
+                }
+                return null;
+            }
+        } catch (IOException e) {
+            logException("IOException obtaining return code: ", e);
+            throw new NetworkAccessException(ERROR_HTTP_TIMEOUT);
+        }
+
+        String contentType = conn.getContentType();
+        ByteArrayOutputStream imageDataOut = new ByteArrayOutputStream();
+        byte[] buffer = new byte[4096];
+        int numRead;
+        try {
+            InputStream is = conn.getInputStream();
+            while (true) {
+                numRead = is.read(buffer);
+                if (numRead < 0) break;
+                imageDataOut.write(buffer, 0, numRead);
+            }
+        } catch (IOException e) {
+            logException("IOException reading from image body: ", e);
+            return null;
+        }
+
+        return new ImageData(imageDataOut.toByteArray(), contentType, null);
+    }
+
+    private void handleExceptionalCompletion(Throwable error) {
+        if (error != null) {
+            if (error.getCause() instanceof NetworkAccessException) {
+                int code = ((NetworkAccessException) error.getCause()).errorCode;
+                if (code == ERROR_UNKNOWN || code == ERROR_HTTP_TIMEOUT) {
+                    scheduleRetry();
+                } else {
+                    int failureCode;
+                    if (code == ERROR_FORBIDDEN) {
+                        failureCode = TelephonyManager.CallComposerException
+                                .ERROR_AUTHENTICATION_FAILED;
+                    } else {
+                        failureCode = TelephonyManager.CallComposerException
+                                .ERROR_UNKNOWN;
+                    }
+                    deliverFailure(failureCode);
+                }
+            } else {
+                deliverFailure(TelephonyManager.CallComposerException.ERROR_UNKNOWN);
+            }
+        }
+    }
+
+    private void scheduleRetry() {
+        mCallback.onRetryNeeded(false, DEFAULT_BACKOFF_MILLIS);
+    }
+
+    private void deliverFailure(int code) {
+        mCallback.onError(code);
+    }
+
+    private static Part makeUploadPart(String name, String contentType, String filename,
+            byte[] data) {
+        return new Part() {
+            @Override
+            public String getName() {
+                return name;
+            }
+
+            @Override
+            public String getContentType() {
+                return contentType;
+            }
+
+            @Override
+            public String getCharSet() {
+                return null;
+            }
+
+            @Override
+            public String getTransferEncoding() {
+                return null;
+            }
+
+            @Override
+            public void sendDispositionHeader(OutputStream out) throws IOException {
+                super.sendDispositionHeader(out);
+                if (filename != null) {
+                    String fileNameSuffix = ";filename=\"" + filename + "\"";
+                    out.write(fileNameSuffix.getBytes());
+                }
+            }
+
+            @Override
+            protected void sendData(OutputStream out) throws IOException {
+                out.write(data);
+            }
+
+            @Override
+            protected long lengthOfData() throws IOException {
+                return data.length;
+            }
+        };
+    }
+
+    private String sendActualImageUpload(Network network, String authHeader, ImageData image) {
+        Part transactionIdPart = makeUploadPart("tid", "text/plain",
+                null, image.getId().getBytes());
+        Part imageDataPart = makeUploadPart("File", image.getMimeType(),
+                image.getId(), image.getImageBytes());
+
+        MultipartEntity multipartEntity =
+                new MultipartEntity(new Part[] {transactionIdPart, imageDataPart});
+
+        HttpURLConnection connection = prepareInitialPost(network, mUrl);
+        connection.setDoOutput(true);
+        connection.addRequestProperty("Authorization", authHeader);
+        try (OutputStream requestBodyOut = connection.getOutputStream()) {
+            multipartEntity.writeTo(requestBodyOut);
+        } catch (IOException e) {
+            logException("IOException making request to upload image: ", e);
+            throw new RuntimeException(e);
+        }
+
+        try {
+            int response = connection.getResponseCode();
+            if (response == 401 || response == 403) {
+                deliverFailure(TelephonyManager.CallComposerException.ERROR_AUTHENTICATION_FAILED);
+                return null;
+            }
+            if (response == 503) {
+                // TODO: implement parsing of retry-after and schedule a retry with that time
+                scheduleRetry();
+                return null;
+            }
+            if (response != 200) {
+                scheduleRetry();
+                return null;
+            }
+            String responseBody = readResponseBody(connection);
+            String parsedUrl = parseImageUploadResponseXmlForUrl(responseBody);
+            Log.i(TAG, "Parsed URL as upload result: " + parsedUrl);
+            return parsedUrl;
+        } catch (IOException e) {
+            logException("IOException getting response to image upload: ", e);
+            deliverFailure(TelephonyManager.CallComposerException.ERROR_UNKNOWN);
+            return null;
+        }
+    }
+
+    private static String parseImageUploadResponseXmlForUrl(String xmlData) {
+        NamespaceContext ns = new NamespaceContext() {
+            public String getNamespaceURI(String prefix) {
+                return "urn:gsma:params:xml:ns:rcs:rcs:fthttp";
+            }
+
+            public String getPrefix(String uri) {
+                throw new UnsupportedOperationException();
+            }
+
+            public Iterator getPrefixes(String uri) {
+                throw new UnsupportedOperationException();
+            }
+        };
+
+        XPath xPath = XPathFactory.newInstance().newXPath();
+        xPath.setNamespaceContext(ns);
+        StringReader reader = new StringReader(xmlData);
+        try {
+            return (String) xPath.evaluate("/a:file/a:file-info[@type='file']/a:data/@url",
+                    new InputSource(reader), XPathConstants.STRING);
+        } catch (XPathExpressionException e) {
+            logException("Error parsing response XML:", e);
+            return null;
+        }
+    }
+
+    private static String readResponseBody(HttpURLConnection connection) {
+        Charset charset = MediaType.parse(connection.getContentType())
+                .charset().or(Charset.defaultCharset());
+        StringBuilder sb = new StringBuilder();
+        try (InputStream inputStream = connection.getInputStream()) {
+            String outLine;
+            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset));
+            while ((outLine = reader.readLine()) != null) {
+                sb.append(outLine);
+            }
+        } catch (IOException e) {
+            logException("IOException reading request body: ", e);
+            return null;
+        }
+        return sb.toString();
+    }
+
+    private static void logException(String message, Throwable e) {
+        StringWriter log = new StringWriter();
+        log.append(message);
+        log.append(":\n");
+        log.append(e.getMessage());
+        PrintWriter pw = new PrintWriter(log);
+        e.printStackTrace(pw);
+        Log.e(TAG, log.toString());
+    }
+}
diff --git a/src/com/android/phone/callcomposer/DigestAuthUtils.java b/src/com/android/phone/callcomposer/DigestAuthUtils.java
new file mode 100644
index 0000000..52a278b
--- /dev/null
+++ b/src/com/android/phone/callcomposer/DigestAuthUtils.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 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.callcomposer;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.google.common.io.BaseEncoding;
+
+import gov.nist.javax.sip.address.GenericURI;
+import gov.nist.javax.sip.header.Authorization;
+import gov.nist.javax.sip.header.WWWAuthenticate;
+import gov.nist.javax.sip.parser.WWWAuthenticateParser;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.text.ParseException;
+
+public class DigestAuthUtils {
+    private static final String TAG = DigestAuthUtils.class.getSimpleName();
+
+    public static final String WWW_AUTHENTICATE = "www-authenticate";
+    private static final String MD5_ALGORITHM = "md5";
+    private static final int CNONCE_LENGTH_BYTES = 16;
+    private static final String AUTH_QOP = "auth";
+
+    public static WWWAuthenticate parseAuthenticateHeader(String header) {
+        String reconstitutedHeader = WWW_AUTHENTICATE + ": " + header;
+        WWWAuthenticate parsedHeader;
+        try {
+            return (WWWAuthenticate) (new WWWAuthenticateParser(reconstitutedHeader).parse());
+        } catch (ParseException e) {
+            Log.e(TAG, "Error parsing received auth header: " + e);
+            return null;
+        }
+    }
+
+    // Generates the Authorization header for use in future requests to the call composer server.
+    public static String generateAuthorizationHeader(WWWAuthenticate parsedHeader,
+            GbaCredentials credentials, String method, String uri) {
+        if (!TextUtils.isEmpty(parsedHeader.getAlgorithm())
+                && !MD5_ALGORITHM.equals(parsedHeader.getAlgorithm().toLowerCase())) {
+            Log.e(TAG, "This client only supports MD5 auth");
+        }
+
+        Log.i(TAG, "nonce=" + parsedHeader.getNonce());
+
+        String clientNonce = makeClientNonce();
+
+        String response = computeResponse(parsedHeader.getNonce(), clientNonce, AUTH_QOP,
+                credentials.getTransactionId(), parsedHeader.getRealm(), credentials.getKey(),
+                method, uri);
+
+        Authorization replyHeader = new Authorization();
+        try {
+            replyHeader.setScheme(parsedHeader.getScheme());
+            replyHeader.setUsername(credentials.getTransactionId());
+            replyHeader.setURI(new WorkaroundURI(uri));
+            replyHeader.setQop(AUTH_QOP);
+            replyHeader.setCNonce(clientNonce);
+            replyHeader.setNonceCount(1);
+            replyHeader.setResponse(response);
+            replyHeader.setOpaque(parsedHeader.getOpaque());
+            replyHeader.setAlgorithm(parsedHeader.getAlgorithm());
+
+        } catch (ParseException e) {
+            Log.e(TAG, "Error parsing while constructing reply header: " + e);
+            return null;
+        }
+
+        return replyHeader.encode();
+    }
+
+    public static String computeResponse(String serverNonce, String clientNonce, String qop,
+            String username, String realm, byte[] password, String method, String uri) {
+        String a1Hash = generateA1Hash(username, realm, password);
+        String a2Hash = generateA2Hash(method, uri);
+
+        // this is the nonce-count; since we don't reuse, it's always 1
+        String nonceCount = "00000001";
+        MessageDigest md5Digest = getMd5Digest();
+
+        String hashInput = String.join(":",
+                a1Hash,
+                serverNonce,
+                nonceCount,
+                clientNonce,
+                qop,
+                a2Hash);
+        md5Digest.update(hashInput.getBytes());
+        return base16(md5Digest.digest());
+    }
+
+    private static String makeClientNonce() {
+        SecureRandom rand = new SecureRandom();
+        byte[] clientNonceBytes = new byte[CNONCE_LENGTH_BYTES];
+        rand.nextBytes(clientNonceBytes);
+        return base16(clientNonceBytes);
+    }
+
+    private static String generateA1Hash(
+            String bootstrapTransactionId, String realm, byte[] gbaKey) {
+        MessageDigest md5Digest = getMd5Digest();
+
+        String gbaKeyBase64 = BaseEncoding.base64().encode(gbaKey);
+        String hashInput = String.join(":", bootstrapTransactionId, realm, gbaKeyBase64);
+        md5Digest.update(hashInput.getBytes());
+
+        return base16(md5Digest.digest());
+    }
+
+    private static String generateA2Hash(String method, String requestUri) {
+        MessageDigest md5Digest = getMd5Digest();
+        md5Digest.update(String.join(":", method, requestUri).getBytes());
+        return base16(md5Digest.digest());
+    }
+
+    private static String base16(byte[] input) {
+        return BaseEncoding.base16().encode(input).toLowerCase();
+    }
+
+    private static MessageDigest getMd5Digest() {
+        try {
+            return MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Couldn't find MD5 algorithm: " + e);
+        }
+    }
+
+    private static class WorkaroundURI extends GenericURI {
+        public WorkaroundURI(String uriString) {
+            this.uriString = uriString;
+            this.scheme = "";
+        }
+    }
+}
diff --git a/src/com/android/phone/callcomposer/GbaCredentials.java b/src/com/android/phone/callcomposer/GbaCredentials.java
new file mode 100644
index 0000000..25a0cd5
--- /dev/null
+++ b/src/com/android/phone/callcomposer/GbaCredentials.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.callcomposer;
+
+public class GbaCredentials {
+    private final String mTransactionId;
+    private final byte[] mKey;
+
+    public GbaCredentials(String transactionId, byte[] key) {
+        mTransactionId = transactionId;
+        mKey = key;
+    }
+
+    public String getTransactionId() {
+        return mTransactionId;
+    }
+
+    public byte[] getKey() {
+        return mKey;
+    }
+}
diff --git a/src/com/android/phone/callcomposer/GbaCredentialsSupplier.java b/src/com/android/phone/callcomposer/GbaCredentialsSupplier.java
new file mode 100644
index 0000000..9e5bb6a
--- /dev/null
+++ b/src/com/android/phone/callcomposer/GbaCredentialsSupplier.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 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.callcomposer;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+
+public interface GbaCredentialsSupplier {
+    CompletableFuture<GbaCredentials> getCredentials(String realm, Executor executor);
+}
diff --git a/src/com/android/phone/callcomposer/ImageData.java b/src/com/android/phone/callcomposer/ImageData.java
new file mode 100644
index 0000000..fc93485
--- /dev/null
+++ b/src/com/android/phone/callcomposer/ImageData.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.callcomposer;
+
+public class ImageData {
+    private final byte[] mImageBytes;
+    private final String mMimeType;
+
+    private String mId;
+
+    public ImageData(byte[] imageBytes, String mimeType, String id) {
+        mImageBytes = imageBytes;
+        mMimeType = mimeType;
+        mId = id;
+    }
+
+    public byte[] getImageBytes() {
+        return mImageBytes;
+    }
+
+    public String getMimeType() {
+        return mMimeType;
+    }
+
+    public String getId() {
+        return mId;
+    }
+
+    public void setId(String id) {
+        mId = id;
+    }
+}
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 57caede..f24e7d6 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -26,7 +26,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
-import android.permission.PermissionManager;
+import android.permission.LegacyPermissionManager;
 import android.service.euicc.EuiccService;
 import android.telephony.euicc.EuiccManager;
 import android.util.Log;
@@ -55,14 +55,15 @@
             PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
                     | PackageManager.GET_RESOLVED_FILTER;
 
-    private PermissionManager mPermissionManager;
+    private LegacyPermissionManager mPermissionManager;
     private boolean mGrantPermissionDone = false;
     private ThreadPoolExecutor mExecutor;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mPermissionManager = (PermissionManager) getSystemService(Context.PERMISSION_SERVICE);
+        mPermissionManager = (LegacyPermissionManager) getSystemService(
+                Context.LEGACY_PERMISSION_SERVICE);
         mExecutor = new ThreadPoolExecutor(
                 1 /* corePoolSize */,
                 1 /* maxPoolSize */,
diff --git a/src/com/android/phone/otasp/OtaspActivationService.java b/src/com/android/phone/otasp/OtaspActivationService.java
index 6ed2ea8..72bf249 100644
--- a/src/com/android/phone/otasp/OtaspActivationService.java
+++ b/src/com/android/phone/otasp/OtaspActivationService.java
@@ -31,6 +31,7 @@
 import com.android.internal.telephony.GsmCdmaConnection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.ServiceStateTracker;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.PhoneUtils;
 
@@ -77,6 +78,11 @@
     public void onCreate() {
         logd("otasp service onCreate");
         mPhone = PhoneGlobals.getPhone();
+        ServiceStateTracker sst = mPhone.getServiceStateTracker();
+        if (sst != null && sst.getOtasp() != TelephonyManager.OTASP_NEEDED) {
+            logd("OTASP is not needed.");
+            return;
+        }
         if ((sIccId == null) || !sIccId.equals(mPhone.getIccSerialNumber())) {
             // reset to allow activation retry on new sim
             sIccId = mPhone.getIccSerialNumber();
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 37212cf..523c710 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -19,6 +19,9 @@
 import android.content.Context;
 import android.media.AudioManager;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.os.PersistableBundle;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
@@ -56,13 +59,10 @@
 
     private static final int WFC_QUERY_TIMEOUT_MILLIS = 20;
 
-    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-        /**
-         * Disable the TTY setting when in/out of a call (and if carrier doesn't
-         * support VoLTE with TTY).
-         * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
-         * java.lang.String)
-         */
+    private final PhoneStateListener mPhoneStateListener = new AccessibilityPhoneStateListener();
+
+    private final class AccessibilityPhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.CallStateChangedListener {
         @Override
         public void onCallStateChanged(int state, String incomingNumber) {
             if (DBG) Log.d(LOG_TAG, "PhoneStateListener.onCallStateChanged: state=" + state);
@@ -78,7 +78,7 @@
                         || (telephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE));
             }
         }
-    };
+    }
 
     private Context mContext;
     private AudioManager mAudioManager;
@@ -122,8 +122,12 @@
                     (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
             boolean isRoaming = tm.isNetworkRoaming(
                     SubscriptionManager.getDefaultVoiceSubscriptionId());
+            boolean alwaysAllowWhileRoaming = isCarrierAllowRttWhenRoaming(
+                    SubscriptionManager.getDefaultVoiceSubscriptionId());
 
-            boolean shouldDisableBecauseRoamingOffWfc = isRoaming && !isOnWfc();
+            boolean shouldDisableBecauseRoamingOffWfc =
+                    (isRoaming && !isOnWfc()) && !alwaysAllowWhileRoaming;
+
             if (shouldDisableBecauseRoamingOffWfc) {
                 mButtonRtt.setSummary(TextUtils.concat(getText(R.string.rtt_mode_summary), "\n",
                         getText(R.string.no_rtt_when_roaming)));
@@ -144,7 +148,8 @@
         super.onResume();
         TelephonyManager tm =
                 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+        tm.registerPhoneStateListener(new HandlerExecutor(new Handler(Looper.getMainLooper())),
+                mPhoneStateListener);
     }
 
     @Override
@@ -152,7 +157,7 @@
         super.onPause();
         TelephonyManager tm =
                 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        tm.unregisterPhoneStateListener(mPhoneStateListener);
     }
 
     @Override
@@ -277,4 +282,13 @@
         return configManager.getConfig().getBoolean(
                 CarrierConfigManager.KEY_TTY_SUPPORTED_BOOL);
     }
+
+    /**
+     * Determines from carrier config whether to always allow RTT while roaming.
+     */
+    private boolean isCarrierAllowRttWhenRoaming(int subId) {
+        PersistableBundle b =
+                PhoneGlobals.getInstance().getCarrierConfigForSubId(subId);
+        return b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL);
+    }
 }
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 31b7a9e..fd8d936 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -17,7 +17,6 @@
 package com.android.phone.settings;
 
 import static android.net.ConnectivityManager.NetworkCallback;
-import static android.provider.Settings.Global.PREFERRED_NETWORK_MODE;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -37,9 +36,11 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.SystemProperties;
-import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentityCdma;
 import android.telephony.CellIdentityGsm;
@@ -50,20 +51,20 @@
 import android.telephony.CellInfoGsm;
 import android.telephony.CellInfoLte;
 import android.telephony.CellInfoWcdma;
-import android.telephony.CellLocation;
 import android.telephony.CellSignalStrengthCdma;
 import android.telephony.CellSignalStrengthGsm;
 import android.telephony.CellSignalStrengthLte;
 import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.DataSpecificRegistrationInfo;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
+import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cdma.CdmaCellLocation;
-import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
@@ -199,9 +200,6 @@
     }
 
     private static final int EVENT_CFI_CHANGED = 302;
-
-    private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
-    private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
     private static final int EVENT_QUERY_SMSC_DONE = 1005;
     private static final int EVENT_UPDATE_SMSC_DONE = 1006;
     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
@@ -228,7 +226,6 @@
     private TextView mDBm;
     private TextView mMwi;
     private TextView mCfi;
-    private TextView mLocation;
     private TextView mCellInfo;
     private TextView mSent;
     private TextView mReceived;
@@ -239,6 +236,11 @@
     private TextView mDnsCheckState;
     private TextView mDownlinkKbps;
     private TextView mUplinkKbps;
+    private TextView mEndcAvailable;
+    private TextView mDcnrRestricted;
+    private TextView mNrAvailable;
+    private TextView mNrState;
+    private TextView mNrFrequency;
     private EditText mSmsc;
     private Switch mRadioPowerOnSwitch;
     private Button mCellInfoRefreshRateButton;
@@ -275,7 +277,6 @@
     private boolean mCfiValue = false;
 
     private List<CellInfo> mCellInfoResult = null;
-    private CellLocation mCellLocationResult = null;
 
     private int mPreferredNetworkTypeResult;
     private int mCellInfoRefreshRateIndex;
@@ -296,9 +297,19 @@
 
     // not final because we need to recreate this object to register on a new subId (b/117555407)
     private PhoneStateListener mPhoneStateListener = new RadioInfoPhoneStateListener();
-    private class RadioInfoPhoneStateListener extends PhoneStateListener {
+    private class RadioInfoPhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.DataConnectionStateChangedListener,
+            PhoneStateListener.DataActivityListener,
+            PhoneStateListener.CallStateChangedListener,
+            PhoneStateListener.MessageWaitingIndicatorChangedListener,
+            PhoneStateListener.CallForwardingIndicatorChangedListener,
+            PhoneStateListener.CellInfoChangedListener,
+            PhoneStateListener.CellLocationChangedListener,
+            PhoneStateListener.SignalStrengthsChangedListener,
+            PhoneStateListener.ServiceStateChangedListener {
+
         @Override
-        public void onDataConnectionStateChanged(int state) {
+        public void onDataConnectionStateChanged(int state, int networkType) {
             updateDataState();
             updateNetworkType();
         }
@@ -315,16 +326,6 @@
         }
 
         @Override
-        public void onPreciseCallStateChanged(PreciseCallState preciseState) {
-            updateNetworkType();
-        }
-
-        @Override
-        public void onCellLocationChanged(CellLocation location) {
-            updateLocation(location);
-        }
-
-        @Override
         public void onMessageWaitingIndicatorChanged(boolean mwi) {
             mMwiValue = mwi;
             updateMessageWaiting();
@@ -356,6 +357,7 @@
             updateRadioPowerState();
             updateNetworkType();
             updateImsProvisionedState();
+            updateNrStats(serviceState);
         }
 
     }
@@ -376,8 +378,7 @@
 
     private void updatePreferredNetworkType(int type) {
         if (type >= PREFERRED_NETWORK_LABELS.length || type < 0) {
-            log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown "
-                    + "type=" + type);
+            log("Network type: unknown type value=" + type);
             type = PREFERRED_NETWORK_LABELS.length - 1; //set to Unknown
         }
         mPreferredNetworkTypeResult = type;
@@ -405,21 +406,6 @@
         public void handleMessage(Message msg) {
             AsyncResult ar;
             switch (msg.what) {
-                case EVENT_QUERY_PREFERRED_TYPE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception == null && ar.result != null) {
-                        updatePreferredNetworkType(((int []) ar.result)[0]);
-                    } else {
-                        //In case of an exception, we will set this to unknown
-                        updatePreferredNetworkType(PREFERRED_NETWORK_LABELS.length - 1);
-                    }
-                    break;
-                case EVENT_SET_PREFERRED_TYPE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception != null) {
-                        log("Set preferred network type failed.");
-                    }
-                    break;
                 case EVENT_QUERY_SMSC_DONE:
                     ar = (AsyncResult) msg.obj;
                     if (ar.exception != null) {
@@ -465,12 +451,12 @@
 
         mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
                 new LinkedBlockingDeque<Runnable>());
-        mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
         mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
         mPhone = PhoneFactory.getDefaultPhone();
+        mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
+                .createForSubscriptionId(mPhone.getSubId());
 
-        mImsManager = ImsManager.getInstance(getApplicationContext(),
-                SubscriptionManager.getDefaultVoicePhoneId());
+        mImsManager = ImsManager.getInstance(getApplicationContext(), mPhone.getPhoneId());
 
         sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager);
 
@@ -489,7 +475,6 @@
         mDBm = (TextView) findViewById(R.id.dbm);
         mMwi = (TextView) findViewById(R.id.mwi);
         mCfi = (TextView) findViewById(R.id.cfi);
-        mLocation = (TextView) findViewById(R.id.location);
         mCellInfo = (TextView) findViewById(R.id.cellinfo);
         mCellInfo.setTypeface(Typeface.MONOSPACE);
 
@@ -500,9 +485,28 @@
         mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
         mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
         mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
-
+        mEndcAvailable = (TextView) findViewById(R.id.endc_available);
+        mDcnrRestricted = (TextView) findViewById(R.id.dcnr_restricted);
+        mNrAvailable = (TextView) findViewById(R.id.nr_available);
+        mNrState = (TextView) findViewById(R.id.nr_state);
+        mNrFrequency = (TextView) findViewById(R.id.nr_frequency);
         mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
 
+        // hide 5G stats on devices that don't support 5G
+        if ((mTelephonyManager.getSupportedRadioAccessFamily()
+                & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+            ((TextView) findViewById(R.id.endc_available_label)).setVisibility(View.GONE);
+            mEndcAvailable.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(View.GONE);
+            mDcnrRestricted.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_available_label)).setVisibility(View.GONE);
+            mNrAvailable.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_state_label)).setVisibility(View.GONE);
+            mNrState.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(View.GONE);
+            mNrFrequency.setVisibility(View.GONE);
+        }
+
         mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
         ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS);
@@ -588,9 +592,11 @@
         mPreferredNetworkTypeResult = PREFERRED_NETWORK_LABELS.length - 1; //Unknown
         mSelectedPhoneIndex = 0; //phone 0
 
-        //FIXME: Replace with TelephonyManager call
-        mPhone.getPreferredNetworkType(
-                mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
+        new Thread(() -> {
+            int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
+            updatePreferredNetworkType(
+                    RadioAccessFamily.getNetworkTypeFromRaf(networkType));
+        }).start();
 
         restoreFromBundle(icicle);
     }
@@ -624,8 +630,8 @@
         updateProperties();
         updateDnsCheckState();
         updateNetworkType();
+        updateNrStats(null);
 
-        updateLocation(mCellLocationResult);
         updateCellInfo(mCellInfoResult);
         updateSubscriptionIds();
 
@@ -636,6 +642,8 @@
         mCellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler);
         //set selection after registering listener to force update
         mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
+        // Request cell information update from RIL.
+        mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex]);
 
         //set selection before registering to prevent update
         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
@@ -673,7 +681,7 @@
 
         log("onPause: unregister phone & data intents");
 
-        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        mTelephonyManager.unregisterPhoneStateListener(mPhoneStateListener);
         mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
 
@@ -774,7 +782,7 @@
     }
 
     private void unregisterPhoneStateListener() {
-        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        mTelephonyManager.unregisterPhoneStateListener(mPhoneStateListener);
         mPhone.unregisterForPhysicalChannelConfig(mHandler);
 
         // clear all fields so they are blank until the next listener event occurs
@@ -785,7 +793,6 @@
         mSent.setText("");
         mReceived.setText("");
         mCallState.setText("");
-        mLocation.setText("");
         mMwiValue = false;
         mMwi.setText("");
         mCfiValue = false;
@@ -800,18 +807,8 @@
     // register mPhoneStateListener for relevant fields using the current TelephonyManager
     private void registerPhoneStateListener() {
         mPhoneStateListener = new RadioInfoPhoneStateListener();
-        mTelephonyManager.listen(mPhoneStateListener,
-                  PhoneStateListener.LISTEN_CALL_STATE
-        //b/27803938 - RadioInfo currently cannot read PRECISE_CALL_STATE
-        //      | PhoneStateListener.LISTEN_PRECISE_CALL_STATE
-                | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                | PhoneStateListener.LISTEN_DATA_ACTIVITY
-                | PhoneStateListener.LISTEN_CELL_LOCATION
-                | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
-                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
-                | PhoneStateListener.LISTEN_CELL_INFO
-                | PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+        mTelephonyManager.registerPhoneStateListener(new HandlerExecutor(mHandler),
+                mPhoneStateListener);
     }
 
     private void updateDnsCheckState() {
@@ -843,45 +840,6 @@
                 + r.getString(R.string.radioInfo_display_asu));
     }
 
-    private void updateLocation(CellLocation location) {
-        Resources r = getResources();
-        if (location instanceof GsmCellLocation) {
-            GsmCellLocation loc = (GsmCellLocation) location;
-            int lac = loc.getLac();
-            int cid = loc.getCid();
-            mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
-                    + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
-                    + "   "
-                    + r.getString(R.string.radioInfo_cid) + " = "
-                    + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
-        } else if (location instanceof CdmaCellLocation) {
-            CdmaCellLocation loc = (CdmaCellLocation) location;
-            int bid = loc.getBaseStationId();
-            int sid = loc.getSystemId();
-            int nid = loc.getNetworkId();
-            int lat = loc.getBaseStationLatitude();
-            int lon = loc.getBaseStationLongitude();
-            mLocation.setText("BID = "
-                    + ((bid == -1) ? "unknown" : Integer.toHexString(bid))
-                    + "   "
-                    + "SID = "
-                    + ((sid == -1) ? "unknown" : Integer.toHexString(sid))
-                    + "   "
-                    + "NID = "
-                    + ((nid == -1) ? "unknown" : Integer.toHexString(nid))
-                    + "\n"
-                    + "LAT = "
-                    + ((lat == -1) ? "unknown" : Integer.toHexString(lat))
-                    + "   "
-                    + "LONG = "
-                    + ((lon == -1) ? "unknown" : Integer.toHexString(lon)));
-        } else {
-            mLocation.setText("unknown");
-        }
-
-
-    }
-
     private String getCellInfoDisplayString(int i) {
         return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
     }
@@ -1131,6 +1089,32 @@
         }
     }
 
+    private void updateNrStats(ServiceState serviceState) {
+        if ((mTelephonyManager.getSupportedRadioAccessFamily()
+                & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+            return;
+        }
+
+        ServiceState ss = serviceState;
+        if (ss == null && mPhone != null) {
+            ss = mPhone.getServiceState();
+        }
+        if (ss != null) {
+            NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+            if (nri != null) {
+                DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
+                if (dsri != null) {
+                    mEndcAvailable.setText(dsri.isEnDcAvailable ? "True" : "False");
+                    mDcnrRestricted.setText(dsri.isDcNrRestricted ? "True" : "False");
+                    mNrAvailable.setText(dsri.isNrAvailable ? "True" : "False");
+                }
+            }
+            mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
+            mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+        }
+    }
+
     private void updateProperties() {
         String s;
         Resources r = getResources();
@@ -1231,11 +1215,9 @@
     private void updateAllCellInfo() {
 
         mCellInfo.setText("");
-        mLocation.setText("");
 
         final Runnable updateAllCellInfoResults = new Runnable() {
             public void run() {
-                updateLocation(mCellLocationResult);
                 updateCellInfo(mCellInfoResult);
             }
         };
@@ -1244,7 +1226,6 @@
             @Override
             public void run() {
                 mCellInfoResult = mTelephonyManager.getAllCellInfo();
-                mCellLocationResult = mTelephonyManager.getCellLocation();
 
                 mHandler.post(updateAllCellInfoResults);
             }
@@ -1465,9 +1446,9 @@
     };
 
     private boolean isImsVolteProvisioned() {
-        if (mPhone != null && mImsManager != null) {
-            return mImsManager.isVolteEnabledByPlatform(mPhone.getContext())
-                && mImsManager.isVolteProvisionedOnDevice(mPhone.getContext());
+        if (mImsManager != null) {
+            return mImsManager.isVolteEnabledByPlatform()
+                && mImsManager.isVolteProvisionedOnDevice();
         }
         return false;
     }
@@ -1480,9 +1461,9 @@
     };
 
     private boolean isImsVtProvisioned() {
-        if (mPhone != null && mImsManager != null) {
-            return mImsManager.isVtEnabledByPlatform(mPhone.getContext())
-                && mImsManager.isVtProvisionedOnDevice(mPhone.getContext());
+        if (mImsManager != null) {
+            return mImsManager.isVtEnabledByPlatform()
+                && mImsManager.isVtProvisionedOnDevice();
         }
         return false;
     }
@@ -1495,9 +1476,9 @@
     };
 
     private boolean isImsWfcProvisioned() {
-        if (mPhone != null && mImsManager != null) {
-            return mImsManager.isWfcEnabledByPlatform(mPhone.getContext())
-                && mImsManager.isWfcProvisionedOnDevice(mPhone.getContext());
+        if (mImsManager != null) {
+            return mImsManager.isWfcEnabledByPlatform()
+                && mImsManager.isWfcProvisionedOnDevice();
         }
         return false;
     }
@@ -1539,13 +1520,16 @@
         return provisioned;
     }
 
-    private static boolean isEabEnabledByPlatform(Context context) {
-        if (context != null) {
+    private boolean isEabEnabledByPlatform() {
+        if (mPhone != null) {
             CarrierConfigManager configManager = (CarrierConfigManager)
-                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-            if (configManager != null && configManager.getConfig().getBoolean(
-                        CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)) {
-                return true;
+                    mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
+            if (b != null) {
+                return b.getBoolean(
+                        CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false) || b.getBoolean(
+                        CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL,
+                        false);
             }
         }
         return false;
@@ -1562,25 +1546,25 @@
         mImsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
         mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD
-                && mImsManager.isVolteEnabledByPlatform(mPhone.getContext()));
+                && mImsManager.isVolteEnabledByPlatform());
 
         mImsVtProvisionedSwitch.setOnCheckedChangeListener(null);
         mImsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
         mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
         mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD
-                && mImsManager.isVtEnabledByPlatform(mPhone.getContext()));
+                && mImsManager.isVtEnabledByPlatform());
 
         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
         mImsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
         mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD
-                && mImsManager.isWfcEnabledByPlatform(mPhone.getContext()));
+                && mImsManager.isWfcEnabledByPlatform());
 
         mEabProvisionedSwitch.setOnCheckedChangeListener(null);
         mEabProvisionedSwitch.setChecked(isEabProvisioned());
         mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
         mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD
-                && isEabEnabledByPlatform(mPhone.getContext()));
+                && isEabEnabledByPlatform());
     }
 
     OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
@@ -1655,21 +1639,11 @@
             if (mPreferredNetworkTypeResult != pos && pos >= 0
                     && pos <= PREFERRED_NETWORK_LABELS.length - 2) {
                 mPreferredNetworkTypeResult = pos;
-
-                // TODO: Possibly migrate this to TelephonyManager.setPreferredNetworkType()
-                // which today still has some issues (mostly that the "set" is conditional
-                // on a successful modem call, which is not what we want). Instead we always
-                // want this setting to be set, so that if the radio hiccups and this setting
-                // is for some reason unsuccessful, future calls to the radio will reflect
-                // the users's preference which is set here.
-                final int subId = mPhone.getSubId();
-                if (SubscriptionManager.isUsableSubIdValue(subId)) {
-                    Settings.Global.putInt(mPhone.getContext().getContentResolver(),
-                            PREFERRED_NETWORK_MODE + subId, mPreferredNetworkTypeResult);
-                }
-                log("Calling setPreferredNetworkType(" + mPreferredNetworkTypeResult + ")");
-                Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
-                mPhone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg);
+                new Thread(() -> {
+                    mTelephonyManager.setAllowedNetworkTypesForReason(
+                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
+                            RadioAccessFamily.getRafFromNetworkType(mPreferredNetworkTypeResult));
+                }).start();
             }
         }
 
diff --git a/src/com/android/phone/settings/SuppServicesUiUtil.java b/src/com/android/phone/settings/SuppServicesUiUtil.java
index 4e9841f..4f1a79f 100644
--- a/src/com/android/phone/settings/SuppServicesUiUtil.java
+++ b/src/com/android/phone/settings/SuppServicesUiUtil.java
@@ -84,7 +84,7 @@
                 .create();
     }
 
-    private static String makeMessage(Context context, String preferenceKey, Phone phone) {
+    public static String makeMessage(Context context, String preferenceKey, Phone phone) {
         String message = "";
         int simSlot = (phone.getPhoneId() == 0) ? 1 : 2;
         String suppServiceName = getSuppServiceName(context, preferenceKey);
diff --git a/src/com/android/phone/settings/VoicemailSettingsActivity.java b/src/com/android/phone/settings/VoicemailSettingsActivity.java
index 66b1af9..2bd5306 100644
--- a/src/com/android/phone/settings/VoicemailSettingsActivity.java
+++ b/src/com/android/phone/settings/VoicemailSettingsActivity.java
@@ -238,6 +238,10 @@
 
         mVoicemailNotificationPreference =
                 findPreference(getString(R.string.voicemail_notifications_key));
+        if (mSubMenuVoicemailSettings == null) {
+            mSubMenuVoicemailSettings =
+                    (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
+        }
         final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
         intent.putExtra(Settings.EXTRA_CHANNEL_ID,
                 NotificationChannelController.CHANNEL_ID_VOICE_MAIL);
@@ -250,12 +254,6 @@
         super.onResume();
         mForeground = true;
 
-        PreferenceScreen prefSet = getPreferenceScreen();
-
-        if (mSubMenuVoicemailSettings == null) {
-            mSubMenuVoicemailSettings =
-                    (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
-        }
         if (mSubMenuVoicemailSettings != null) {
             mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
             mSubMenuVoicemailSettings.setDialogOnClosedListener(this);
diff --git a/src/com/android/phone/settings/fdn/DeleteFdnContactScreen.java b/src/com/android/phone/settings/fdn/DeleteFdnContactScreen.java
index 92baa97..8b17cfb 100644
--- a/src/com/android/phone/settings/fdn/DeleteFdnContactScreen.java
+++ b/src/com/android/phone/settings/fdn/DeleteFdnContactScreen.java
@@ -64,7 +64,8 @@
 
         resolveIntent();
 
-        authenticatePin2();
+        // Starts PIN2 authentication only for the first time.
+        if (icicle == null) authenticatePin2();
 
         getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
         setContentView(R.layout.delete_fdn_contact_screen);
diff --git a/src/com/android/phone/vvm/VvmSimStateTracker.java b/src/com/android/phone/vvm/VvmSimStateTracker.java
index c648d9c..d26ef6c 100644
--- a/src/com/android/phone/vvm/VvmSimStateTracker.java
+++ b/src/com/android/phone/vvm/VvmSimStateTracker.java
@@ -20,6 +20,9 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.os.SystemProperties;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -68,7 +71,8 @@
      * Waits for the account to become {@link ServiceState#STATE_IN_SERVICE} and notify the
      * connected event. Will unregister itself once the event has been triggered.
      */
-    private class ServiceStateListener extends PhoneStateListener {
+    private class ServiceStateListener extends PhoneStateListener
+            implements PhoneStateListener.ServiceStateChangedListener  {
 
         private final PhoneAccountHandle mPhoneAccountHandle;
         private final Context mContext;
@@ -84,7 +88,8 @@
                 VvmLog.e(TAG, "Cannot create TelephonyManager from " + mPhoneAccountHandle);
                 return;
             }
-            telephonyManager.listen(this, PhoneStateListener.LISTEN_SERVICE_STATE);
+            telephonyManager.registerPhoneStateListener(
+                    new HandlerExecutor(new Handler(Looper.getMainLooper())), this);
         }
 
         public void unlisten() {
@@ -92,7 +97,7 @@
             // PhoneStateListener, and mPhoneAccountHandle might be invalid at this point
             // (e.g. SIM removal)
             mContext.getSystemService(TelephonyManager.class)
-                    .listen(this, PhoneStateListener.LISTEN_NONE);
+                    .unregisterPhoneStateListener(this);
             sListeners.put(mPhoneAccountHandle, null);
         }
 
diff --git a/src/com/android/services/telephony/CallQualityManager.java b/src/com/android/services/telephony/CallQualityManager.java
new file mode 100644
index 0000000..01b5bae
--- /dev/null
+++ b/src/com/android/services/telephony/CallQualityManager.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.telecom.BluetoothCallQualityReport;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.R;
+
+/**
+ * class to handle call quality events that are received by telecom and telephony
+ */
+public class CallQualityManager {
+    private static final String TAG = CallQualityManager.class.getCanonicalName();
+    private static final String CALL_QUALITY_REPORT_CHANNEL = "call_quality_report_channel";
+
+    /** notification ids */
+    public static final int BLUETOOTH_CHOPPY_VOICE_NOTIFICATION_ID = 700;
+
+    public static final String CALL_QUALITY_CHANNEL_ID = "CallQualityNotification";
+
+    private final Context mContext;
+    private final NotificationChannel mNotificationChannel;
+    private final NotificationManager mNotificationManager;
+
+    public CallQualityManager(Context context) {
+        mContext = context;
+        mNotificationChannel = new NotificationChannel(CALL_QUALITY_CHANNEL_ID,
+                mContext.getString(R.string.call_quality_notification_name),
+                NotificationManager.IMPORTANCE_HIGH);
+        mNotificationManager = (NotificationManager)
+                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mNotificationManager.createNotificationChannel(mNotificationChannel);
+    }
+
+    /**
+     * method that is called whenever a
+     * {@code BluetoothCallQualityReport.EVENT_SEND_BLUETOOTH_CALL_QUALITY_REPORT} is received
+     * @param extras Bundle that includes serialized {@code BluetoothCallQualityReport} parcelable
+     */
+    @VisibleForTesting
+    public void onBluetoothCallQualityReported(Bundle extras) {
+        if (extras == null) {
+            Log.d(TAG, "onBluetoothCallQualityReported: no extras provided");
+        }
+
+        BluetoothCallQualityReport callQualityReport = extras.getParcelable(
+                BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT);
+
+        if (callQualityReport.isChoppyVoice()) {
+            onChoppyVoice();
+        }
+        // TODO: once other signals are also sent, we will add more actions here
+    }
+
+    /**
+     * method to post a notification to user suggesting ways to improve call quality in case of
+     * bluetooth choppy voice
+     */
+    @VisibleForTesting
+    public void onChoppyVoice() {
+        String title = "Call Quality Improvement";
+        //TODO: update call_quality_bluetooth_enhancement_suggestion with below before submitting:
+//        "Voice is not being transmitted properly via your bluetooth device."
+//                + "To improve, try:\n"
+//                + "1. moving your phone closer to your bluetooth device\n"
+//                + "2. using a different bluetooth device, or your phone's speaker\n";
+        popUpNotification(title,
+                mContext.getText(R.string.call_quality_notification_bluetooth_details));
+    }
+
+    private void popUpNotification(String title, CharSequence details) {
+        int iconId = android.R.drawable.stat_notify_error;
+
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(iconId)
+                .setWhen(System.currentTimeMillis())
+                .setAutoCancel(true)
+                .setContentTitle(title)
+                .setContentText(details)
+                .setStyle(new Notification.BigTextStyle().bigText(details))
+                .setOngoing(true)
+                .setChannelId(CALL_QUALITY_CHANNEL_ID)
+                .setOnlyAlertOnce(true)
+                .build();
+
+        mNotificationManager.notify(TAG, BLUETOOTH_CHOPPY_VOICE_NOTIFICATION_ID, notification);
+    }
+}
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index 90e7663..c7b324d 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -16,11 +16,12 @@
 
 package com.android.services.telephony;
 
+import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
 import android.provider.Settings;
 import android.telephony.DisconnectCause;
-import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
@@ -284,8 +285,14 @@
 
     private boolean isEmergency() {
         Phone phone = getPhone();
-        return phone != null && getAddress() != null && PhoneNumberUtils.isLocalEmergencyNumber(
-                phone.getContext(), getAddress().getSchemeSpecificPart());
+        if (phone != null && getAddress() != null) {
+            TelephonyManager tm = (TelephonyManager) phone.getContext()
+                    .getSystemService(Context.TELEPHONY_SERVICE);
+            if (tm != null) {
+                return tm.isEmergencyNumber(getAddress().getSchemeSpecificPart());
+            }
+        }
+        return false;
     }
 
     /**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 816348a..c9f762b 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -16,6 +16,7 @@
 
 package com.android.services.telephony;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -28,6 +29,7 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
 import android.util.Pair;
 
 import com.android.ims.internal.ConferenceParticipant;
@@ -268,7 +270,7 @@
 
                 @Override
                 public void onExtrasChanged(Connection c, Bundle extras) {
-                    Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
+                    Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + Rlog.pii(LOG_TAG, extras));
                     updateExtras(extras);
                 }
 
@@ -438,6 +440,7 @@
 
         mTelephonyConnectionService = telephonyConnectionService;
         setConferenceHost(conferenceHost);
+        setVideoProvider(conferenceHost, conferenceHost.getVideoProvider());
 
         int capabilities = Connection.CAPABILITY_MUTE |
                 Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
@@ -864,6 +867,16 @@
 
             mConferenceHostAddress = new Uri[hostAddresses.size()];
             mConferenceHostAddress = hostAddresses.toArray(mConferenceHostAddress);
+            Log.i(this, "setConferenceHost: temp log hosts are "
+                    + Arrays.stream(mConferenceHostAddress)
+                    .map(Uri::toString)
+                    .collect(Collectors.joining(", ")));
+
+            Log.i(this, "setConferenceHost: hosts are "
+                    + Arrays.stream(mConferenceHostAddress)
+                    .map(Uri::getSchemeSpecificPart)
+                    .map(ssp -> Rlog.pii(LOG_TAG, ssp))
+                    .collect(Collectors.joining(", ")));
 
             Log.i(this, "setConferenceHost: hosts are "
                     + Arrays.stream(mConferenceHostAddress)
@@ -1258,58 +1271,79 @@
     }
 
     /**
+     * Extracts a phone number from a {@link Uri}.
+     * <p>
+     * Phone numbers can be represented either as a TEL URI or a SIP URI.
+     * For conference event packages, RFC3261 specifies how participants can be identified using a
+     * SIP URI.
+     * A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
+     * Per RFC3261, the "user" can be a telephone number.
+     * For example: sip:1650555121;phone-context=blah.com@host.com
+     * In this case, the phone number is in the user field of the URI, and the parameters can be
+     * ignored.
+     *
+     * A SIP URI can also specify a phone number in a format similar to:
+     * sip:+1-212-555-1212@something.com;user=phone
+     * In this case, the phone number is again in user field and the parameters can be ignored.
+     * We can get the user field in these instances by splitting the string on the @, ;, or :
+     * and looking at the first found item.
+     * @param handle The URI containing a SIP or TEL formatted phone number.
+     * @return extracted phone number.
+     */
+    private static @NonNull String extractPhoneNumber(@NonNull Uri handle) {
+        // Number is always in the scheme specific part, regardless of whether this is a TEL or SIP
+        // URI.
+        String number = handle.getSchemeSpecificPart();
+        // Get anything before the @ for the SIP case.
+        String[] numberParts = number.split("[@;:]");
+
+        if (numberParts.length == 0) {
+            Log.v(LOG_TAG, "extractPhoneNumber(N) : no number in handle");
+            return "";
+        }
+        return numberParts[0];
+    }
+
+    /**
      * Determines if the passed in participant handle is the same as the conference host's handle.
      * Starts with a simple equality check.  However, the handles from a conference event package
      * will be a SIP uri, so we need to pull that apart to look for the participant's phone number.
      *
-     * @param hostHandles The handle(s) of the connection hosting the conference.
+     * @param hostHandles The handle(s) of the connection hosting the conference, typically obtained
+     *                    from P-Associated-Uri entries.
      * @param handle The handle of the conference participant.
      * @return {@code true} if the host's handle matches the participant's handle, {@code false}
      *      otherwise.
      */
-    private boolean isParticipantHost(Uri[] hostHandles, Uri handle) {
+    @VisibleForTesting
+    public static boolean isParticipantHost(Uri[] hostHandles, Uri handle) {
         // If there is no host handle or no participant handle, bail early.
         if (hostHandles == null || hostHandles.length == 0 || handle == null) {
-            Log.v(this, "isParticipantHost(N) : host or participant uri null");
+            Log.v(LOG_TAG, "isParticipantHost(N) : host or participant uri null");
             return false;
         }
 
-        // Conference event package participants are identified using SIP URIs (see RFC3261).
-        // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
-        // Per RFC3261, the "user" can be a telephone number.
-        // For example: sip:1650555121;phone-context=blah.com@host.com
-        // In this case, the phone number is in the user field of the URI, and the parameters can be
-        // ignored.
-        //
-        // A SIP URI can also specify a phone number in a format similar to:
-        // sip:+1-212-555-1212@something.com;user=phone
-        // In this case, the phone number is again in user field and the parameters can be ignored.
-        // We can get the user field in these instances by splitting the string on the @, ;, or :
-        // and looking at the first found item.
-
-        String number = handle.getSchemeSpecificPart();
-        String numberParts[] = number.split("[@;:]");
-
-        if (numberParts.length == 0) {
-            Log.v(this, "isParticipantHost(N) : no number in participant handle");
+        String number = extractPhoneNumber(handle);
+        // If we couldn't extract the participant's number, then we can't determine if it is the
+        // host or not.
+        if (TextUtils.isEmpty(number)) {
             return false;
         }
-        number = numberParts[0];
 
         for (Uri hostHandle : hostHandles) {
             if (hostHandle == null) {
                 continue;
             }
-            // The host number will be a tel: uri.  Per RFC3966, the part after tel: is the phone
-            // number.
-            String hostNumber = hostHandle.getSchemeSpecificPart();
+            // Similar to the CEP participant data, the host identity in the P-Associated-Uri could
+            // be a SIP URI or a TEL URI.
+            String hostNumber = extractPhoneNumber(hostHandle);
 
             // Use a loose comparison of the phone numbers.  This ensures that numbers that differ
             // by special characters are counted as equal.
             // E.g. +16505551212 would be the same as 16505551212
             boolean isHost = PhoneNumberUtils.compare(hostNumber, number);
 
-            Log.v(this, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
+            Log.v(LOG_TAG, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
                     Rlog.pii(LOG_TAG, hostNumber), Rlog.pii(LOG_TAG, number));
 
             if (isHost) {
@@ -1359,9 +1393,12 @@
             }
 
             if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
-                Log.i(this,"handleOriginalConnectionChange : SRVCC to GSM");
                 GsmConnection c = new GsmConnection(originalConnection, getTelecomCallId(),
                         mConferenceHost.getCallDirection());
+                Log.i(this, "handleOriginalConnectionChange : SRVCC to GSM."
+                        + " Created new GsmConnection with objId=" + System.identityHashCode(c)
+                        + " and originalConnection objId="
+                        + System.identityHashCode(originalConnection));
                 // This is a newly created conference connection as a result of SRVCC
                 c.setConferenceSupported(true);
                 c.setTelephonyConnectionProperties(
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 6d3d4c2..7cf9415 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -403,6 +403,20 @@
         conferenceHostConnection.setVideoPauseSupported(connection.getVideoPauseSupported());
         conferenceHostConnection.setManageImsConferenceCallSupported(
                 connection.isManageImsConferenceCallSupported());
+        // WARNING: do not try to copy the video provider from connection to
+        // conferenceHostConnection here.  In connection.cloneConnection, part of the clone
+        // process is to set the original connection so it's already set:
+        // conferenceHostConnection.setVideoProvider(connection.getVideoProvider());
+        // There is a subtle concurrency issue here where at the time of merge, the
+        // TelephonyConnection potentially has the WRONG video provider set on it (compared to
+        // the ImsPhoneConnection (ie original connection) which has the correct one.
+        // If you follow the logic in ImsPhoneCallTracker#onCallMerged through, what happens is the
+        // new post-merge video provider is set on the ImsPhoneConnection.  That informs it's
+        // listeners (e.g. TelephonyConnection) via a handler.  We immediately change the multiparty
+        // start of the host connection and ImsPhoneCallTracker starts the setup we are
+        // performing here.  When cloning TelephonyConnection, we get the right VideoProvider
+        // because it is copied from the originalConnection, not using the potentially stale value
+        // in the TelephonyConnection.
 
         PhoneAccountHandle phoneAccountHandle = null;
 
diff --git a/src/com/android/services/telephony/MmiCodeUtil.java b/src/com/android/services/telephony/MmiCodeUtil.java
new file mode 100644
index 0000000..d208ec3
--- /dev/null
+++ b/src/com/android/services/telephony/MmiCodeUtil.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class MmiCodeUtil {
+    //***** Constants
+
+    // Supp Service codes from TS 22.030 Annex B
+
+    //Called line presentation
+    static final String SC_CLIP    = "30";
+    static final String SC_CLIR    = "31";
+
+    // Call Forwarding
+    static final String SC_CFU     = "21";
+    static final String SC_CFB     = "67";
+    static final String SC_CFNRy   = "61";
+    static final String SC_CFNR    = "62";
+
+    static final String SC_CF_All = "002";
+    static final String SC_CF_All_Conditional = "004";
+
+    // Call Waiting
+    static final String SC_WAIT     = "43";
+
+    // Call Barring
+    static final String SC_BAOC         = "33";
+    static final String SC_BAOIC        = "331";
+    static final String SC_BAOICxH      = "332";
+    static final String SC_BAIC         = "35";
+    static final String SC_BAICr        = "351";
+
+    static final String SC_BA_ALL       = "330";
+    static final String SC_BA_MO        = "333";
+    static final String SC_BA_MT        = "353";
+
+    // Supp Service Password registration
+    static final String SC_PWD          = "03";
+
+    // PIN/PIN2/PUK/PUK2
+    static final String SC_PIN          = "04";
+    static final String SC_PIN2         = "042";
+    static final String SC_PUK          = "05";
+    static final String SC_PUK2         = "052";
+
+    // See TS 22.030 6.5.2 "Structure of the MMI"
+
+    static Pattern sPatternSuppService = Pattern.compile(
+        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
+/*       1  2                    3          4  5       6   7         8    9     10  11             12
+
+         1 = Full string up to and including #
+         2 = action (activation/interrogation/registration/erasure)
+         3 = service code
+         5 = SIA
+         7 = SIB
+         9 = SIC
+         10 = dialing number
+*/
+
+    static final int MATCH_GROUP_SERVICE_CODE = 3;
+
+    public static final String BUTTON_CLIR_KEY  = "button_clir_key";
+    public static final String BUTTON_CW_KEY    = "button_cw_key";
+    public static final String CALL_FORWARDING_KEY = "call_forwarding_key";
+    public static final String CALL_BARRING_KEY = "call_barring_key";
+
+    //***** Public Class methods
+    public static String getMmiServiceCode(String dialString) {
+        Matcher m;
+        String ret = null;
+
+        m = sPatternSuppService.matcher(dialString);
+
+        if (m.matches()) {
+            ret = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
+        }
+
+        return ret;
+    }
+
+    private static String makeEmptyNull(String s) {
+        if (s != null && s.length() == 0) return null;
+
+        return s;
+    }
+
+    static boolean isServiceCodeCallForwarding(String sc) {
+        return sc != null &&
+                (sc.equals(SC_CFU)
+                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
+                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
+                || sc.equals(SC_CF_All_Conditional));
+    }
+
+    static boolean isServiceCodeCallBarring(String sc) {
+        return sc != null &&
+            (sc.equals(SC_BAOC)
+             || sc.equals(SC_BAOIC) || sc.equals(SC_BAOICxH)
+             || sc.equals(SC_BAIC) || sc.equals(SC_BAICr)
+             || sc.equals(SC_BA_ALL) || sc.equals(SC_BA_MO)
+             || sc.equals(SC_BA_MT));
+    }
+
+    static boolean isPinPukCommand(String sc) {
+        return sc != null && (sc.equals(SC_PIN) || sc.equals(SC_PIN2)
+                              || sc.equals(SC_PUK) || sc.equals(SC_PUK2));
+     }
+
+    public static String getSuppServiceKey(String dialString) {
+        String sc = getMmiServiceCode(dialString);
+        if (sc != null && sc.equals(SC_CLIP)) {
+            return "";
+        } else if (sc != null && sc.equals(SC_CLIR)) {
+            return BUTTON_CLIR_KEY;
+        } else if (isServiceCodeCallForwarding(sc)) {
+            return CALL_FORWARDING_KEY;
+        } else if (isServiceCodeCallBarring(sc)) {
+            return CALL_BARRING_KEY;
+        } else if (sc != null && sc.equals(SC_PWD)) {
+            return "";
+        } else if (sc != null && sc.equals(SC_WAIT)) {
+            return BUTTON_CW_KEY;
+        } else if (isPinPukCommand(sc)) {
+            return "";
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 1c1725f..235cbce 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -25,8 +25,10 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.ims.ImsCallProfile;
 import android.text.TextUtils;
 
+import com.android.ims.ImsCall;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
@@ -39,6 +41,7 @@
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.phone.NumberVerificationManager;
 import com.android.phone.PhoneUtils;
+import com.android.phone.callcomposer.CallComposerPictureManager;
 import com.android.telephony.Rlog;
 
 import java.util.List;
@@ -65,6 +68,12 @@
      */
     private static final int MAX_NUMBER_VERIFICATION_HANGUP_DELAY_MILLIS = 10000;
 
+    /**
+     * Hardcoded extra for a call that's used to provide metrics information to the dialer app.
+     */
+    private static final String EXTRA_CALL_CREATED_TIME_MILLIS =
+            "android.telecom.extra.CALL_CREATED_TIME_MILLIS";
+
     /** The phone object to listen to. */
     private final Phone mPhone;
 
@@ -216,6 +225,9 @@
             Call call = connection.getCall();
             if (call != null && call.getState().isAlive()) {
                 addNewUnknownCall(connection);
+            } else {
+                Log.i(this, "Skipping new unknown connection because its call is null or dead."
+                        + " connection=" + connection);
             }
         }
     }
@@ -242,8 +254,7 @@
             }
 
             // Specifies the time the call was added. This is used by the dialer for analytics.
-            extras.putLong(TelecomManager.EXTRA_CALL_CREATED_TIME_MILLIS,
-                    SystemClock.elapsedRealtime());
+            extras.putLong(EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
 
             PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
             if (handle == null) {
@@ -273,8 +284,7 @@
         }
 
         // Specifies the time the call was added. This is used by the dialer for analytics.
-        extras.putLong(TelecomManager.EXTRA_CALL_CREATED_TIME_MILLIS,
-                SystemClock.elapsedRealtime());
+        extras.putLong(EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
 
         if (connection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
             if (((ImsPhoneConnection) connection).isRttEnabledForCall()) {
@@ -282,7 +292,28 @@
             }
             if (((ImsPhoneConnection) connection).isIncomingCallAutoRejected()) {
                 extras.putString(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE,
-                        "Call Dropped by lower layers");
+                        TelecomManager.CALL_AUTO_DISCONNECT_MESSAGE_STRING);
+            }
+            ImsCall imsCall = ((ImsPhoneConnection) connection).getImsCall();
+            if (imsCall != null) {
+                ImsCallProfile imsCallProfile = imsCall.getCallProfile();
+                if (imsCallProfile != null) {
+                    if (CallComposerPictureManager.sTestMode) {
+                        imsCallProfile.setCallExtra(ImsCallProfile.EXTRA_PICTURE_URL,
+                                CallComposerPictureManager.FAKE_SERVER_URL);
+                    }
+
+                    extras.putInt(TelecomManager.EXTRA_PRIORITY,
+                            imsCallProfile.getCallExtraInt(ImsCallProfile.EXTRA_PRIORITY));
+                    extras.putString(TelecomManager.EXTRA_CALL_SUBJECT,
+                            imsCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_SUBJECT));
+                    extras.putParcelable(TelecomManager.EXTRA_LOCATION,
+                            imsCallProfile.getCallExtraParcelable(ImsCallProfile.EXTRA_LOCATION));
+                    if (!TextUtils.isEmpty(
+                            imsCallProfile.getCallExtra(ImsCallProfile.EXTRA_PICTURE_URL))) {
+                        extras.putBoolean(TelecomManager.EXTRA_HAS_PICTURE, true);
+                    }
+                }
             }
         }
 
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 3b8f4fd..4846d44 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.PersistableBundle;
@@ -106,6 +107,15 @@
      */
     private static final int LISTENER_STATE_REGISTERED = 3;
 
+    /**
+     * Copy-pasted from android.telecom.PhoneAccount -- hidden constant which is unfortunately being
+     * used by some 1P apps, so we're keeping it here until we can remove it.
+     */
+    private static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK =
+            "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
+
+    private Handler mHandler;
+
     final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
         private final Phone mPhone;
         private PhoneAccount mAccount;
@@ -113,13 +123,14 @@
         private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
         private boolean mIsEmergency;
         private boolean mIsRttCapable;
+        private boolean mIsCallComposerCapable;
         private boolean mIsAdhocConfCapable;
         private boolean mIsEmergencyPreferred;
         private MmTelFeature.MmTelCapabilities mMmTelCapabilities;
         private ImsMmTelManager.CapabilityCallback mMmtelCapabilityCallback;
         private RegistrationManager.RegistrationCallback mImsRegistrationCallback;
         private ImsMmTelManager mMmTelManager;
-        private final boolean mIsDummy;
+        private final boolean mIsTestAccount;
         private boolean mIsVideoCapable;
         private boolean mIsVideoPresenceSupported;
         private boolean mIsVideoPauseSupported;
@@ -131,20 +142,20 @@
         private boolean mIsUsingSimCallManager;
         private boolean mIsShowPreciseFailedCause;
 
-        AccountEntry(Phone phone, boolean isEmergency, boolean isDummy) {
+        AccountEntry(Phone phone, boolean isEmergency, boolean isTest) {
             mPhone = phone;
             mIsEmergency = isEmergency;
-            mIsDummy = isDummy;
+            mIsTestAccount = isTest;
             mIsAdhocConfCapable = mPhone.isImsRegistered();
-            mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
+            mAccount = registerPstnPhoneAccount(isEmergency, isTest);
             Log.i(this, "Registered phoneAccount: %s with handle: %s",
                     mAccount, mAccount.getAccountHandle());
             mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone);
             mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone,
                     this);
 
-            if (mIsDummy || isEmergency) {
-                // For dummy and emergency entries, there is no sub ID that can be assigned, so do
+            if (mIsTestAccount || isEmergency) {
+                // For test and emergency entries, there is no sub ID that can be assigned, so do
                 // not register for capabilities callbacks.
                 return;
             }
@@ -166,6 +177,7 @@
                         MmTelFeature.MmTelCapabilities capabilities) {
                     mMmTelCapabilities = capabilities;
                     updateRttCapability();
+                    updateCallComposerCapability(capabilities);
                 }
             };
             registerMmTelCapabilityCallback();
@@ -247,7 +259,7 @@
          * Trigger re-registration of this account.
          */
         public void reRegisterPstnPhoneAccount() {
-            PhoneAccount newAccount = buildPstnPhoneAccount(mIsEmergency, mIsDummy);
+            PhoneAccount newAccount = buildPstnPhoneAccount(mIsEmergency, mIsTestAccount);
             if (!newAccount.equals(mAccount)) {
                 Log.i(this, "reRegisterPstnPhoneAccount: subId: " + getSubId()
                         + " - re-register due to account change.");
@@ -258,8 +270,8 @@
             }
         }
 
-        private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
-            PhoneAccount account = buildPstnPhoneAccount(mIsEmergency, mIsDummy);
+        private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) {
+            PhoneAccount account = buildPstnPhoneAccount(mIsEmergency, mIsTestAccount);
             // Register with Telecom and put into the account entry.
             mTelecomManager.registerPhoneAccount(account);
             return account;
@@ -268,13 +280,13 @@
         /**
          * Registers the specified account with Telecom as a PhoneAccountHandle.
          */
-        private PhoneAccount buildPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
-            String dummyPrefix = isDummyAccount ? "Dummy " : "";
+        private PhoneAccount buildPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) {
+            String testPrefix = isTestAccount ? "Test " : "";
 
             // Build the Phone account handle.
             PhoneAccountHandle phoneAccountHandle =
                     PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
-                            mPhone, dummyPrefix, isEmergency);
+                            mPhone, testPrefix, isEmergency);
 
             // Populate the phone account data.
             int subId = mPhone.getSubId();
@@ -334,8 +346,8 @@
 
                 // The label is user-visible so let's use the display name that the user may
                 // have set in Settings->Sim cards.
-                label = dummyPrefix + subDisplayName;
-                description = dummyPrefix + mContext.getResources().getString(
+                label = testPrefix + subDisplayName;
+                description = testPrefix + mContext.getResources().getString(
                                 R.string.sim_description_default, slotIdString);
             }
 
@@ -360,6 +372,10 @@
                 mIsRttCapable = false;
             }
 
+            if (mIsCallComposerCapable) {
+                capabilities |= PhoneAccount.CAPABILITY_CALL_COMPOSER;
+            }
+
             mIsVideoCapable = mPhone.isVideoEnabled();
             boolean isVideoEnabledByPlatform = ImsManager.getInstance(mPhone.getContext(),
                     mPhone.getPhoneId()).isVtEnabledByPlatform();
@@ -416,13 +432,12 @@
                 extras.putBoolean(PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, true);
             }
 
-            extras.putBoolean(PhoneAccount.EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK,
+            extras.putBoolean(EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK,
                     mContext.getResources()
                             .getBoolean(R.bool.config_support_video_calling_fallback));
 
             if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-                extras.putString(PhoneAccount.EXTRA_SORT_ORDER,
-                    String.valueOf(slotId));
+                extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, slotId);
             }
 
             mIsMergeCallSupported = isCarrierMergeCallSupported();
@@ -574,7 +589,9 @@
             PersistableBundle b =
                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
             boolean carrierConfigEnabled = b != null
-                    && b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL);
+                    && (b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)
+                    || b.getBoolean(
+                    CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL));
             return carrierConfigEnabled && isUserContactDiscoverySettingEnabled();
         }
 
@@ -729,6 +746,15 @@
         }
 
         /**
+         * Determines from carrier config whether to always allow RTT while roaming.
+         */
+        private boolean isCarrierAllowRttWhenRoaming() {
+            PersistableBundle b =
+                    PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+            return b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL);
+        }
+
+        /**
          * Where a device supports instant lettering and call subjects, retrieves the necessary
          * PhoneAccount extras for those features.
          *
@@ -767,7 +793,7 @@
                     // time we get here, the original phone account could have been torn down.
                     return;
                 }
-                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
             }
         }
 
@@ -786,7 +812,7 @@
                     Log.i(this, "updateAdhocConfCapability - changed, new value: "
                             + isAdhocConfCapable);
                     mIsAdhocConfCapable = isAdhocConfCapable;
-                    mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+                    mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
                 }
             }
         }
@@ -805,7 +831,7 @@
                 if (mIsVideoPresenceSupported != isVideoPresenceSupported) {
                     Log.i(this, "updateVideoPresenceCapability for subId=" + mPhone.getSubId()
                             + ", new value= " + isVideoPresenceSupported);
-                    mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+                    mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
                 }
             }
         }
@@ -814,7 +840,18 @@
             boolean isRttEnabled = isRttCurrentlySupported();
             if (isRttEnabled != mIsRttCapable) {
                 Log.i(this, "updateRttCapability - changed, new value: " + isRttEnabled);
-                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
+            }
+        }
+
+        public void updateCallComposerCapability(MmTelFeature.MmTelCapabilities capabilities) {
+            boolean isCallComposerCapable = capabilities.isCapable(
+                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER);
+            if (isCallComposerCapable != mIsCallComposerCapable) {
+                mIsCallComposerCapable = isCallComposerCapable;
+                Log.i(this, "updateCallComposerCapability - changed, new value: "
+                        + isCallComposerCapable);
+                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
             }
         }
 
@@ -823,7 +860,7 @@
                     activeDataSubId);
             if (isEmergencyPreferred != mIsEmergencyPreferred) {
                 Log.i(this, "updateDefaultDataSubId - changed, new value: " + isEmergencyPreferred);
-                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+                mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
             }
         }
 
@@ -847,7 +884,8 @@
                 // Next check whether we're in or near a country that supports it
                 String country =
                         mPhone.getServiceStateTracker().getLocaleTracker()
-                                .getCurrentCountry().toLowerCase();
+                                .getLastKnownCountryIso().toLowerCase();
+
                 String[] supportedCountries = mContext.getResources().getStringArray(
                         R.array.config_simless_emergency_rtt_supported_countries);
                 if (supportedCountries == null || Arrays.stream(supportedCountries).noneMatch(
@@ -856,7 +894,7 @@
                             + " not supported in this country: " + country);
                     return false;
                 }
-                
+
                 return true;
             }
 
@@ -868,11 +906,15 @@
             boolean isRoaming = mTelephonyManager.isNetworkRoaming(mPhone.getSubId());
             boolean isOnWfc = mPhone.getImsRegistrationTech()
                     == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
+            boolean alwaysAllowWhileRoaming = isCarrierAllowRttWhenRoaming();
 
-            boolean shouldDisableBecauseRoamingOffWfc = isRoaming && !isOnWfc;
+            boolean shouldDisableBecauseRoamingOffWfc =
+                    (isRoaming && !isOnWfc) && !alwaysAllowWhileRoaming;
+
             Log.i(this, "isRttCurrentlySupported -- regular acct,"
                     + " hasVoiceAvailability: " + hasVoiceAvailability + "\n"
                     + " isRttSupported: " + isRttSupported + "\n"
+                    + " alwaysAllowWhileRoaming: " + alwaysAllowWhileRoaming + "\n"
                     + " isRoaming: " + isRoaming + "\n"
                     + " isOnWfc: " + isOnWfc + "\n");
 
@@ -965,6 +1007,9 @@
             return mMmTelManager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
                     MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)
                     || mMmTelManager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)
+                    || mMmTelManager.isAvailable(
+                            ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM,
                     MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
         }
     }
@@ -1039,7 +1084,11 @@
         }
     };
 
-    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+    private final PhoneStateListener mPhoneStateListener = new TelecomAccountPhoneStateListener();
+
+    private class TelecomAccountPhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.ActiveDataSubscriptionIdChangedListener,
+            PhoneStateListener.ServiceStateChangedListener {
         @Override
         public void onServiceStateChanged(ServiceState serviceState) {
             int newState = serviceState.getState();
@@ -1065,7 +1114,7 @@
                 }
             }
         }
-    };
+    }
 
     private static TelecomAccountRegistry sInstance;
     private final Context mContext;
@@ -1105,6 +1154,7 @@
         mTelephonyManager = TelephonyManager.from(context);
         mSubscriptionManager = SubscriptionManager.from(context);
         mHandlerThread.start();
+        mHandler = new Handler(Looper.getMainLooper());
         mRegisterSubscriptionListenerBackoff = new ExponentialBackoff(
                 REGISTER_START_DELAY_MS,
                 REGISTER_MAXIMUM_DELAY_MS,
@@ -1127,7 +1177,7 @@
         this.mTelephonyConnectionService = telephonyConnectionService;
     }
 
-    TelephonyConnectionService getTelephonyConnectionService() {
+    public TelephonyConnectionService getTelephonyConnectionService() {
         return mTelephonyConnectionService;
     }
 
@@ -1156,7 +1206,7 @@
      * @param handle The {@link PhoneAccountHandle}.
      * @return {@code True} if merging calls is supported.
      */
-    boolean isMergeCallSupported(PhoneAccountHandle handle) {
+    public boolean isMergeCallSupported(PhoneAccountHandle handle) {
         synchronized (mAccountsLock) {
             for (AccountEntry entry : mAccounts) {
                 if (entry.getPhoneAccountHandle().equals(handle)) {
@@ -1174,7 +1224,7 @@
      * @param handle The {@link PhoneAccountHandle}.
      * @return {@code True} if video conferencing is supported.
      */
-    boolean isVideoConferencingSupported(PhoneAccountHandle handle) {
+    public boolean isVideoConferencingSupported(PhoneAccountHandle handle) {
         synchronized (mAccountsLock) {
             for (AccountEntry entry : mAccounts) {
                 if (entry.getPhoneAccountHandle().equals(handle)) {
@@ -1192,7 +1242,7 @@
      * @param handle The {@link PhoneAccountHandle}.
      * @return {@code True} if merging of wifi calls is allowed when VoWIFI is disabled.
      */
-    boolean isMergeOfWifiCallsAllowedWhenVoWifiOff(final PhoneAccountHandle handle) {
+    public boolean isMergeOfWifiCallsAllowedWhenVoWifiOff(final PhoneAccountHandle handle) {
         synchronized (mAccountsLock) {
             Optional<AccountEntry> result = mAccounts.stream().filter(
                     entry -> entry.getPhoneAccountHandle().equals(handle)).findFirst();
@@ -1212,7 +1262,7 @@
      * @param handle The {@link PhoneAccountHandle}.
      * @return {@code True} if merging IMS calls is supported.
      */
-    boolean isMergeImsCallSupported(PhoneAccountHandle handle) {
+    public boolean isMergeImsCallSupported(PhoneAccountHandle handle) {
         synchronized (mAccountsLock) {
             for (AccountEntry entry : mAccounts) {
                 if (entry.getPhoneAccountHandle().equals(handle)) {
@@ -1332,8 +1382,8 @@
 
         // We also need to listen for changes to the service state (e.g. emergency -> in service)
         // because this could signal a removal or addition of a SIM in a single SIM phone.
-        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+        mTelephonyManager.registerPhoneStateListener(new HandlerExecutor(mHandler),
+                mPhoneStateListener);
 
         // Listen for user switches.  When the user switches, we need to ensure that if the current
         // use is not the primary user we disable video calling.
@@ -1353,8 +1403,7 @@
 
     private void registerContentObservers() {
         // Listen to the RTT system setting so that we update it when the user flips it.
-        ContentObserver rttUiSettingObserver = new ContentObserver(
-                new Handler(Looper.getMainLooper())) {
+        ContentObserver rttUiSettingObserver = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 synchronized (mAccountsLock) {
@@ -1370,8 +1419,7 @@
                 rttSettingUri, false, rttUiSettingObserver);
 
         // Listen to the changes to the user's Contacts Discovery Setting.
-        ContentObserver contactDiscoveryObserver = new ContentObserver(
-                new Handler(Looper.getMainLooper())) {
+        ContentObserver contactDiscoveryObserver = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 synchronized (mAccountsLock) {
@@ -1405,6 +1453,17 @@
         return false;
     }
 
+    PhoneAccountHandle getPhoneAccountHandleForSubId(int subId) {
+        synchronized (mAccountsLock) {
+            for (AccountEntry entry : mAccounts) {
+                if (entry.getSubId() == subId) {
+                    return entry.getPhoneAccountHandle();
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * Un-registers any {@link PhoneAccount}s which are no longer present in the list
      * {@code AccountEntry}(s).
@@ -1462,7 +1521,7 @@
                         }
 
                         mAccounts.add(new AccountEntry(phone, false /* emergency */,
-                                false /* isDummy */));
+                                false /* isTest */));
                     }
                 }
             } finally {
@@ -1473,14 +1532,14 @@
                     Log.i(this, "setupAccounts: adding default");
                     mAccounts.add(
                             new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
-                                    false /* isDummy */));
+                                    false /* isTest */));
                 }
             }
 
             // Add a fake account entry.
-            if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
+            if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("test_sim"))) {
                 mAccounts.add(new AccountEntry(phones[0], false /* emergency */,
-                        true /* isDummy */));
+                        true /* isTest */));
             }
         }
 
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 95281b3..fd16d4b 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -260,6 +260,8 @@
                     }
 
                     mTelephonyConference = new TelephonyConference(phoneAccountHandle);
+                    Log.i(this, "Creating new TelephonyConference to hold conferenced connections."
+                            + " conference=" + mTelephonyConference);
                     for (Connection connection : conferencedConnections) {
                         Log.d(this, "Adding a connection to a conference call: %s %s",
                                 mTelephonyConference, connection);
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index b4dd050..c41bf1a 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -28,6 +28,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
+import android.telecom.BluetoothCallQualityReport;
 import android.telecom.CallAudioState;
 import android.telecom.Conference;
 import android.telecom.Connection;
@@ -46,6 +47,8 @@
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
 import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.RtpHeaderExtension;
+import android.telephony.ims.RtpHeaderExtensionType;
 import android.text.TextUtils;
 import android.util.Pair;
 
@@ -61,6 +64,9 @@
 import com.android.internal.telephony.Connection.PostDialListener;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.d2d.Communicator;
+import com.android.internal.telephony.d2d.RtpAdapter;
+import com.android.internal.telephony.d2d.RtpTransport;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneCall;
@@ -70,6 +76,8 @@
 import com.android.phone.PhoneGlobals;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
+import com.android.phone.callcomposer.CallComposerPictureManager;
+import com.android.phone.callcomposer.CallComposerPictureTransfer;
 import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
@@ -85,7 +93,7 @@
 /**
  * Base class for CDMA and GSM connections.
  */
-abstract class TelephonyConnection extends Connection implements Holdable {
+abstract class TelephonyConnection extends Connection implements Holdable, Communicator.Callback {
     private static final String LOG_TAG = "TelephonyConnection";
 
     private static final int MSG_PRECISE_CALL_STATE_CHANGED = 1;
@@ -96,6 +104,9 @@
     private static final int MSG_CONFERENCE_MERGE_FAILED = 6;
     private static final int MSG_SUPP_SERVICE_NOTIFY = 7;
 
+    // the threshold used to compare mAudioCodecBitrateKbps and mAudioCodecBandwidth.
+    private static final float THRESHOLD = 0.01f;
+
     /**
      * Mappings from {@link com.android.internal.telephony.Connection} extras keys to their
      * equivalents defined in {@link android.telecom.Connection}.
@@ -117,6 +128,9 @@
     private static final int MSG_REDIAL_CONNECTION_CHANGED = 20;
     private static final int MSG_REJECT = 21;
 
+    private static final String JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN = "+81";
+    private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
+
     private List<Uri> mParticipants;
     private boolean mIsAdhocConferenceCall;
 
@@ -149,15 +163,18 @@
                             mOriginalConnection.getAddress() != null &&
                             mOriginalConnection.getAddress().equals(connection.getAddress())) ||
                             connection.getState() == mOriginalConnection.getStateBeforeHandover())) {
-                            Log.d(TelephonyConnection.this,
-                                    "SettingOriginalConnection " + mOriginalConnection.toString()
-                                            + " with " + connection.toString());
+                            Log.d(TelephonyConnection.this, "Setting original connection after"
+                                    + " handover or redial, current original connection="
+                                    + mOriginalConnection.toString()
+                                    + ", new original connection="
+                                    + connection.toString());
                             setOriginalConnection(connection);
                             mWasImsConnection = false;
                         }
                     } else {
                         Log.w(TelephonyConnection.this,
-                                what + ": mOriginalConnection==null - invalid state (not cleaned up)");
+                                what + ": mOriginalConnection==null --"
+                                        + " invalid state (not cleaned up)");
                     }
                     break;
                 case MSG_RINGBACK_TONE:
@@ -478,6 +495,19 @@
         public void onRingbackRequested(Connection c, boolean ringback) {}
     }
 
+    public static class D2DCallStateAdapter extends TelephonyConnectionListener {
+        private Communicator mCommunicator;
+
+        D2DCallStateAdapter(Communicator communicator) {
+            mCommunicator = communicator;
+        }
+
+        @Override
+        public void onStateChanged(android.telecom.Connection c, int state) {
+            mCommunicator.onStateChanged(c, state);
+        }
+    }
+
     private final PostDialListener mPostDialListener = new PostDialListener() {
         @Override
         public void onPostDialWait() {
@@ -692,6 +722,20 @@
         public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall) {
             setIsNetworkIdentifiedEmergencyCall(isEmergencyCall);
         }
+
+        /**
+         * Indicates data from an RTP header extension has been received from the network.
+         * @param extensionData The extension data.
+         */
+        @Override
+        public void onReceivedRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> extensionData) {
+            if (mRtpTransport == null) {
+                return;
+            }
+            Log.i(this, "onReceivedRtpHeaderExtensions: received %d extensions",
+                    extensionData.size());
+            mRtpTransport.onRtpHeaderExtensionsReceived(extensionData);
+        }
     };
 
     private TelephonyConnectionService mTelephonyConnectionService;
@@ -796,11 +840,25 @@
     private int mHangupDisconnectCause = DisconnectCause.NOT_VALID;
 
     /**
+     * Provides a means for a {@link Communicator} to be informed of call state changes.
+     */
+    private D2DCallStateAdapter mD2DCallStateAdapter;
+
+    private RtpTransport mRtpTransport;
+
+    /**
+     * Facilitates device to device communication.
+     */
+    private Communicator mCommunicator;
+
+    /**
      * Listeners to our TelephonyConnection specific callbacks
      */
     private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
             new ConcurrentHashMap<TelephonyConnectionListener, Boolean>(8, 0.9f, 1));
 
+    private CallQualityManager mCallQualityManager;
+
     protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection,
             String callId, @android.telecom.Call.Details.CallDirection int callDirection) {
         setCallDirection(callDirection);
@@ -810,6 +868,20 @@
         }
     }
 
+    @Override
+    public void onCallEvent(String event, Bundle extras) {
+        switch (event) {
+            case BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT:
+                if (mCallQualityManager == null) {
+                    mCallQualityManager = new CallQualityManager(getPhone().getContext());
+                }
+                mCallQualityManager.onBluetoothCallQualityReported(extras);
+                break;
+            default:
+                break;
+        }
+
+    }
     /**
      * Creates a clone of the current {@link TelephonyConnection}.
      *
@@ -1059,6 +1131,43 @@
     }
 
     @Override
+    public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts) {
+        if (isImsConnection()) {
+            ImsPhone imsPhone = (getPhone() instanceof ImsPhone) ? (ImsPhone) getPhone() : null;
+            if (imsPhone != null
+                    && imsPhone.getCallComposerStatus() == TelephonyManager.CALL_COMPOSER_STATUS_ON
+                    && !isBlocked && isInContacts) {
+                ImsPhoneConnection originalConnection = (ImsPhoneConnection) mOriginalConnection;
+                ImsCallProfile profile = originalConnection.getImsCall().getCallProfile();
+                String serverUrl = CallComposerPictureManager.sTestMode
+                        ? CallComposerPictureManager.FAKE_SERVER_URL
+                        : profile.getCallExtra(ImsCallProfile.EXTRA_PICTURE_URL);
+                if (profile != null
+                        && !TextUtils.isEmpty(serverUrl)) {
+                    CallComposerPictureManager manager = CallComposerPictureManager
+                            .getInstance(getPhone().getContext(), getPhone().getSubId());
+                    manager.handleDownloadFromServer(new CallComposerPictureTransfer.Factory() {},
+                            serverUrl,
+                            (result) -> {
+                                if (result.first != null) {
+                                    Bundle newExtras = new Bundle();
+                                    newExtras.putParcelable(TelecomManager.EXTRA_PICTURE_URI,
+                                            result.first);
+                                    putTelephonyExtras(newExtras);
+                                } else {
+                                    Log.i(this, "Call composer picture download:"
+                                            + " error=" + result.second);
+                                    Bundle newExtras = new Bundle();
+                                    newExtras.putBoolean(TelecomManager.EXTRA_HAS_PICTURE, false);
+                                    putTelephonyExtras(newExtras);
+                                }
+                            });
+                }
+            }
+        }
+    }
+
+    @Override
     public void handleRttUpgradeResponse(RttTextStream textStream) {
         if (!isImsConnection()) {
             Log.w(this, "handleRttUpgradeResponse - not in IMS, so RTT cannot be enabled.");
@@ -1276,6 +1385,8 @@
                 isNetworkIdentifiedEmergencyCall());
         newProperties = changeBitmask(newProperties, PROPERTY_IS_ADHOC_CONFERENCE,
                 isAdhocConferenceCall());
+        newProperties = changeBitmask(newProperties, PROPERTY_CROSS_SIM,
+                isCrossSimCall());
 
         if (getConnectionProperties() != newProperties) {
             setTelephonyConnectionProperties(newProperties);
@@ -1295,6 +1406,9 @@
             if (isShowingOriginalDialString()
                     && mOriginalConnection.getOrigDialString() != null) {
                 address = getAddressFromNumber(mOriginalConnection.getOrigDialString());
+            } else if (isNeededToFormatIncomingNumberForJp()) {
+                address = getAddressFromNumber(
+                        formatIncomingNumberForJp(mOriginalConnection.getAddress()));
             } else {
                 address = getAddressFromNumber(mOriginalConnection.getAddress());
             }
@@ -1316,7 +1430,9 @@
                 setCallerDisplayName(name, namePresentation);
             }
 
-            if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
+            TelephonyManager tm = (TelephonyManager) getPhone().getContext()
+                    .getSystemService(Context.TELEPHONY_SERVICE);
+            if (tm.isEmergencyNumber(mOriginalConnection.getAddress())) {
                 mTreatAsEmergencyCall = true;
             }
 
@@ -1379,7 +1495,9 @@
             mHandler.obtainMessage(MSG_CONNECTION_EXTRAS_CHANGED, connExtras == null ? null :
                     new Bundle(connExtras)).sendToTarget();
 
-        if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
+        TelephonyManager tm = (TelephonyManager) getPhone().getContext()
+                .getSystemService(Context.TELEPHONY_SERVICE);
+        if (tm.isEmergencyNumber(mOriginalConnection.getAddress())) {
             mTreatAsEmergencyCall = true;
         }
         // Propagate VERSTAT for IMS calls.
@@ -1388,6 +1506,9 @@
         if (isImsConnection()) {
             mWasImsConnection = true;
         }
+        if (originalConnection instanceof ImsPhoneConnection) {
+            maybeConfigureDeviceToDeviceCommunication();
+        }
         mIsMultiParty = mOriginalConnection.isMultiparty();
 
         Bundle extrasToPut = new Bundle();
@@ -1403,6 +1524,15 @@
         } else {
             extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL);
         }
+
+        if (mOriginalConnection != null) {
+            ArrayList<String> forwardedNumber = mOriginalConnection.getForwardedNumber();
+            if (forwardedNumber != null) {
+                extrasToPut.putStringArrayList(Connection.EXTRA_LAST_FORWARDED_NUMBER,
+                        forwardedNumber);
+            }
+        }
+
         putTelephonyExtras(extrasToPut);
         removeTelephonyExtras(extrasToRemove);
 
@@ -1483,7 +1613,8 @@
         }
     }
 
-    private void refreshCodecType() {
+    private void refreshCodec() {
+        boolean changed = false;
         Bundle newExtras = getExtras();
         if (newExtras == null) {
             newExtras = new Bundle();
@@ -1499,6 +1630,31 @@
                 Connection.AUDIO_CODEC_NONE);
         if (newCodecType != oldCodecType) {
             newExtras.putInt(Connection.EXTRA_AUDIO_CODEC, newCodecType);
+            changed = true;
+        }
+        if (isImsConnection()) {
+            float newBitrate = getOriginalConnection().getAudioCodecBitrateKbps();
+            float oldBitrate = newExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, 0.0f);
+            if (Math.abs(newBitrate - oldBitrate) > THRESHOLD) {
+                newExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, newBitrate);
+                changed = true;
+            }
+
+            float newBandwidth = getOriginalConnection().getAudioCodecBandwidthKhz();
+            float oldBandwidth = newExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ,
+                    0.0f);
+            if (Math.abs(newBandwidth - oldBandwidth) > THRESHOLD) {
+                newExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ, newBandwidth);
+                changed = true;
+            }
+        } else {
+            ArrayList<String> toRemove = new ArrayList<>();
+            toRemove.add(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS);
+            toRemove.add(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ);
+            removeTelephonyExtras(toRemove);
+        }
+
+        if (changed) {
             putTelephonyExtras(newExtras);
         }
     }
@@ -1577,7 +1733,7 @@
                 }
             }
 
-            isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+            isVowifiEnabled = isWfcEnabled(phone);
         }
 
         if (isCurrentVideoCall) {
@@ -1711,8 +1867,12 @@
           *     - not indicated, then the add participant capability is same as before.
           */
         if (isCapable && (mOriginalConnection != null) && !mIsMultiParty) {
-            isCapable = mOriginalConnectionExtras.getBoolean(
+            // In case OEMs are still using deprecated value, read it and use it as default value.
+            boolean isCapableFromDeprecatedExtra = mOriginalConnectionExtras.getBoolean(
                     ImsCallProfile.EXTRA_CONFERENCE_AVAIL, isCapable);
+            isCapable = mOriginalConnectionExtras.getBoolean(
+                    ImsCallProfile.EXTRA_EXTENDING_TO_CONFERENCE_SUPPORTED,
+                    isCapableFromDeprecatedExtra);
         }
         return isCapable;
     }
@@ -2044,7 +2204,9 @@
                     // If extras contain Conference support information,
                     // then ensure capabilities are updated.
                     if (mOriginalConnectionExtras.containsKey(
-                            ImsCallProfile.EXTRA_CONFERENCE_AVAIL)) {
+                            ImsCallProfile.EXTRA_EXTENDING_TO_CONFERENCE_SUPPORTED)
+                            || mOriginalConnectionExtras.containsKey(
+                                ImsCallProfile.EXTRA_CONFERENCE_AVAIL)) {
                         updateConnectionCapabilities();
                     }
                 } else {
@@ -2167,6 +2329,10 @@
                 case DISCONNECTING:
                     break;
             }
+
+            if (mCommunicator != null) {
+                mCommunicator.onStateChanged(this, getState());
+            }
         }
     }
 
@@ -2182,7 +2348,7 @@
         updateAddress();
         updateMultiparty();
         refreshDisableAddCall();
-        refreshCodecType();
+        refreshCodec();
     }
 
     /**
@@ -2304,6 +2470,16 @@
     }
 
     /**
+     * Determines if the current connection is cross sim calling
+     */
+    private boolean isCrossSimCall() {
+        return mOriginalConnection != null
+                && mOriginalConnection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS
+                && mOriginalConnection instanceof ImsPhoneConnection
+                && ((ImsPhoneConnection) mOriginalConnection).isCrossSimCall();
+    }
+
+    /**
      * Determines if the current connection is pullable.
      *
      * A connection is deemed to be pullable if the original connection capabilities state that it
@@ -2541,8 +2717,10 @@
      */
     protected boolean isImsConnection() {
         com.android.internal.telephony.Connection originalConnection = getOriginalConnection();
-        return originalConnection != null &&
-                originalConnection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
+
+        return originalConnection != null
+                && originalConnection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS
+                && originalConnection instanceof ImsPhoneConnection;
     }
 
     /**
@@ -2713,15 +2891,15 @@
         boolean isIms = phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
         boolean isVoWifiEnabled = false;
         if (isIms) {
-            isVoWifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+            isVoWifiEnabled = isWfcEnabled(phone);
         }
         boolean isRttMergeSupported = getCarrierConfig()
                 .getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
         PhoneAccountHandle phoneAccountHandle = isIms ? PhoneUtils
                 .makePstnPhoneAccountHandle(phone.getDefaultPhone())
                 : PhoneUtils.makePstnPhoneAccountHandle(phone);
-        TelecomAccountRegistry telecomAccountRegistry = TelecomAccountRegistry
-                .getInstance(getPhone().getContext());
+        TelecomAccountRegistry telecomAccountRegistry = getTelecomAccountRegistry(
+                getPhone().getContext());
         boolean isConferencingSupported = telecomAccountRegistry
                 .isMergeCallSupported(phoneAccountHandle);
         boolean isImsConferencingSupported = telecomAccountRegistry
@@ -2730,6 +2908,19 @@
                 .isVideoConferencingSupported(phoneAccountHandle);
         boolean isMergeOfWifiCallsAllowedWhenVoWifiOff = telecomAccountRegistry
                 .isMergeOfWifiCallsAllowedWhenVoWifiOff(phoneAccountHandle);
+        ImsCall imsCall = isImsConnection()
+                ? ((ImsPhoneConnection) getOriginalConnection()).getImsCall()
+                : null;
+        CarrierConfigManager configManager = (CarrierConfigManager) phone.getContext()
+                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        boolean downGradedVideoCall = false;
+        if (configManager != null) {
+            PersistableBundle config = configManager.getConfigForSubId(phone.getSubId());
+            if (config != null) {
+                downGradedVideoCall = config.getBoolean(
+                        CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL);
+            }
+        }
 
         Log.v(this, "refreshConferenceSupported : isConfSupp=%b, isImsConfSupp=%b, " +
                 "isVidConfSupp=%b, isMergeOfWifiAllowed=%b, " +
@@ -2750,6 +2941,12 @@
         } else if (isVideoCall && !mIsCarrierVideoConferencingSupported) {
             isConferenceSupported = false;
             Log.d(this, "refreshConferenceSupported = false; video conf not supported.");
+        } else if ((imsCall != null) && (imsCall.wasVideoCall() && downGradedVideoCall)
+                && !mIsCarrierVideoConferencingSupported) {
+            isConferenceSupported = false;
+            Log.d(this,
+                    "refreshConferenceSupported = false;"
+                            + " video conf not supported for downgraded audio call.");
         } else if (!isMergeOfWifiCallsAllowedWhenVoWifiOff && isWifi() && !isVoWifiEnabled) {
             isConferenceSupported = false;
             Log.d(this,
@@ -2763,6 +2960,12 @@
             notifyConferenceSupportedChanged(isConferenceSupported);
         }
     }
+
+    @VisibleForTesting
+    boolean isWfcEnabled(Phone phone) {
+        return ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+    }
+
     /**
      * Provides a mapping from extras keys which may be found in the
      * {@link com.android.internal.telephony.Connection} to their equivalents defined in
@@ -3055,6 +3258,77 @@
     }
 
     /**
+     * Where device to device communication is available and this is an IMS call, configures the
+     * D2D communication infrastructure for operation.
+     */
+    private void maybeConfigureDeviceToDeviceCommunication() {
+        if (!getPhone().getContext().getResources().getBoolean(
+                R.bool.config_use_device_to_device_communication)) {
+            Log.d(this, "maybeConfigureDeviceToDeviceCommunication: not using D2D.");
+            return;
+        }
+        if (!isImsConnection()) {
+            Log.d(this, "maybeConfigureDeviceToDeviceCommunication: not an IMS connection.");
+            return;
+        }
+        // Implement abstracted out RTP functionality the RTP transport depends on.
+        RtpAdapter rtpAdapter = new RtpAdapter() {
+            @Override
+            public Set<RtpHeaderExtensionType> getAcceptedRtpHeaderExtensions() {
+                if (!isImsConnection()) {
+                    return Collections.EMPTY_SET;
+                }
+                ImsPhoneConnection originalConnection =
+                        (ImsPhoneConnection) mOriginalConnection;
+                return originalConnection.getAcceptedRtpHeaderExtensions();
+            }
+
+            @Override
+            public void sendRtpHeaderExtensions(
+                    @NonNull Set<RtpHeaderExtension> rtpHeaderExtensions) {
+                if (!isImsConnection()) {
+                    Log.w(TelephonyConnection.this, "sendRtpHeaderExtensions: not an ims conn.");
+                }
+                Log.d(TelephonyConnection.this, "sendRtpHeaderExtensions: sending %d messages",
+                        rtpHeaderExtensions.size());
+                ImsPhoneConnection originalConnection =
+                        (ImsPhoneConnection) mOriginalConnection;
+                originalConnection.sendRtpHeaderExtensions(rtpHeaderExtensions);
+            }
+        };
+        mRtpTransport = new RtpTransport(rtpAdapter, null /* TODO: not needed yet */, mHandler);
+        mCommunicator = new Communicator(List.of(mRtpTransport), this);
+        mD2DCallStateAdapter = new D2DCallStateAdapter(mCommunicator);
+        addTelephonyConnectionListener(mD2DCallStateAdapter);
+    }
+
+    /**
+     * @return The D2D communication class, or {@code null} if not set up.
+     */
+    public @Nullable Communicator getCommunicator() {
+        return mCommunicator;
+    }
+
+    /**
+     * Called by {@link Communicator} associated with this {@link TelephonyConnection} when there
+     * are incoming device-to-device messages received.
+     * @param messages the incoming messages.
+     */
+    @Override
+    public void onMessagesReceived(@NonNull Set<Communicator.Message> messages) {
+        Log.i(this, "onMessagesReceived: got d2d messages: %s", messages);
+        // TODO: Actually do something WITH the messages.
+
+        // TODO: Remove this prior to launch.
+        // This is just here for debug purposes; send as a connection event so that it
+        // will be output in the Telecom logs.
+        for (Communicator.Message msg : messages) {
+            sendConnectionEvent("D2D_" + Communicator.messageToString(msg.getType())
+                + "_" + Communicator.valueToString(msg.getType(), msg.getValue()), null);
+        }
+    }
+
+    /**
      * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
      * operation has started.
      */
@@ -3201,4 +3475,33 @@
             listener.onStatusHintsChanged(this, statusHints);
         }
     }
+
+    /**
+     * Whether the incoming call number should be formatted to national number for Japan.
+     * @return {@code true} should be convert to the national format, {@code false} otherwise.
+     */
+    private boolean isNeededToFormatIncomingNumberForJp() {
+        if (mOriginalConnection.isIncoming()
+                && !TextUtils.isEmpty(mOriginalConnection.getAddress())
+                && mOriginalConnection.getAddress().startsWith(JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN)) {
+            PersistableBundle b = getCarrierConfig();
+            return b != null && b.getBoolean(
+                    CarrierConfigManager.KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL);
+        }
+        return false;
+    }
+
+    /**
+     * Format the incoming call number to national number for Japan.
+     * @param number
+     * @return the formatted phone number (e.g, "+819012345678" -> "09012345678")
+     */
+    private String formatIncomingNumberForJp(String number) {
+        return PhoneNumberUtils.stripSeparators(
+                PhoneNumberUtils.formatNumber(number, JAPAN_ISO_COUNTRY_CODE));
+    }
+
+    public TelecomAccountRegistry getTelecomAccountRegistry(Context context) {
+        return TelecomAccountRegistry.getInstance(context);
+    }
 }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 356407a..219c782 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -17,10 +17,13 @@
 package com.android.services.telephony;
 
 import android.annotation.NonNull;
+import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
@@ -28,6 +31,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.ParcelUuid;
 import android.telecom.Conference;
 import android.telecom.Connection;
 import android.telecom.ConnectionRequest;
@@ -46,6 +50,7 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.text.TextUtils;
 import android.util.Pair;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Call;
@@ -59,12 +64,15 @@
 import com.android.internal.telephony.PhoneSwitcher;
 import com.android.internal.telephony.RIL;
 import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.d2d.Communicator;
 import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.phone.MMIDialogActivity;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
+import com.android.phone.callcomposer.CallComposerPictureManager;
+import com.android.phone.settings.SuppServicesUiUtil;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -72,6 +80,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -155,6 +164,9 @@
     private EmergencyTonePlayer mEmergencyTonePlayer;
     private HoldTracker mHoldTracker;
     private boolean mIsTtyEnabled;
+    /** Set to true when there is an emergency call pending which will potential trigger a dial.
+     * This must be set to false when the call is dialed. */
+    private volatile boolean mIsEmergencyCallPending;
 
     // Contains one TelephonyConnection that has placed a call and a memory of which Phones it has
     // already tried to connect with. There should be only one TelephonyConnection trying to place a
@@ -795,6 +807,10 @@
             if (mRadioOnHelper == null) {
                 mRadioOnHelper = new RadioOnHelper(this);
             }
+
+            if (isEmergencyNumber) {
+                mIsEmergencyCallPending = true;
+            }
             mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
                 @Override
                 public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
@@ -907,6 +923,14 @@
     }
 
     /**
+     * @return whether radio has recently been turned on for emergency call but hasn't actually
+     * dialed the call yet.
+     */
+    public boolean isEmergencyCallPending() {
+        return mIsEmergencyCallPending;
+    }
+
+    /**
      * Whether the cellular radio is power off because the device is on Bluetooth.
      */
     private boolean isRadioPowerDownOnBluetooth() {
@@ -931,6 +955,7 @@
                 for (Phone curPhone : mPhoneFactoryProxy.getPhones()) {
                     curPhone.setRadioPower(true, false, false, true);
                 }
+                mIsEmergencyCallPending = false;
             }
             return;
         }
@@ -946,6 +971,7 @@
                         Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
                         adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
                                 numberToDial, handle, originalPhoneType, true);
+                        mIsEmergencyCallPending = false;
                     }
                 });
             }
@@ -956,6 +982,7 @@
                     mDisconnectCauseFactory.toTelecomDisconnectCause(
                             android.telephony.DisconnectCause.POWER_OFF,
                             "Failed to turn on radio."));
+            mIsEmergencyCallPending = false;
         }
     }
 
@@ -1055,7 +1082,8 @@
         if (state == ServiceState.STATE_OUT_OF_SERVICE) {
             int dataNetType = phone.getServiceState().getDataNetworkType();
             if (dataNetType == TelephonyManager.NETWORK_TYPE_LTE ||
-                    dataNetType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
+                    dataNetType == TelephonyManager.NETWORK_TYPE_LTE_CA ||
+                    dataNetType == TelephonyManager.NETWORK_TYPE_NR) {
                 state = phone.getServiceState().getDataRegistrationState();
             }
         }
@@ -1139,9 +1167,9 @@
                             phone.getPhoneId()));
         }
 
-
+        PhoneAccountHandle accountHandle = adjustAccountHandle(phone, request.getAccountHandle());
         final TelephonyConnection connection =
-                createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle(),
+                createConnectionFor(phone, null, true /* isOutgoing */, accountHandle,
                         request.getTelecomCallId(), request.isAdhocConferenceCall());
         if (connection == null) {
             return Connection.createFailedConnection(
@@ -1185,15 +1213,23 @@
                             "Phone is null"));
         }
 
+        Bundle extras = request.getExtras();
+        String disconnectMessage = null;
+        if (extras.containsKey(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE)) {
+            disconnectMessage = extras.getString(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE);
+            Log.i(this, "onCreateIncomingConnection Disconnect message " + disconnectMessage);
+        }
+
         Call call = phone.getRingingCall();
-        if (!call.getState().isRinging()) {
+        if (!call.getState().isRinging()
+                || (disconnectMessage != null
+                && disconnectMessage.equals(TelecomManager.CALL_AUTO_DISCONNECT_MESSAGE_STRING))) {
             Log.i(this, "onCreateIncomingConnection, no ringing call");
             Connection connection = Connection.createFailedConnection(
                     mDisconnectCauseFactory.toTelecomDisconnectCause(
                             android.telephony.DisconnectCause.INCOMING_MISSED,
                             "Found no ringing call",
                             phone.getPhoneId()));
-            Bundle extras = request.getExtras();
 
             long time = extras.getLong(TelecomManager.EXTRA_CALL_CREATED_EPOCH_TIME_MILLIS);
             if (time != 0) {
@@ -1535,10 +1571,17 @@
         if (phone == null || TextUtils.isEmpty(number) || !phone.getServiceState().getRoaming()) {
             return false;
         }
+        boolean allowPrefixIms = true;
         String[] blockPrefixes = null;
         CarrierConfigManager cfgManager = (CarrierConfigManager)
                 phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
         if (cfgManager != null) {
+            allowPrefixIms = cfgManager.getConfigForSubId(phone.getSubId()).getBoolean(
+                    CarrierConfigManager.KEY_SUPPORT_IMS_CALL_FORWARDING_WHILE_ROAMING_BOOL,
+                    true);
+            if (allowPrefixIms && useImsForAudioOnlyCall(phone)) {
+                return false;
+            }
             blockPrefixes = cfgManager.getConfigForSubId(phone.getSubId()).getStringArray(
                     CarrierConfigManager.KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY);
         }
@@ -1553,6 +1596,14 @@
         return false;
     }
 
+    private boolean useImsForAudioOnlyCall(Phone phone) {
+        Phone imsPhone = phone.getImsPhone();
+
+        return imsPhone != null
+                && (imsPhone.isVolteEnabled() || imsPhone.isWifiCallingEnabled())
+                && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
+    }
+
     private boolean isRadioOn() {
         boolean result = false;
         for (Phone phone : mPhoneFactoryProxy.getPhones()) {
@@ -1655,13 +1706,34 @@
                 ? connection.getAddress().getSchemeSpecificPart()
                 : "";
 
+        if (showDataDialog(phone, number)) {
+            connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
+                        android.telephony.DisconnectCause.DIALED_MMI, "UT is not available"));
+            return;
+        }
+
+        if (extras != null && extras.containsKey(TelecomManager.EXTRA_OUTGOING_PICTURE)) {
+            ParcelUuid uuid = extras.getParcelable(TelecomManager.EXTRA_OUTGOING_PICTURE);
+            CallComposerPictureManager.getInstance(phone.getContext(), phone.getSubId())
+                    .storeUploadedPictureToCallLog(uuid.getUuid(), (uri) -> {
+                        if (uri != null) {
+                            try {
+                                Bundle b = new Bundle();
+                                b.putParcelable(TelecomManager.EXTRA_PICTURE_URI, uri);
+                                connection.putTelephonyExtras(b);
+                            } catch (Exception e) {
+                                Log.e(this, e, "Couldn't set picture extra on outgoing call");
+                            }
+                        }
+                    });
+        }
+
         com.android.internal.telephony.Connection originalConnection = null;
         try {
             if (phone != null) {
                 EmergencyNumber emergencyNumber =
                         phone.getEmergencyNumberTracker().getEmergencyNumber(number);
                 if (emergencyNumber != null) {
-                    phone.notifyOutgoingEmergencyCall(emergencyNumber);
                     if (!getAllConnections().isEmpty()) {
                         if (!shouldHoldForEmergencyCall(phone)) {
                             // If we do not support holding ongoing calls for an outgoing
@@ -1713,7 +1785,8 @@
         if (originalConnection == null) {
             int telephonyDisconnectCause = android.telephony.DisconnectCause.OUTGOING_FAILURE;
             // On GSM phones, null connection means that we dialed an MMI code
-            if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+            if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
+                phone.isUtEnabled()) {
                 Log.d(this, "dialed MMI code");
                 int subId = phone.getSubId();
                 Log.d(this, "subId: "+subId);
@@ -2358,6 +2431,78 @@
         }
     }
 
+    private boolean showDataDialog(Phone phone, String number) {
+        boolean ret = false;
+        final Context context = getApplicationContext();
+        String suppKey = MmiCodeUtil.getSuppServiceKey(number);
+        if (suppKey != null) {
+            boolean clirOverUtPrecautions = false;
+            boolean cfOverUtPrecautions = false;
+            boolean cbOverUtPrecautions = false;
+            boolean cwOverUtPrecautions = false;
+
+            CarrierConfigManager cfgManager = (CarrierConfigManager)
+                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            if (cfgManager != null) {
+                clirOverUtPrecautions = cfgManager.getConfigForSubId(phone.getSubId())
+                    .getBoolean(CarrierConfigManager.KEY_CALLER_ID_OVER_UT_WARNING_BOOL);
+                cfOverUtPrecautions = cfgManager.getConfigForSubId(phone.getSubId())
+                    .getBoolean(CarrierConfigManager.KEY_CALL_FORWARDING_OVER_UT_WARNING_BOOL);
+                cbOverUtPrecautions = cfgManager.getConfigForSubId(phone.getSubId())
+                    .getBoolean(CarrierConfigManager.KEY_CALL_BARRING_OVER_UT_WARNING_BOOL);
+                cwOverUtPrecautions = cfgManager.getConfigForSubId(phone.getSubId())
+                    .getBoolean(CarrierConfigManager.KEY_CALL_WAITING_OVER_UT_WARNING_BOOL);
+            }
+
+            boolean isSsOverUtPrecautions = SuppServicesUiUtil
+                .isSsOverUtPrecautions(context, phone);
+            if (isSsOverUtPrecautions) {
+                boolean showDialog = false;
+                if (suppKey == MmiCodeUtil.BUTTON_CLIR_KEY && clirOverUtPrecautions) {
+                    showDialog = true;
+                } else if (suppKey == MmiCodeUtil.CALL_FORWARDING_KEY && cfOverUtPrecautions) {
+                    showDialog = true;
+                } else if (suppKey == MmiCodeUtil.CALL_BARRING_KEY && cbOverUtPrecautions) {
+                    showDialog = true;
+                } else if (suppKey == MmiCodeUtil.BUTTON_CW_KEY && cwOverUtPrecautions) {
+                    showDialog = true;
+                }
+
+                if (showDialog) {
+                    Log.d(this, "Creating UT Data enable dialog");
+                    String message = SuppServicesUiUtil.makeMessage(context, suppKey, phone);
+                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
+                    DialogInterface.OnClickListener networkSettingsClickListener =
+                            new Dialog.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialog, int which) {
+                                    Intent intent = new Intent(Intent.ACTION_MAIN);
+                                    ComponentName mobileNetworkSettingsComponent
+                                        = new ComponentName(
+                                                context.getString(
+                                                    R.string.mobile_network_settings_package),
+                                                context.getString(
+                                                    R.string.mobile_network_settings_class));
+                                    intent.setComponent(mobileNetworkSettingsComponent);
+                                    context.startActivity(intent);
+                                }
+                            };
+                    Dialog dialog = builder.setMessage(message)
+                        .setNeutralButton(context.getResources().getString(
+                                R.string.settings_label),
+                                networkSettingsClickListener)
+                        .setPositiveButton(context.getResources().getString(
+                                R.string.supp_service_over_ut_precautions_dialog_dismiss), null)
+                        .create();
+                    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+                    dialog.show();
+                    ret = true;
+                }
+            }
+        }
+        return ret;
+    }
+
     /**
      * Adds a {@link Conference} to the telephony ConnectionService and registers a listener for
      * changes to the conference.  Should be used instead of {@link #addConference(Conference)}.
@@ -2367,4 +2512,45 @@
         addConference(conference);
         conference.addTelephonyConferenceListener(mTelephonyConferenceListener);
     }
+
+    /**
+     * Sends a test device to device message on the active call which supports it.
+     * Used exclusively from the telephony shell command to send a test message.
+     *
+     * @param message the message
+     * @param value the value
+     */
+    public void sendTestDeviceToDeviceMessage(int message, int value) {
+       getAllConnections().stream()
+               .filter(f -> f instanceof TelephonyConnection)
+               .forEach(t -> {
+                        TelephonyConnection tc = (TelephonyConnection) t;
+                        Communicator c = tc.getCommunicator();
+                        if (c == null) {
+                            Log.w(this, "sendTestDeviceToDeviceMessage: D2D not enabled");
+                            return;
+                        }
+
+                        c.sendMessages(new HashSet<Communicator.Message>() {{
+                            add(new Communicator.Message(message, value));
+                        }});
+
+       });
+    }
+
+    private PhoneAccountHandle adjustAccountHandle(Phone phone,
+            PhoneAccountHandle origAccountHandle) {
+        int origSubId = PhoneUtils.getSubIdForPhoneAccountHandle(origAccountHandle);
+        int subId = phone.getSubId();
+        if (origSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                && subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                && origSubId != subId) {
+            PhoneAccountHandle handle = TelecomAccountRegistry.getInstance(this)
+                .getPhoneAccountHandleForSubId(subId);
+            if (handle != null) {
+                return handle;
+            }
+        }
+        return origAccountHandle;
+    }
 }
diff --git a/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java b/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java
new file mode 100644
index 0000000..9d2c5d6
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Defines the interface to be used to manage the state of a SipDelegate on the ImsService side.
+ */
+public interface DelegateBinderStateManager {
+
+    /**
+     * Callback interface that allows listeners to listen to changes in registration or
+     * configuration state.
+     */
+    interface StateCallback {
+        /**
+         * The SipDelegate has notified telephony that the registration state has changed.
+         */
+        void onRegistrationStateChanged(DelegateRegistrationState registrationState);
+
+        /**
+         * The SipDelegate has notified telephony that the IMS configuration has changed.
+         */
+        void onImsConfigurationChanged(SipDelegateImsConfiguration config);
+    }
+
+    /** Allow for mocks to be created for testing. */
+    @VisibleForTesting
+    interface Factory {
+        /**
+         * Create a new instance of this interface, which may change depending on the tags being
+         * denied. See {@link SipDelegateBinderConnectionStub} and
+         * {@link SipDelegateBinderConnection}
+         */
+        DelegateBinderStateManager create(int subId, DelegateRequest requestedConfig,
+                Set<FeatureTagState> transportDeniedTags,
+                Executor executor, List<StateCallback> stateCallbacks);
+    }
+
+    /**
+     * Start the process to create a SipDelegate on the ImsService.
+     * @param cb The Binder interface that the SipDelegate should use to notify new incoming SIP
+     *         messages as well as acknowledge whether or not an outgoing SIP message was
+     *         successfully sent.
+     * @param createdConsumer The consumer that will be notified when the creation process has
+     *         completed. Contains the ISipDelegate interface to communicate with the SipDelegate
+     *         and the feature tags the SipDelegate itself denied.
+     * @return true if the creation process started, false if the remote process died. If false, the
+     * consumers will not be notified.
+     */
+    boolean create(ISipDelegateMessageCallback cb,
+            BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer);
+
+    /**
+     * Destroy the existing SipDelegate managed by this object.
+     * <p>
+     * This instance should be cleaned up after this call.
+     * @param reason The reason for why this delegate is being destroyed.
+     * @param destroyedConsumer The consumer that will be notified when this operation completes.
+     *         Contains the reason the SipDelegate reported it was destroyed.
+     */
+    void destroy(int reason, Consumer<Integer> destroyedConsumer);
+
+    /**
+     * Called by IMS application, see
+     * {@link SipDelegateManager#triggerFullNetworkRegistration(SipDelegateConnection, int, String)}
+     * for more information about when this is called.
+     */
+    void triggerFullNetworkRegistration(int sipCode, String sipReason);
+}
diff --git a/src/com/android/services/telephony/rcs/DelegateStateTracker.java b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
new file mode 100644
index 0000000..18ad98e
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Manages the events sent back to the remote IMS application using the AIDL backing for the
+ * {@link DelegateConnectionStateCallback} interface.
+ */
+public class DelegateStateTracker implements DelegateBinderStateManager.StateCallback {
+    private static final String LOG_TAG = "DelegateST";
+
+    private final int mSubId;
+    private final ISipDelegateConnectionStateCallback mAppStateCallback;
+    private final ISipDelegate mLocalDelegateImpl;
+
+    private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+    private List<FeatureTagState> mDelegateDeniedTags;
+    private DelegateRegistrationState mLastRegState;
+    private boolean mCreatedCalled = false;
+    private int mRegistrationStateOverride = -1;
+
+    public DelegateStateTracker(int subId, ISipDelegateConnectionStateCallback appStateCallback,
+            ISipDelegate localDelegateImpl) {
+        mSubId = subId;
+        mAppStateCallback = appStateCallback;
+        mLocalDelegateImpl = localDelegateImpl;
+    }
+
+    /**
+     * Notify this state tracker that a new internal SipDelegate has been connected.
+     *
+     * Registration and state updates will be send via the
+     * {@link SipDelegateBinderConnection.StateCallback} callback implemented by this class as they
+     * arrive.
+     * @param deniedTags The tags denied by the SipTransportController and ImsService creating the
+     *         SipDelegate. These tags will need to be notified back to the IMS application.
+     */
+    public void sipDelegateConnected(Set<FeatureTagState> deniedTags) {
+        logi("SipDelegate connected with denied tags:" + deniedTags);
+        // From the IMS application perspective, we only call onCreated/onDestroyed once and
+        // provide the local implementation of ISipDelegate, which doesn't change, even though
+        // SipDelegates may be changing underneath.
+        if (!mCreatedCalled) {
+            mCreatedCalled = true;
+            notifySipDelegateCreated();
+        }
+        mRegistrationStateOverride = -1;
+        mDelegateDeniedTags = new ArrayList<>(deniedTags);
+    }
+
+    /**
+     * The underlying SipDelegate is changing due to a state change in the SipDelegateController.
+     *
+     * This will trigger an override of the IMS application's registration state. All feature tags
+     * in the REGISTERED state will be overridden to move to the deregistering state specified until
+     * a new SipDelegate was successfully created and {@link #sipDelegateConnected(Set)} was called
+     * or it was destroyed and {@link #sipDelegateDestroyed(int)} was called.
+     * @param deregisteringReason The new deregistering reason that all feature tags in the
+     *         registered state should now report.
+     */
+    public void sipDelegateChanging(int deregisteringReason) {
+        logi("SipDelegate Changing");
+        mRegistrationStateOverride = deregisteringReason;
+        if (mLastRegState == null) {
+            logw("sipDelegateChanging: invalid state, onRegistrationStateChanged never called.");
+            mLastRegState = new DelegateRegistrationState.Builder().build();
+        }
+        onRegistrationStateChanged(mLastRegState);
+    }
+
+    /**
+     * The underlying SipDelegate has been destroyed.
+     *
+     * This should only be called when the entire {@link SipDelegateController} is going down
+     * because the application has requested that the SipDelegate be destroyed.
+     *
+     * This can also be called in error conditions where the IMS application or ImsService has
+     * crashed.
+     * @param reason The reason that will be sent to the IMS application for why the SipDelegate
+     *         is being destroyed.
+     */
+    public void sipDelegateDestroyed(int reason) {
+        logi("SipDelegate destroyed:" + reason);
+        mRegistrationStateOverride = -1;
+        try {
+            mAppStateCallback.onDestroyed(reason);
+        } catch (RemoteException e) {
+            logw("sipDelegateDestroyed: IMS application is dead: " + e);
+        }
+    }
+
+    /**
+     * The underlying SipDelegate has reported that its registration state has changed.
+     * @param registrationState The RegistrationState reported by the SipDelegate to be sent to the
+     *         IMS application.
+     */
+    @Override
+    public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
+        if (mRegistrationStateOverride > DelegateRegistrationState.DEREGISTERED_REASON_UNKNOWN) {
+            logi("onRegistrationStateChanged: overriding registered state to "
+                    + mRegistrationStateOverride);
+            registrationState = overrideRegistrationForDelegateChange(mRegistrationStateOverride,
+                    registrationState);
+        }
+        if (registrationState.equals(mLastRegState)) {
+            logi("onRegistrationStateChanged: skipping notification, state is the same.");
+            return;
+        }
+        mLastRegState = registrationState;
+        logi("onRegistrationStateChanged: sending reg state " + registrationState);
+        try {
+            mAppStateCallback.onFeatureTagStatusChanged(registrationState, mDelegateDeniedTags);
+        } catch (RemoteException e) {
+            logw("onRegistrationStateChanged: IMS application is dead: " + e);
+        }
+    }
+
+    /**
+     * THe underlying SipDelegate has reported that the IMS configuration has changed.
+     * @param config The config to be sent to the IMS application.
+     */
+    @Override
+    public void onImsConfigurationChanged(SipDelegateImsConfiguration config) {
+        logi("onImsConfigurationChanged: Sending new IMS configuration.");
+        try {
+            mAppStateCallback.onImsConfigurationChanged(config);
+        } catch (RemoteException e) {
+            logw("onImsConfigurationChanged: IMS application is dead: " + e);
+        }
+    }
+
+    /** Write state about this tracker into the PrintWriter to be included in the dumpsys */
+    public void dump(PrintWriter printWriter) {
+        printWriter.println("Last reg state: " + mLastRegState);
+        printWriter.println("Denied tags: " + mDelegateDeniedTags);
+        printWriter.println();
+        printWriter.println("Most recent logs: ");
+        mLocalLog.dump(printWriter);
+    }
+
+    private DelegateRegistrationState overrideRegistrationForDelegateChange(
+            int registerOverrideReason, DelegateRegistrationState state) {
+        Set<String> registeredFeatures = state.getRegisteredFeatureTags();
+        DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
+        // keep other deregistering/deregistered tags the same.
+        for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
+            overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
+                    dereging.getState());
+        }
+        for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
+            overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
+                    dereged.getState());
+        }
+        // Override REGISTERED only
+        for (String ft : registeredFeatures) {
+            overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
+        }
+        return overriddenState.build();
+    }
+
+    private void notifySipDelegateCreated() {
+        try {
+            mAppStateCallback.onCreated(mLocalDelegateImpl);
+        } catch (RemoteException e) {
+            logw("notifySipDelegateCreated: IMS application is dead: " + e);
+        }
+    }
+
+    private void logi(String log) {
+        Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[I] " + log);
+    }
+    private void logw(String log) {
+        Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[W] " + log);
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
new file mode 100644
index 0000000..c42472d
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.os.Binder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Tracks the SIP message path both from the IMS application to the SipDelegate and from the
+ * SipDelegate back to the IMS Application.
+ * <p>
+ * Responsibilities include:
+ * 1) Queue incoming and outgoing SIP messages and deliver to IMS application and SipDelegate in
+ *        order. If there is an error delivering the message, notify the caller.
+ * 2) TODO Perform basic validation of outgoing messages.
+ * 3) TODO Record the status of ongoing SIP Dialogs and trigger the completion of pending
+ *         consumers when they are finished or call closeDialog to clean up the SIP
+ *         dialogs that did not complete within the allotted timeout time.
+ * <p>
+ * Note: This handles incoming binder calls, so all calls from other processes should be handled on
+ * the provided Executor.
+ */
+public class MessageTransportStateTracker implements DelegateBinderStateManager.StateCallback {
+    private static final String TAG = "MessageST";
+
+    /**
+     * Communicates the result of verifying whether a SIP message should be sent based on the
+     * contents of the SIP message as well as if the transport is in an available state for the
+     * intended recipient of the message.
+     */
+    private static class VerificationResult {
+        public static final VerificationResult SUCCESS = new VerificationResult();
+
+        /**
+         * If {@code true}, the requested SIP message has been verified to be sent to the remote. If
+         * {@code false}, the SIP message has failed verification and should not be sent to the
+         * result. The {@link #restrictedReason} field will contain the reason for the verification
+         * failure.
+         */
+        public final boolean isVerified;
+
+        /**
+         * The reason associated with why the SIP message was not verified and generated a
+         * {@code false} result for {@link #isVerified}.
+         */
+        public final int restrictedReason;
+
+        /**
+         * Communicates a verified result of success. Use {@link #SUCCESS} instead.
+         */
+        private VerificationResult() {
+            isVerified = true;
+            restrictedReason = SipDelegateManager.MESSAGE_FAILURE_REASON_UNKNOWN;
+        }
+
+        /**
+         * The result of verifying that the SIP Message should be sent.
+         * @param reason The reason associated with why the SIP message was not verified and
+         *               generated a {@code false} result for {@link #isVerified}.
+         */
+        VerificationResult(@SipDelegateManager.MessageFailureReason int reason) {
+            isVerified = false;
+            restrictedReason = reason;
+        }
+    }
+
+    // SipDelegateConnection(IMS Application) -> SipDelegate(ImsService)
+    private final ISipDelegate.Stub mSipDelegateConnection = new ISipDelegate.Stub() {
+        /**
+         * The IMS application is acknowledging that it has successfully received and processed an
+         * incoming SIP message sent by the SipDelegate in
+         * {@link ISipDelegateMessageCallback#onMessageReceived(SipMessage)}.
+         */
+        @Override
+        public void notifyMessageReceived(String viaTransactionId) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    if (mSipDelegate == null) {
+                        logw("notifyMessageReceived called when SipDelegate is not associated for "
+                                + "transaction id: " + viaTransactionId);
+                        return;
+                    }
+                    try {
+                        // TODO track the SIP Dialogs created/destroyed on the associated
+                        // SipDelegate.
+                        mSipDelegate.notifyMessageReceived(viaTransactionId);
+                    } catch (RemoteException e) {
+                        logw("SipDelegate not available when notifyMessageReceived was called "
+                                + "for transaction id: " + viaTransactionId);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * The IMS application is acknowledging that it received an incoming SIP message sent by the
+         * SipDelegate in {@link ISipDelegateMessageCallback#onMessageReceived(SipMessage)} but it
+         * was unable to process it.
+         */
+        @Override
+        public void notifyMessageReceiveError(String viaTransactionId, int reason) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    if (mSipDelegate == null) {
+                        logw("notifyMessageReceiveError called when SipDelegate is not associated "
+                                + "for transaction id: " + viaTransactionId);
+                        return;
+                    }
+                    try {
+                        // TODO track the SIP Dialogs created/destroyed on the associated
+                        // SipDelegate.
+                        mSipDelegate.notifyMessageReceiveError(viaTransactionId, reason);
+                    } catch (RemoteException e) {
+                        logw("SipDelegate not available when notifyMessageReceiveError was called "
+                                + "for transaction id: " + viaTransactionId);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * The IMS application is sending an outgoing SIP message to the SipDelegate to be processed
+         * and sent over the network.
+         */
+        @Override
+        public void sendMessage(SipMessage sipMessage, long configVersion) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    VerificationResult result = verifyOutgoingMessage(sipMessage);
+                    if (!result.isVerified) {
+                        notifyDelegateSendError("Outgoing messages restricted", sipMessage,
+                                result.restrictedReason);
+                        return;
+                    }
+                    try {
+                        // TODO track the SIP Dialogs created/destroyed on the associated
+                        // SipDelegate.
+                        mSipDelegate.sendMessage(sipMessage, configVersion);
+                        logi("sendMessage: message sent - " + sipMessage + ", configVersion: "
+                                + configVersion);
+                    } catch (RemoteException e) {
+                        notifyDelegateSendError("RemoteException: " + e, sipMessage,
+                                SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * The SipDelegateConnection is requesting that the resources associated with an ongoing SIP
+         * dialog be released as the SIP dialog is now closed.
+         */
+        @Override
+        public void closeDialog(String callId) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    if (mSipDelegate == null) {
+                        logw("closeDialog called when SipDelegate is not associated, callId: "
+                                + callId);
+                        return;
+                    }
+                    try {
+                        // TODO track the SIP Dialogs created/destroyed on the associated
+                        // SipDelegate.
+                        mSipDelegate.closeDialog(callId);
+                    } catch (RemoteException e) {
+                        logw("SipDelegate not available when closeDialog was called "
+                                + "for call id: " + callId);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    };
+
+    // SipDelegate(ImsService) -> SipDelegateConnection(IMS Application)
+    private final ISipDelegateMessageCallback.Stub mDelegateConnectionMessageCallback =
+            new ISipDelegateMessageCallback.Stub() {
+        /**
+         * An Incoming SIP Message has been received by the SipDelegate and is being routed
+         * to the IMS application for processing.
+         * <p>
+         * IMS application will call {@link ISipDelegate#notifyMessageReceived(String)} to
+         * acknowledge receipt of this incoming message.
+         */
+        @Override
+        public void onMessageReceived(SipMessage message) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    VerificationResult result = verifyIncomingMessage(message);
+                    if (!result.isVerified) {
+                        notifyAppReceiveError("Incoming messages restricted", message,
+                                result.restrictedReason);
+                        return;
+                    }
+                    try {
+                        // TODO track the SIP Dialogs created/destroyed on the associated
+                        //  SipDelegate.
+                        mAppCallback.onMessageReceived(message);
+                        logi("onMessageReceived: received " + message);
+                    } catch (RemoteException e) {
+                        notifyAppReceiveError("RemoteException: " + e, message,
+                                SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * An outgoing SIP message sent previously by the SipDelegateConnection to the SipDelegate
+         * using {@link ISipDelegate#sendMessage(SipMessage, int)} as been successfully sent.
+         */
+        @Override
+        public void onMessageSent(String viaTransactionId) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    if (mSipDelegate == null) {
+                        logw("Unexpected state, onMessageSent called when SipDelegate is not "
+                                + "associated");
+                    }
+                    try {
+                        mAppCallback.onMessageSent(viaTransactionId);
+                    } catch (RemoteException e) {
+                        logw("Error sending onMessageSent to SipDelegateConnection, remote not"
+                                + "available for transaction ID: " + viaTransactionId);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * An outgoing SIP message sent previously by the SipDelegateConnection to the SipDelegate
+         * using {@link ISipDelegate#sendMessage(SipMessage, int)} failed to be sent.
+         */
+        @Override
+        public void onMessageSendFailure(String viaTransactionId, int reason) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> {
+                    if (mSipDelegate == null) {
+                        logw("Unexpected state, onMessageSendFailure called when SipDelegate is not"
+                                + "associated");
+                    }
+                    try {
+                        mAppCallback.onMessageSendFailure(viaTransactionId, reason);
+                    } catch (RemoteException e) {
+                        logw("Error sending onMessageSendFailure to SipDelegateConnection, remote"
+                                + " not available for transaction ID: " + viaTransactionId);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    };
+
+    private final ISipDelegateMessageCallback mAppCallback;
+    private final Executor mExecutor;
+    private final int mSubId;
+    private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+    private ISipDelegate mSipDelegate;
+    private Consumer<Boolean> mPendingClosedConsumer;
+    private int mDelegateClosingReason = -1;
+    private int mDelegateClosedReason = -1;
+
+    public MessageTransportStateTracker(int subId, Executor executor,
+            ISipDelegateMessageCallback appMessageCallback) {
+        mSubId = subId;
+        mAppCallback = appMessageCallback;
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
+        // TODO: integrate registration changes to SipMessage verification checks.
+    }
+
+    @Override
+    public void onImsConfigurationChanged(SipDelegateImsConfiguration config) {
+        // Not needed for this Tracker
+    }
+
+    /**
+     * Open the transport and allow SIP messages to be sent/received on the delegate specified.
+     * @param delegate The delegate connection to send SIP messages to on the ImsService.
+     * @param deniedFeatureTags Feature tags that have been denied. Outgoing SIP messages relating
+     *         to these tags will be denied.
+     */
+    public void openTransport(ISipDelegate delegate, Set<FeatureTagState> deniedFeatureTags) {
+        mSipDelegate = delegate;
+        mDelegateClosingReason = -1;
+        mDelegateClosedReason = -1;
+        // TODO: integrate denied tags to SipMessage verification checks.
+    }
+
+    /** Dump state about this tracker that should be included in the dumpsys */
+    public void dump(PrintWriter printWriter) {
+        printWriter.println("Most recent logs:");
+        mLocalLog.dump(printWriter);
+    }
+
+    /**
+     * @return SipDelegate implementation to be sent to IMS application.
+     */
+    public ISipDelegate getDelegateConnection() {
+        return mSipDelegateConnection;
+    }
+
+    /**
+     * @return MessageCallback implementation to be sent to the ImsService.
+     */
+    public ISipDelegateMessageCallback getMessageCallback() {
+        return mDelegateConnectionMessageCallback;
+    }
+
+    /**
+     * Gradually close all SIP Dialogs by:
+     * 1) denying all new outgoing SIP Dialog requests with the reason specified and
+     * 2) only allowing existing SIP Dialogs to continue.
+     * <p>
+     * This will allow traffic to continue on existing SIP Dialogs until a BYE is sent and the
+     * SIP Dialogs are closed or a timeout is hit and {@link SipDelegate#closeDialog(String)} is
+     * forcefully called on all open SIP Dialogs.
+     * <p>
+     * Any outgoing out-of-dialog traffic on this transport will be denied with the provided reason.
+     * <p>
+     * Incoming out-of-dialog traffic will continue to be set up until the SipDelegate is fully
+     * closed.
+     * @param delegateClosingReason The reason code to return to
+     * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} if a new out-of-dialog SIP
+     *         message is received while waiting for existing Dialogs.
+     * @param closedReason reason to return to new outgoing SIP messages via
+     *         {@link SipDelegate#notifyMessageReceiveError(String, int)} once the transport
+     *         transitions to the fully closed state.
+     * @param resultConsumer The consumer called when the message transport has been closed. It will
+     *         return {@code true} if the procedure completed successfully or {@link false} if the
+     *         transport needed to be closed forcefully due to the application not responding before
+     *         a timeout occurred.
+     */
+    public void closeGracefully(int delegateClosingReason, int closedReason,
+            Consumer<Boolean> resultConsumer) {
+        mDelegateClosingReason = delegateClosingReason;
+        mPendingClosedConsumer = resultConsumer;
+        mExecutor.execute(() -> {
+            // TODO: Track SIP Dialogs and complete when there are no SIP dialogs open anymore or
+            //  the timeout occurs.
+            mPendingClosedConsumer.accept(true);
+            mPendingClosedConsumer = null;
+            closeTransport(closedReason);
+        });
+    }
+
+    /**
+     * Close all ongoing SIP Dialogs immediately and respond to any incoming/outgoing messages with
+     * the provided reason.
+     * @param closedReason The failure reason to provide to incoming/outgoing SIP messages
+     *         if an attempt is made to send/receive a message after this method is called.
+     */
+    public void close(int closedReason) {
+        closeTransport(closedReason);
+    }
+
+    // Clean up all state related to the existing SipDelegate immediately.
+    private void closeTransport(int closedReason) {
+        // TODO: add logic to forcefully close open SIP dialogs once they are being tracked.
+        mSipDelegate = null;
+        if (mPendingClosedConsumer != null) {
+            mExecutor.execute(() -> {
+                logw("closeTransport: transport close forced with pending consumer.");
+                mPendingClosedConsumer.accept(false /*closedGracefully*/);
+                mPendingClosedConsumer = null;
+            });
+        }
+        mDelegateClosingReason = -1;
+        mDelegateClosedReason = closedReason;
+    }
+
+    private VerificationResult verifyOutgoingMessage(SipMessage message) {
+        if (mDelegateClosingReason > -1) {
+            return new VerificationResult(mDelegateClosingReason);
+        }
+        if (mDelegateClosedReason > -1) {
+            return new VerificationResult(mDelegateClosedReason);
+        }
+        if (mSipDelegate == null) {
+            logw("sendMessage called when SipDelegate is not associated." + message);
+            return new VerificationResult(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+        }
+        return VerificationResult.SUCCESS;
+    }
+
+    private VerificationResult verifyIncomingMessage(SipMessage message) {
+        // Do not restrict incoming based on closing reason.
+        if (mDelegateClosedReason > -1) {
+            return new VerificationResult(mDelegateClosedReason);
+        }
+        return VerificationResult.SUCCESS;
+    }
+
+    private void notifyDelegateSendError(String logReason, SipMessage message, int reasonCode) {
+        // TODO parse SipMessage header for viaTransactionId.
+        logw("Error sending SipMessage[id: " + null + ", code: " + reasonCode + "] -> SipDelegate "
+                + "for reason: " + logReason);
+        try {
+            mAppCallback.onMessageSendFailure(null, reasonCode);
+        } catch (RemoteException e) {
+            logw("notifyDelegateSendError, SipDelegate is not available: " + e);
+        }
+    }
+
+    private void notifyAppReceiveError(String logReason, SipMessage message, int reasonCode) {
+        // TODO parse SipMessage header for viaTransactionId.
+        logw("Error sending SipMessage[id: " + null + ", code: " + reasonCode + "] -> "
+                + "SipDelegateConnection for reason: " + logReason);
+        try {
+            mSipDelegate.notifyMessageReceiveError(null, reasonCode);
+        } catch (RemoteException e) {
+            logw("notifyAppReceiveError, SipDelegate is not available: " + e);
+        }
+    }
+
+    private void logi(String log) {
+        Log.w(SipTransportController.LOG_TAG, TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[I] " + log);
+    }
+
+    private void logw(String log) {
+        Log.w(SipTransportController.LOG_TAG, TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[W] " + log);
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/RcsFeatureController.java b/src/com/android/services/telephony/rcs/RcsFeatureController.java
index 5094c57..304a74d 100644
--- a/src/com/android/services/telephony/rcs/RcsFeatureController.java
+++ b/src/com/android/services/telephony/rcs/RcsFeatureController.java
@@ -30,7 +30,7 @@
 import android.util.Log;
 
 import com.android.ims.FeatureConnector;
-import com.android.ims.IFeatureConnector;
+import com.android.ims.FeatureUpdates;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
@@ -74,19 +74,25 @@
          * Called when the feature should be destroyed.
          */
         void onDestroy();
+
+        /**
+         * Called when a dumpsys is being generated for this RcsFeatureController for all Features
+         * to report their status.
+         */
+        void dump(PrintWriter pw);
     }
 
     /**
      * Used to inject FeatureConnector instances for testing.
      */
     @VisibleForTesting
-    public interface FeatureConnectorFactory<T extends IFeatureConnector> {
+    public interface FeatureConnectorFactory<U extends FeatureUpdates> {
         /**
-         * @return a {@link FeatureConnector} associated for the given {@link IFeatureConnector}
-         * and slot id.
+         * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates}
+         * and slot index.
          */
-        FeatureConnector<T> create(Context context, int slotId,
-                FeatureConnector.Listener<T> listener, Executor executor, String tag);
+        FeatureConnector<U> create(Context context, int slotIndex,
+                FeatureConnector.Listener<U> listener, Executor executor, String logPrefix);
     }
 
     /**
@@ -102,7 +108,8 @@
                 ImsRegistrationCallbackHelper.ImsRegistrationUpdate cb, Executor executor);
     }
 
-    private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory = FeatureConnector::new;
+    private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory =
+            RcsFeatureManager::getConnector;
     private RegistrationHelperFactory mRegistrationHelperFactory =
             ImsRegistrationCallbackHelper::new;
 
@@ -117,11 +124,6 @@
     private FeatureConnector.Listener<RcsFeatureManager> mFeatureConnectorListener =
             new FeatureConnector.Listener<RcsFeatureManager>() {
                 @Override
-                public RcsFeatureManager getFeatureManager() {
-                    return new RcsFeatureManager(mContext, mSlotId);
-                }
-
-                @Override
                 public void connectionReady(RcsFeatureManager manager)
                         throws com.android.ims.ImsException {
                     if (manager == null) {
@@ -131,17 +133,21 @@
                     try {
                         // May throw ImsException if for some reason the connection to the
                         // ImsService is gone.
+                        updateConnectionStatus(manager);
                         setupConnectionToService(manager);
                     } catch (ImsException e) {
+                        updateConnectionStatus(null /*manager*/);
                         // Use deprecated Exception for compatibility.
                         throw new com.android.ims.ImsException(e.getMessage(),
                                 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
                     }
-                    updateConnectionStatus(manager);
                 }
 
                 @Override
-                public void connectionUnavailable() {
+                public void connectionUnavailable(int reason) {
+                    if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
+                        loge("unexpected - connectionUnavailable due to server unavailable");
+                    }
                     // Call before disabling connection to manager.
                     removeConnectionToService();
                     updateConnectionStatus(null /*manager*/);
@@ -280,7 +286,7 @@
     }
 
     @VisibleForTesting
-    public void setFeatureConnectorFactory(FeatureConnectorFactory factory) {
+    public void setFeatureConnectorFactory(FeatureConnectorFactory<RcsFeatureManager> factory) {
         mFeatureFactory = factory;
     }
 
@@ -427,6 +433,14 @@
         pw.print("connected=");
         synchronized (mLock) {
             pw.println(mFeatureManager != null);
+            pw.println();
+            pw.println("RcsFeatureControllers:");
+            pw.increaseIndent();
+            for (Feature f : mFeatures.values()) {
+                f.dump(pw);
+                pw.println();
+            }
+            pw.decreaseIndent();
         }
     }
 
@@ -434,6 +448,10 @@
         Log.w(LOG_TAG, getLogPrefix().append(log).toString());
     }
 
+    private void loge(String log) {
+        Log.e(LOG_TAG, getLogPrefix().append(log).toString());
+    }
+
     private StringBuilder getLogPrefix() {
         StringBuilder sb = new StringBuilder("[");
         sb.append(mSlotId);
diff --git a/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java b/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java
new file mode 100644
index 0000000..3f6f269
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Container for the active connection to the {@link SipDelegate} active on the ImsService.
+ * <p>
+ * New instances of this class will be created and destroyed new {@link SipDelegate}s are created
+ * and destroyed by the {@link SipDelegateController}.
+ */
+public class SipDelegateBinderConnection implements DelegateBinderStateManager,
+        IBinder.DeathRecipient {
+    private static final String LOG_TAG = "BinderConn";
+
+    protected final int mSubId;
+    protected final Set<FeatureTagState> mDeniedTags;
+    protected final Executor mExecutor;
+    protected final List<StateCallback> mStateCallbacks;
+
+    private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+    // Callback interface from ImsService to this Connection. State Events will be forwarded to IMS
+    // application through DelegateStateTracker.
+    private final ISipDelegateStateCallback mSipDelegateStateCallback =
+            new ISipDelegateStateCallback.Stub() {
+                @Override
+                public void onCreated(ISipDelegate delegate,
+                        List<FeatureTagState> deniedFeatureTags) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() ->
+                                notifySipDelegateCreated(delegate, deniedFeatureTags));
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
+                public void onFeatureTagRegistrationChanged(
+                        DelegateRegistrationState registrationState) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() -> {
+                            logi("onFeatureTagRegistrationChanged:" + registrationState);
+                            for (StateCallback c : mStateCallbacks) {
+                                c.onRegistrationStateChanged(registrationState);
+                            }
+                        });
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
+                public void onImsConfigurationChanged(
+                        SipDelegateImsConfiguration registeredSipConfig) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() -> {
+                            logi("onImsConfigurationChanged");
+                            for (StateCallback c : mStateCallbacks) {
+                                c.onImsConfigurationChanged(registeredSipConfig);
+                            }
+                        });
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
+                public void onDestroyed(int reason) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            };
+
+    private final ISipTransport mSipTransport;
+    private final IImsRegistration mImsRegistration;
+    private final DelegateRequest mRequestedConfig;
+
+    private ISipDelegate mDelegateBinder;
+    private BiConsumer<ISipDelegate, Set<FeatureTagState>> mPendingCreatedConsumer;
+    private Consumer<Integer> mPendingDestroyedConsumer;
+
+    /**
+     * Create a new Connection object to manage the creation and destruction of a
+     * {@link SipDelegate}.
+     * @param subId The subid that this SipDelegate is being created for.
+     * @param sipTransport The SipTransport implementation that will be used to manage SipDelegates.
+     * @param registrationImpl The ImsRegistration implementation that will be used to manage
+     *                         registration changes in relation to the SipDelegates.
+     * @param requestedConfig The DelegateRequest to be sent to the ImsService.
+     * @param transportDeniedTags The feature tags that have already been denied by the
+     *                            SipTransportController and should not be requested.
+     * @param executor The Executor that all binder calls from the remote process will be executed
+     *                on.
+     * @param stateCallbacks A list of callbacks that will each be called when the state of the
+     *                       SipDelegate changes. This will be called on the supplied executor.
+     */
+    public SipDelegateBinderConnection(int subId, ISipTransport sipTransport,
+            IImsRegistration registrationImpl, DelegateRequest requestedConfig,
+            Set<FeatureTagState> transportDeniedTags, Executor executor,
+            List<StateCallback> stateCallbacks) {
+        mSubId = subId;
+        mSipTransport = sipTransport;
+        mImsRegistration = registrationImpl;
+        mRequestedConfig = requestedConfig;
+        mDeniedTags = transportDeniedTags;
+        mExecutor = executor;
+        mStateCallbacks = stateCallbacks;
+    }
+
+    @Override
+    public boolean create(ISipDelegateMessageCallback cb,
+            BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) {
+        try {
+            mSipTransport.createSipDelegate(mSubId, mRequestedConfig, mSipDelegateStateCallback,
+                    cb);
+            mSipTransport.asBinder().linkToDeath(this, 0);
+        } catch (RemoteException e) {
+            logw("create called on unreachable SipTransport:" + e);
+            return false;
+        }
+        mPendingCreatedConsumer = createdConsumer;
+        return true;
+    }
+
+    @Override
+    public void destroy(int reason, Consumer<Integer> destroyedConsumer) {
+        mPendingDestroyedConsumer = destroyedConsumer;
+        try {
+            if (mDelegateBinder != null) {
+                mSipTransport.destroySipDelegate(mDelegateBinder, reason);
+            } else {
+                mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+            }
+            mStateCallbacks.clear();
+        } catch (RemoteException e) {
+            logw("destroy called on unreachable SipTransport:" + e);
+            mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+        }
+        try {
+            mSipTransport.asBinder().unlinkToDeath(this, 0);
+        } catch (NoSuchElementException e) {
+            logw("unlinkToDeath called on already unlinked binder" + e);
+        }
+    }
+
+    @Override
+    public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
+        try {
+            mImsRegistration.triggerFullNetworkRegistration(sipCode, sipReason);
+        } catch (RemoteException e) {
+            logw("triggerFullNetworkRegistration called on unreachable ImsRegistration:" + e);
+        }
+    }
+
+    private void notifySipDelegateCreated(ISipDelegate delegate,
+            List<FeatureTagState> deniedFeatureTags) {
+        logi("Delegate Created: " + delegate + ", deniedTags:" + deniedFeatureTags);
+        if (delegate == null) {
+            logw("Invalid null delegate returned!");
+        }
+        mDelegateBinder = delegate;
+        // Add denied feature tags from SipDelegate to the ones denied by the transport
+        if (deniedFeatureTags != null) {
+            mDeniedTags.addAll(deniedFeatureTags);
+        }
+        if (mPendingCreatedConsumer == null) return;
+        mPendingCreatedConsumer.accept(delegate, mDeniedTags);
+        mPendingCreatedConsumer = null;
+    }
+
+    private void notifySipDelegateDestroyed(int reason) {
+        logi("Delegate Destroyed, reason: " + reason);
+        mDelegateBinder = null;
+        if (mPendingDestroyedConsumer == null) return;
+        mPendingDestroyedConsumer.accept(reason);
+        mPendingDestroyedConsumer = null;
+    }
+
+    /** Dump state about this binder connection that should be included in the dumpsys. */
+    public void dump(PrintWriter printWriter) {
+        mLocalLog.dump(printWriter);
+    }
+
+    protected final void logi(String log) {
+        Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[I] " + log);
+    }
+
+    protected final void logw(String log) {
+        Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[W] " + log);
+    }
+
+    @Override
+    public void binderDied() {
+        mExecutor.execute(() -> {
+            logw("binderDied!");
+            // Unblock any pending create/destroy operations.
+            // SipTransportController will handle the overall destruction/teardown.
+            notifySipDelegateCreated(null, Collections.emptyList());
+            notifySipDelegateDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+        });
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java b/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java
new file mode 100644
index 0000000..ef12eb8
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.stub.SipDelegate;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Stub implementation used when a SipDelegate needs to be set up in specific cases, but there
+ * is no underlying implementation in the ImsService.
+ *
+ * This is used in cases where all of the requested feature tags were denied for various reasons
+ * from the SipTransportController. In this case, we will "connect", send a update to include the
+ * denied feature tags, and then do nothing until this stub is torn down.
+ */
+public class SipDelegateBinderConnectionStub implements DelegateBinderStateManager {
+    protected final Set<FeatureTagState> mDeniedTags;
+    protected final Executor mExecutor;
+    protected final List<StateCallback> mStateCallbacks;
+
+    /**
+     * Create a new Connection object to manage the creation and destruction of a
+     * {@link SipDelegate}.
+     * @param transportDeniedTags The feature tags that have already been denied by the
+     *                            SipTransportController and should not be requested.
+     * @param executor The Executor that all binder calls from the remote process will be executed
+     *                on.
+     * @param stateCallbacks A list of callbacks that will each be called when the state of the
+     *                       SipDelegate changes. This will be called on the supplied executor.
+     */
+    public SipDelegateBinderConnectionStub(Set<FeatureTagState> transportDeniedTags,
+            Executor executor, List<StateCallback> stateCallbacks) {
+        mDeniedTags = transportDeniedTags;
+        mExecutor = executor;
+        mStateCallbacks = stateCallbacks;
+    }
+
+    @Override
+    public boolean create(ISipDelegateMessageCallback cb,
+            BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) {
+        mExecutor.execute(() -> {
+            createdConsumer.accept(null, (mDeniedTags));
+            for (SipDelegateBinderConnection.StateCallback  c: mStateCallbacks) {
+                c.onRegistrationStateChanged(new DelegateRegistrationState.Builder().build());
+            }
+        });
+        return true;
+    }
+
+    @Override
+    public void destroy(int reason, Consumer<Integer> destroyedConsumer) {
+        mExecutor.execute(() -> {
+            mStateCallbacks.clear();
+            destroyedConsumer.accept(reason);
+        });
+    }
+
+    @Override
+    public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
+        // This stub is not connected to an ImsService, so this method is intentionally not
+        // implemented.
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/SipDelegateController.java b/src/com/android/services/telephony/rcs/SipDelegateController.java
new file mode 100644
index 0000000..2d6d4f0
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateController.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * Created when an IMS application wishes to open up a {@link SipDelegateConnection} and manages the
+ * resulting {@link SipDelegate} that may be created on the ImsService side.
+ */
+public class SipDelegateController {
+    static final String LOG_TAG = "SipDelegateC";
+
+    private class BinderConnectionFactory implements DelegateBinderStateManager.Factory {
+
+        private final ISipTransport mSipTransportImpl;
+        private final IImsRegistration mImsRegistrationImpl;
+
+        BinderConnectionFactory(ISipTransport transport, IImsRegistration registration) {
+            mSipTransportImpl = transport;
+            mImsRegistrationImpl = registration;
+        }
+
+        @Override
+        public DelegateBinderStateManager create(int subId,
+                DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags,
+                Executor executor, List<DelegateBinderStateManager.StateCallback> stateCallbacks) {
+            // We should not actually create a SipDelegate in this case.
+            if (requestedConfig.getFeatureTags().isEmpty()) {
+                return new SipDelegateBinderConnectionStub(transportDeniedTags, executor,
+                        stateCallbacks);
+            }
+            return new SipDelegateBinderConnection(mSubId, mSipTransportImpl, mImsRegistrationImpl,
+                    requestedConfig, transportDeniedTags, mExecutorService, stateCallbacks);
+        }
+    }
+
+    private final int mSubId;
+    private final String mPackageName;
+    private final DelegateRequest mInitialRequest;
+    private final ScheduledExecutorService mExecutorService;
+    private final MessageTransportStateTracker mMessageTransportStateTracker;
+    private final DelegateStateTracker mDelegateStateTracker;
+    private final DelegateBinderStateManager.Factory mBinderConnectionFactory;
+    private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+    private DelegateBinderStateManager mBinderConnection;
+    private Set<String> mTrackedFeatureTags;
+
+    public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
+            ISipTransport transportImpl, IImsRegistration registrationImpl,
+            ScheduledExecutorService executorService,
+            ISipDelegateConnectionStateCallback stateCallback,
+            ISipDelegateMessageCallback messageCallback) {
+        mSubId = subId;
+        mPackageName = packageName;
+        mInitialRequest = initialRequest;
+        mExecutorService = executorService;
+        mBinderConnectionFactory = new BinderConnectionFactory(transportImpl, registrationImpl);
+
+        mMessageTransportStateTracker = new MessageTransportStateTracker(mSubId, executorService,
+                messageCallback);
+        mDelegateStateTracker = new DelegateStateTracker(mSubId, stateCallback,
+                mMessageTransportStateTracker.getDelegateConnection());
+    }
+
+    /**
+     * Inject dependencies for testing only.
+     */
+    @VisibleForTesting
+    public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
+            ScheduledExecutorService executorService,
+            MessageTransportStateTracker messageTransportStateTracker,
+            DelegateStateTracker delegateStateTracker,
+            DelegateBinderStateManager.Factory connectionFactory) {
+        mSubId = subId;
+        mInitialRequest = initialRequest;
+        mPackageName = packageName;
+        mExecutorService = executorService;
+        mMessageTransportStateTracker = messageTransportStateTracker;
+        mDelegateStateTracker = delegateStateTracker;
+        mBinderConnectionFactory = connectionFactory;
+    }
+
+    /**
+     * @return The InitialRequest from the IMS application. The feature tags that are actually set
+     * up may differ from this request based on the state of this controller.
+     */
+    public DelegateRequest getInitialRequest() {
+        return mInitialRequest;
+    }
+
+    /**
+     * @return The package name of the IMS application associated with this SipDelegateController.
+     */
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public ISipDelegate getSipDelegateInterface() {
+        return mMessageTransportStateTracker.getDelegateConnection();
+    }
+
+    /**
+     * Create the underlying SipDelegate.
+     * <p>
+     * This may not happen instantly, The CompletableFuture returned will not complete until
+     * {@link DelegateConnectionStateCallback#onCreated(SipDelegateConnection)} is called by the
+     * SipDelegate or DelegateStateTracker state is updated in the case that all requested features
+     * were denied.
+     * @return A CompletableFuture that will complete once the SipDelegate has been created. If true
+     * is returned, the SipDelegate has been created successfully. If false, the ImsService is not
+     * reachable and the process should be aborted.
+     */
+    public CompletableFuture<Boolean> create(Set<String> supportedSet,
+            Set<FeatureTagState> deniedSet) {
+        logi("create, supported: " + supportedSet + ", denied: " + deniedSet);
+        mTrackedFeatureTags = supportedSet;
+        DelegateBinderStateManager connection =
+                createBinderConnection(supportedSet, deniedSet);
+        CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> pendingCreate =
+                createSipDelegate(connection);
+        // May need to implement special case handling where SipDelegate denies all in supportedSet,
+        // however that should be a very rare case. For now, if that happens, just keep the
+        // SipDelegate bound.
+        // use thenApply here because we need this to happen on the same thread that it was called
+        // on in order to ensure ordering of onCreated being called, followed by registration
+        // state changed. If not, this is subject to race conditions where registered is queued
+        // before the async processing of this future.
+        return pendingCreate.thenApply((resultPair) -> {
+            if (resultPair == null) {
+                logw("create: resultPair returned null");
+                return false;
+            }
+            mBinderConnection = connection;
+            logi("create: created, delegate denied: " + resultPair.second);
+            mMessageTransportStateTracker.openTransport(resultPair.first, resultPair.second);
+            mDelegateStateTracker.sipDelegateConnected(resultPair.second);
+            return true;
+        });
+    }
+
+    /**
+     * Modify the SipTransport to reflect the new Feature Tag set that the IMS application has
+     * access to.
+     * <p>
+     * This involves the following operations if the new supported tag set does not match the
+     * the existing set:
+     * 1) destroy the existing underlying SipDelegate. If there are SIP Dialogs that are active
+     * on the SipDelegate that is pending to be destroyed, we must move the feature tags into a
+     * deregistering state via
+     * {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} to signal to the
+     * IMS application to close all dialogs before the operation can proceed. If any outgoing
+     * out-of-dialog messages are sent at this time, they will also fail with reason
+     * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION}.
+     * 2) create a new underlying SipDelegate and notify trackers, allowing the transport to
+     * re-open.
+     * @param newSupportedSet The new supported set of feature tags that the SipDelegate should
+     *     be opened for.
+     * @param deniedSet The new set of tags that have been denied as well as the reason for the
+     *        denial to be reported back to the IMS Application.
+     * @return A CompletableFuture containing the pending operation that will change the supported
+     * feature tags. Any operations to change the supported feature tags of the associated
+     * SipDelegate after this should not happen until this pending operation completes. Will
+     * complete with {@code true} if the operation was successful or {@code false} if the
+     * IMS service was unreachable.
+     */
+    public CompletableFuture<Boolean> changeSupportedFeatureTags(Set<String> newSupportedSet,
+            Set<FeatureTagState> deniedSet) {
+        logi("Received feature tag set change, old: [" + mTrackedFeatureTags + "], new: "
+                + newSupportedSet + ",denied: [" + deniedSet + "]");
+        if (mTrackedFeatureTags != null && mTrackedFeatureTags.equals(newSupportedSet)) {
+            logi("changeSupportedFeatureTags: no change, returning");
+            return CompletableFuture.completedFuture(true);
+        }
+
+        mTrackedFeatureTags = newSupportedSet;
+        // Next perform the destroy operation.
+        CompletableFuture<Integer> pendingDestroy = destroySipDelegate(false/*force*/,
+                SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+                SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+                DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+        // Next perform the create operation with the new set of supported feature tags.
+        return pendingDestroy.thenComposeAsync((reasonFromService) -> {
+            logi("changeSupportedFeatureTags: destroy stage complete, reason reported: "
+                    + reasonFromService);
+            return create(newSupportedSet, deniedSet);
+        }, mExecutorService);
+    }
+
+    /**
+     * Destroy this SipDelegate. This controller should be disposed of after this method is
+     * called.
+     * <p>
+     * This may not happen instantly if there are SIP Dialogs that are active on this SipDelegate.
+     * In this case, the CompletableFuture will not complete until
+     * {@link DelegateConnectionStateCallback#onDestroyed(int)} is called by the SipDelegate.
+     * @param force If set true, we will close the transport immediately and call
+     * {@link SipDelegate#closeDialog(String)} on any open dialogs. If false, we will wait for the
+     *         SIP Dialogs to close or the close timer to timeout before destroying the underlying
+     *         SipDelegate.
+     * @param destroyReason The reason for why this SipDelegate is being destroyed.
+     * @return A CompletableFuture that will complete once the SipDelegate has been destroyed.
+     */
+    public CompletableFuture<Integer> destroy(boolean force, int destroyReason) {
+        logi("destroy, forced " + force + ", destroyReason: " + destroyReason);
+
+        CompletableFuture<Integer> pendingOperationComplete =
+                destroySipDelegate(force, SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+                        getMessageFailReasonFromDestroyReason(destroyReason),
+                        DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING,
+                        destroyReason);
+        return pendingOperationComplete.thenApplyAsync((reasonFromDelegate) -> {
+            logi("destroy, operation complete, notifying trackers, reason" + reasonFromDelegate);
+            mDelegateStateTracker.sipDelegateDestroyed(reasonFromDelegate);
+            return reasonFromDelegate;
+        }, mExecutorService);
+    };
+
+    /**
+     * The IMS application is notifying the ImsService that it has received a response to a request
+     * that will require that the IMS registration be torn down and brought back up.
+     *<p>
+     * See {@link SipDelegateManager#triggerFullNetworkRegistration} for more information.
+     */
+    public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
+        logi("triggerFullNetworkRegistration, code=" + sipCode + ", reason=" + sipReason);
+        if (mBinderConnection != null) {
+            mBinderConnection.triggerFullNetworkRegistration(sipCode, sipReason);
+        } else {
+            logw("triggerFullNetworkRegistration called when binder connection is null");
+        }
+    }
+
+    private static int getMessageFailReasonFromDestroyReason(int destroyReason) {
+        switch (destroyReason) {
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD:
+                return SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD;
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP:
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS:
+                return SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED;
+            default:
+                return SipDelegateManager.MESSAGE_FAILURE_REASON_UNKNOWN;
+        }
+    }
+
+    /**
+     * @param force If set true, we will close the transport immediately and call
+     * {@link SipDelegate#closeDialog(String)} on any open dialogs. If false, we will wait for the
+     *         SIP Dialogs to close or the close timer to timeout before destroying the underlying
+     *         SipDelegate.
+     * @param messageDestroyingReason The reason to send back to the IMS application in the case
+     *         that a new outgoing SIP message is sent that is out-of-dialog while the message
+     *         transport is closing.
+     * @param messageDestroyedReason The reason to send back to the IMS application in the case
+     *         that a new outgoing SIP message is sent once the underlying transport is closed.
+     * @param deregisteringReason The deregistering state reported to the IMS application for all
+     *         registered feature tags.
+     * @param delegateDestroyedReason The reason to send to the underlying SipDelegate that is being
+     *         destroyed.
+     * @return A CompletableFuture containing the reason from the SipDelegate for why it was
+     * destroyed.
+     */
+    private CompletableFuture<Integer> destroySipDelegate(boolean force,
+            int messageDestroyingReason, int messageDestroyedReason, int deregisteringReason,
+            int delegateDestroyedReason) {
+        if (mBinderConnection == null) {
+            logi("destroySipDelegate, called when binder connection is already null");
+            return CompletableFuture.completedFuture(delegateDestroyedReason);
+        }
+        // First, bring down the message transport.
+        CompletableFuture<Boolean> pendingTransportClosed = new CompletableFuture<>();
+        if (force) {
+            logi("destroySipDelegate, forced");
+            mMessageTransportStateTracker.close(messageDestroyedReason);
+            pendingTransportClosed.complete(true);
+        } else {
+            mMessageTransportStateTracker.closeGracefully(messageDestroyingReason,
+                    messageDestroyedReason, pendingTransportClosed::complete);
+        }
+
+        // Do not send an intermediate pending state to app if there are no open SIP dialogs to
+        // worry about.
+        if (!pendingTransportClosed.isDone()) {
+            mDelegateStateTracker.sipDelegateChanging(deregisteringReason);
+        } else {
+            logi("destroySipDelegate, skip DEREGISTERING_REASON_DESTROY_PENDING");
+        }
+
+        // Next, destroy the SipDelegate.
+        return pendingTransportClosed.thenComposeAsync((wasGraceful) -> {
+            logi("destroySipDelegate, transport gracefully closed = " + wasGraceful);
+            CompletableFuture<Integer> pendingDestroy = new CompletableFuture<>();
+            mBinderConnection.destroy(delegateDestroyedReason, pendingDestroy::complete);
+            return pendingDestroy;
+        }, mExecutorService);
+    }
+
+    /**
+     * @return a CompletableFuture that returns a Pair containing SipDelegate Binder interface as
+     * well as rejected feature tags or a {@code null} Pair instance if the ImsService is not
+     * available.
+     */
+    private CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> createSipDelegate(
+            DelegateBinderStateManager connection) {
+        CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> createdFuture =
+                new CompletableFuture<>();
+        boolean isStarted = connection.create(mMessageTransportStateTracker.getMessageCallback(),
+                (delegate, delegateDeniedTags) ->
+                        createdFuture.complete(new Pair<>(delegate, delegateDeniedTags)));
+        if (!isStarted) {
+            logw("Couldn't create binder connection, ImsService is not available.");
+            connection.destroy(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD, null);
+            return CompletableFuture.completedFuture(null);
+        }
+        return createdFuture;
+    }
+
+    private DelegateBinderStateManager createBinderConnection(Set<String> supportedSet,
+            Set<FeatureTagState> deniedSet) {
+
+        List<DelegateBinderStateManager.StateCallback> stateCallbacks = new ArrayList<>(2);
+        stateCallbacks.add(mDelegateStateTracker);
+        stateCallbacks.add(mMessageTransportStateTracker);
+
+        return mBinderConnectionFactory.create(mSubId,
+                new DelegateRequest(supportedSet), deniedSet, mExecutorService, stateCallbacks);
+    }
+
+    /**
+     * Write the current state of this controller in String format using the PrintWriter provided
+     * for dumpsys.
+     */
+    public void dump(PrintWriter printWriter) {
+        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
+        pw.println("SipDelegateController" + "[" + mSubId + "]:");
+        pw.increaseIndent();
+        pw.println("Most recent logs:");
+        pw.increaseIndent();
+        mLocalLog.dump(pw);
+        pw.decreaseIndent();
+
+        pw.println();
+        pw.println("DelegateStateTracker:");
+        pw.increaseIndent();
+        mDelegateStateTracker.dump(pw);
+        pw.decreaseIndent();
+
+        pw.println();
+        pw.println("MessageStateTracker:");
+        pw.increaseIndent();
+        mMessageTransportStateTracker.dump(pw);
+        pw.decreaseIndent();
+
+        pw.decreaseIndent();
+    }
+
+    private void logi(String log) {
+        Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[I] " + log);
+    }
+
+    private void logw(String log) {
+        Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+        mLocalLog.log("[W] " + log);
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/SipTransportController.java b/src/com/android/services/telephony/rcs/SipTransportController.java
new file mode 100644
index 0000000..028e49f
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipTransportController.java
@@ -0,0 +1,972 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.DelegateConnectionMessageCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.LocalLog;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.ims.RcsFeatureManager;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import com.google.common.base.Objects;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * Manages the creation and destruction of SipDelegates in response to an IMS application requesting
+ * a SipDelegateConnection registered to one or more IMS feature tags.
+ * <p>
+ * This allows an IMS application to forward traffic related to those feature tags over the existing
+ * IMS registration managed by the {@link ImsService} associated with this cellular subscription
+ * instead of requiring that the IMS application manage its own IMS registration over-the-top. This
+ * is required for some cellular carriers, which mandate that all IMS SIP traffic must be sent
+ * through a single IMS registration managed by the system IMS service.
+ *
+ * //TODO: Support other roles besides SMS
+ * //TODO: Bring in carrier provisioning to influence features that can be created.
+ * //TODO: Generate registration change events.
+ */
+public class SipTransportController implements RcsFeatureController.Feature,
+        OnRoleHoldersChangedListener {
+    static final int LOG_SIZE = 50;
+    static final String LOG_TAG = "SipTransportC";
+
+    /**See {@link TimerAdapter#getReevaluateThrottleTimerMilliseconds()}.*/
+    private static final int REEVALUATE_THROTTLE_DEFAULT_MS = 1000;
+    /**See {@link TimerAdapter#getUpdateRegistrationDelayMilliseconds()}.*/
+    private static final int TRIGGER_UPDATE_REGISTRATION_DELAY_DEFAULT_MS = 1000;
+
+    /**
+     * {@link RoleManager} is final so we have to wrap the implementation for testing.
+     */
+    @VisibleForTesting
+    public interface RoleManagerAdapter {
+        /** See {@link RoleManager#getRoleHolders(String)} */
+        List<String> getRoleHolders(String roleName);
+        /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */
+        void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user);
+        /** See {@link RoleManager#removeOnRoleHoldersChangedListenerAsUser} */
+        void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user);
+    }
+
+    /**
+     * Adapter for timers related to this class so they can be modified during testing.
+     */
+    @VisibleForTesting
+    public interface TimerAdapter {
+        /**
+         * Time we will delay after a {@link #createSipDelegate} or {@link #destroySipDelegate}
+         * command to re-evaluate and apply any changes to the list of tracked
+         * SipDelegateControllers.
+         * <p>
+         * Another create/destroy request sent during this time will not postpone re-evaluation
+         * again.
+         */
+        int getReevaluateThrottleTimerMilliseconds();
+
+        /**
+         * Time after re-evaluate we will wait to trigger the update of IMS registration.
+         * <p>
+         * Another re-evaluate while waiting to trigger a registration update will cause this
+         * controller to cancel and reschedule the event again, further delaying the trigger to send
+         * a registration update.
+         */
+        int getUpdateRegistrationDelayMilliseconds();
+    }
+
+    private static class TimerAdapterImpl implements TimerAdapter {
+
+        @Override
+        public int getReevaluateThrottleTimerMilliseconds() {
+            return REEVALUATE_THROTTLE_DEFAULT_MS;
+        }
+
+        @Override
+        public int getUpdateRegistrationDelayMilliseconds() {
+            return TRIGGER_UPDATE_REGISTRATION_DELAY_DEFAULT_MS;
+        }
+    }
+
+    private static class RoleManagerAdapterImpl implements RoleManagerAdapter {
+
+        private final RoleManager mRoleManager;
+
+        private RoleManagerAdapterImpl(Context context) {
+            mRoleManager = context.getSystemService(RoleManager.class);
+        }
+
+        @Override
+        public List<String> getRoleHolders(String roleName) {
+            return mRoleManager.getRoleHolders(roleName);
+        }
+
+        @Override
+        public void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user) {
+            mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user);
+        }
+
+        @Override
+        public void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user) {
+            mRoleManager.removeOnRoleHoldersChangedListenerAsUser(listener, user);
+        }
+    }
+
+    /**
+     * Used in {@link #destroySipDelegate(int, ISipDelegate, int)} to store pending destroy
+     * requests.
+     */
+    private static final class DestroyRequest {
+        public final SipDelegateController controller;
+        public final int reason;
+
+        DestroyRequest(SipDelegateController c, int r) {
+            controller = c;
+            reason = r;
+        }
+
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            DestroyRequest that = (DestroyRequest) o;
+            return reason == that.reason
+                    && controller.equals(that.controller);
+        }
+
+        @Override
+        public int hashCode() {
+            return java.util.Objects.hash(controller, reason);
+        }
+
+        @Override
+        public String toString() {
+            return "DestroyRequest{" + "controller=" + controller + ", reason=" + reason + '}';
+        }
+    }
+
+    /**
+     * Allow the ability for tests to easily mock out the SipDelegateController for testing.
+     */
+    @VisibleForTesting
+    public interface SipDelegateControllerFactory {
+        /** See {@link SipDelegateController} */
+        SipDelegateController create(int subId, DelegateRequest initialRequest, String packageName,
+                ISipTransport sipTransportImpl,  IImsRegistration registrationImpl,
+                ScheduledExecutorService executorService,
+                ISipDelegateConnectionStateCallback stateCallback,
+                ISipDelegateMessageCallback messageCallback);
+    }
+
+    private SipDelegateControllerFactory mDelegateControllerFactory = SipDelegateController::new;
+    private final int mSlotId;
+    private final ScheduledExecutorService mExecutorService;
+    private final RoleManagerAdapter mRoleManagerAdapter;
+    private final TimerAdapter mTimerAdapter;
+    private final LocalLog mLocalLog = new LocalLog(LOG_SIZE);
+
+    // A priority queue of active SipDelegateControllers, where the oldest SipDelegate gets
+    // access to the feature tag if multiple apps are allowed to request the same feature tag.
+    private final List<SipDelegateController> mDelegatePriorityQueue = new ArrayList<>();
+    // SipDelegateControllers who have been created and are pending to be added to the priority
+    // queue. Will be added into the queue in the same order as they were added here.
+    private final List<SipDelegateController> mDelegatePendingCreate = new ArrayList<>();
+    // SipDelegateControllers that are pending to be destroyed.
+    private final List<DestroyRequest> mDelegatePendingDestroy = new ArrayList<>();
+
+    // Future scheduled for operations that require the list of SipDelegateControllers to
+    // be evaluated. When the timer expires and triggers the reevaluate method, this controller
+    // will iterate through mDelegatePriorityQueue and assign Feature Tags based on role+priority.
+    private ScheduledFuture<?> mScheduledEvaluateFuture;
+    // mPendingEvaluateFTFuture creates this CompletableFuture, exposed in order to stop other
+    // evaluates from occurring while another is waiting for a result on other threads.
+    private CompletableFuture<Void> mEvaluateCompleteFuture;
+    // Future scheduled that will trigger the ImsService to update the IMS registration for the
+    // SipDelegate configuration. Will be scheduled TRIGGER_UPDATE_REGISTRATION_DELAY_MS
+    // milliseconds after a pending evaluate completes.
+    private ScheduledFuture<?> mPendingUpdateRegistrationFuture;
+    // Subscription id will change as new subscriptions are loaded on the slot.
+    private int mSubId;
+    // Will go up/down as the ImsService associated with this slotId goes up/down.
+    private RcsFeatureManager mRcsManager;
+    // Cached package name of the app that is considered the default SMS app.
+    private String mCachedSmsRolePackageName = "";
+
+    /**
+     * Create an instance of SipTransportController.
+     * @param context The Context associated with this controller.
+     * @param slotId The slot index associated with this controller.
+     * @param subId The subscription ID associated with this controller when it was first created.
+     */
+    public SipTransportController(Context context, int slotId, int subId) {
+        mSlotId = slotId;
+        mSubId = subId;
+
+        mRoleManagerAdapter = new RoleManagerAdapterImpl(context);
+        mTimerAdapter = new TimerAdapterImpl();
+        mExecutorService = Executors.newSingleThreadScheduledExecutor();
+    }
+
+    /**
+     * Constructor to inject dependencies for testing.
+     */
+    @VisibleForTesting
+    public SipTransportController(Context context, int slotId, int subId,
+            SipDelegateControllerFactory delegateFactory, RoleManagerAdapter roleManagerAdapter,
+            TimerAdapter timerAdapter, ScheduledExecutorService executor) {
+        mSlotId = slotId;
+        mSubId = subId;
+
+        mRoleManagerAdapter = roleManagerAdapter;
+        mTimerAdapter = timerAdapter;
+        mDelegateControllerFactory = delegateFactory;
+        mExecutorService = executor;
+        logi("created");
+    }
+
+    @Override
+    public void onRcsConnected(RcsFeatureManager manager) {
+        mExecutorService.submit(() -> onRcsManagerChanged(manager));
+    }
+
+    @Override
+    public void onRcsDisconnected() {
+        mExecutorService.submit(() -> onRcsManagerChanged(null));
+    }
+
+    @Override
+    public void onAssociatedSubscriptionUpdated(int subId) {
+        mExecutorService.submit(()-> onSubIdChanged(subId));
+    }
+
+    @Override
+    public void onDestroy() {
+        mExecutorService.submit(()-> {
+            // Ensure new create/destroy requests are denied.
+            mSubId = -1;
+            triggerDeregistrationEvent();
+            scheduleDestroyDelegates(
+                    SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN)
+                    .thenRun(mExecutorService::shutdown);
+        });
+    }
+
+    /**
+     * Optionally create a new {@link SipDelegate} based off of the {@link DelegateRequest} given
+     * based on the state of this controller and associate it with the given callbacks.
+     * <p>
+     * Once the {@link SipDelegate} has been created,
+     * {@link ISipDelegateConnectionStateCallback#onCreated(ISipDelegate)} must be called with
+     * the AIDL instance corresponding to the remote {@link SipDelegate}.
+     * @param subId the subId associated with the request.
+     * @param request The request parameters used to create the {@link SipDelegate}.
+     * @param delegateState The {@link DelegateConnectionStateCallback} Binder connection.
+     * @param delegateMessage The {@link DelegateConnectionMessageCallback} Binder Connection
+     * @throws ImsException if the request to create the {@link SipDelegate} did not complete.
+     */
+    public void createSipDelegate(int subId, DelegateRequest request, String packageName,
+            ISipDelegateConnectionStateCallback delegateState,
+            ISipDelegateMessageCallback delegateMessage) throws ImsException {
+        logi("createSipDelegate: request= " + request + ", packageName= " + packageName);
+        CompletableFuture<ImsException> result = new CompletableFuture<>();
+        mExecutorService.submit(() -> createSipDelegateInternal(subId, request, packageName,
+                delegateState,
+                // Capture any ImsExceptions generated during the process.
+                delegateMessage, result::complete));
+        try {
+            ImsException e = result.get();
+            logi("createSipDelegate: request finished");
+            if (e != null) {
+                throw e;
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            logw("createSipDelegate: exception completing future: " + e);
+        }
+    }
+
+    /**
+     * The remote IMS application has requested the destruction of an existing {@link SipDelegate}.
+     * @param subId The subId associated with the request.
+     * @param connection The internal Binder connection associated with the {@link SipDelegate}.
+     * @param reason The reason for why the {@link SipDelegate} was destroyed.
+     */
+    public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
+        mExecutorService.execute(() -> destroySipDelegateInternal(subId, connection, reason));
+    }
+
+    /**
+     * The remote IMS application has requested that the ImsService tear down and re-register for
+     * IMS features due to an error it received on the network in response to a SIP request.
+     */
+    public void triggerFullNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
+            String sipReason) {
+        mExecutorService.execute(() -> triggerFullNetworkRegistrationInternal(subId, connection,
+                sipCode, sipReason));
+    }
+
+    /**
+     * @return Whether or not SipTransports are supported on the connected ImsService. This can
+     * change based on the capabilities of the ImsService.
+     * @throws ImsException if the ImsService connected to this controller is currently down.
+     */
+    public boolean isSupported(int subId) throws ImsException {
+        Boolean result = waitForMethodToComplete(() -> isSupportedInternal(subId));
+        if (result == null) {
+            logw("isSupported, unexpected null result, returning false");
+            return false;
+        }
+        return result;
+    }
+
+    private void createSipDelegateInternal(int subId, DelegateRequest request, String packageName,
+            ISipDelegateConnectionStateCallback delegateState,
+            ISipDelegateMessageCallback delegateMessage,
+            Consumer<ImsException> startedErrorConsumer) {
+        ISipTransport transport;
+        IImsRegistration registration;
+        // Send back any errors via Consumer early in creation process if it is clear that the
+        // SipDelegate will never be created.
+        try {
+            checkStateOfController(subId);
+            transport = mRcsManager.getSipTransport();
+            registration = mRcsManager.getImsRegistration();
+            if (transport == null) {
+                logw("createSipDelegateInternal, transport null during request.");
+                startedErrorConsumer.accept(new ImsException("SipTransport not supported",
+                        ImsException.CODE_ERROR_UNSUPPORTED_OPERATION));
+                return;
+            } else {
+                // Release the binder thread as there were no issues processing the initial request.
+                startedErrorConsumer.accept(null);
+            }
+        } catch (ImsException e) {
+            logw("createSipDelegateInternal, ImsException during create: " + e);
+            startedErrorConsumer.accept(e);
+            return;
+        }
+
+        SipDelegateController c = mDelegateControllerFactory.create(subId, request, packageName,
+                transport, registration, mExecutorService, delegateState, delegateMessage);
+        logi("createSipDelegateInternal: request= " + request + ", packageName= " + packageName
+                + ", controller created: " + c);
+        addPendingCreateAndEvaluate(c);
+    }
+
+    private void destroySipDelegateInternal(int subId, ISipDelegate connection, int reason) {
+        if (subId != mSubId) {
+            logw("destroySipDelegateInternal: ignoring destroy, as this is about to be destroyed "
+                    + "anyway due to subId change, delegate=" + connection);
+            return;
+        }
+        if (connection == null) {
+            logw("destroySipDelegateInternal: ignoring destroy, null connection binder.");
+            return;
+        }
+        SipDelegateController match = null;
+        for (SipDelegateController controller : mDelegatePriorityQueue) {
+            if (Objects.equal(connection.asBinder(),
+                    controller.getSipDelegateInterface().asBinder())) {
+                match = controller;
+                break;
+            }
+        }
+        if (match == null) {
+            logw("destroySipDelegateInternal: could not find matching connection=" + connection);
+            return;
+        }
+
+        logi("destroySipDelegateInternal: destroy queued for connection= " + connection);
+        addPendingDestroyAndEvaluate(match, reason);
+    }
+
+    private void triggerFullNetworkRegistrationInternal(int subId, ISipDelegate connection,
+            int sipCode, String sipReason) {
+        if (subId != mSubId) {
+            logw("triggerFullNetworkRegistrationInternal: ignoring network reg request, as this is"
+                    + "about to be destroyed anyway due to subId change, delegate=" + connection);
+            return;
+        }
+        if (connection == null) {
+            logw("triggerFullNetworkRegistrationInternal: ignoring, null connection binder.");
+            return;
+        }
+        // Ensure the requester has a valid SipDelegate registered.
+        SipDelegateController match = null;
+        for (SipDelegateController controller : mDelegatePriorityQueue) {
+            if (Objects.equal(connection.asBinder(),
+                    controller.getSipDelegateInterface().asBinder())) {
+                match = controller;
+                break;
+            }
+        }
+        if (match == null) {
+            logw("triggerFullNetworkRegistrationInternal: could not find matching connection, "
+                    + "ignoring");
+            return;
+        }
+
+        match.triggerFullNetworkRegistration(sipCode, sipReason);
+    }
+
+    /**
+     * Cancel pending update IMS registration events if they exist and instead send a deregister
+     * event.
+     */
+    private void triggerDeregistrationEvent() {
+        logi("triggerDeregistrationEvent: Sending deregister event to ImsService");
+        cancelPendingUpdateRegistration();
+
+        IImsRegistration registrationImpl = mRcsManager.getImsRegistration();
+        if (registrationImpl != null) {
+            try {
+                registrationImpl.triggerSipDelegateDeregistration();
+            } catch (RemoteException e) {
+                logi("triggerDeregistrationEvent: received RemoteException: " + e);
+            }
+        }
+    }
+
+    /**
+     * Schedule an update to the IMS registration. If there is an existing update scheduled, cancel
+     * it and reschedule.
+     * <p>
+     * We want to wait because this can directly result in changes to the IMS registration on the
+     * network, so we need to wait for a steady state where all changes have been made before
+     * triggering an update to the network registration.
+     */
+    private void scheduleUpdateRegistration() {
+        cancelPendingUpdateRegistration();
+
+        ScheduledFuture<?> f = mExecutorService.schedule(this::triggerUpdateRegistrationEvent,
+                mTimerAdapter.getUpdateRegistrationDelayMilliseconds(), TimeUnit.MILLISECONDS);
+        logi("scheduleUpdateRegistration: scheduling new event: " + f);
+        mPendingUpdateRegistrationFuture = f;
+    }
+
+    /**
+     * Cancel an existing pending task to update the IMS registration associated with SIP delegates.
+     */
+    private void cancelPendingUpdateRegistration() {
+        if (mPendingUpdateRegistrationFuture == null
+                || mPendingUpdateRegistrationFuture.isDone()) {
+            return;
+        }
+        // Cancel the old pending operation and reschedule again.
+        mPendingUpdateRegistrationFuture.cancel(false);
+        logi("scheduleUpdateRegistration: cancelling existing reg update event: "
+                + mPendingUpdateRegistrationFuture);
+    }
+
+    /**
+     * Triggers an event to update the IMS registration of the ImsService. Should only be called
+     * from {@link #scheduleUpdateRegistration()}.
+     */
+    private void triggerUpdateRegistrationEvent() {
+        logi("triggerUpdateRegistrationEvent: Sending update registration event to ImsService");
+        IImsRegistration registrationImpl = mRcsManager.getImsRegistration();
+        if (registrationImpl != null) {
+            try {
+                registrationImpl.triggerUpdateSipDelegateRegistration();
+            } catch (RemoteException e) {
+                logi("triggerUpdateRegistrationEvent: received RemoteException: " + e);
+            }
+        }
+    }
+
+    /**
+     * Returns whether or not the ImsService implementation associated with the supplied subId
+     * supports the SipTransport APIs.
+     * <p>
+     * This should only be called on the ExecutorService.
+     * @return true if SipTransport is supported on this subscription, false otherwise.
+     * @throws ImsException thrown if there was an error determining the state of the ImsService.
+     */
+    private boolean isSupportedInternal(int subId) throws ImsException {
+        checkStateOfController(subId);
+        return (mRcsManager.getSipTransport() != null);
+    }
+
+    private boolean addPendingDestroy(SipDelegateController c, int reason) {
+        DestroyRequest request = new DestroyRequest(c, reason);
+        if (!mDelegatePendingDestroy.contains(request)) {
+            return mDelegatePendingDestroy.add(request);
+        }
+        return false;
+    }
+
+    /**
+     * The supplied SipDelegateController has been destroyed and associated feature tags have been
+     * released. Trigger the re-evaluation of the priority queue with the new configuration.
+     */
+    private void addPendingDestroyAndEvaluate(SipDelegateController c, int reason) {
+        if (addPendingDestroy(c, reason)) {
+            scheduleThrottledReevaluate();
+        }
+    }
+
+    /**
+     * A new SipDelegateController has been created, add to the back of the priority queue and
+     * trigger the re-evaluation of the priority queue with the new configuration.
+     */
+    private void addPendingCreateAndEvaluate(SipDelegateController c) {
+        mDelegatePendingCreate.add(c);
+        scheduleThrottledReevaluate();
+    }
+
+    /**
+     * The priority queue has changed, which will cause a re-evaluation of the feature tags granted
+     * to each SipDelegate.
+     * <p>
+     * Note: re-evaluations are throttled to happen at a minimum to occur every
+     * REEVALUATE_THROTTLE_MS seconds. We also do not reevaluate while another reevaluate operation
+     * is in progress, so in this case, defer schedule itself.
+     */
+    private void scheduleThrottledReevaluate() {
+        if (isEvaluatePendingAndNotInProgress()) {
+            logi("scheduleThrottledReevaluate: throttling reevaluate, eval already pending: "
+                    + mScheduledEvaluateFuture);
+        } else {
+            mScheduledEvaluateFuture = mExecutorService.schedule(this::reevaluateDelegates,
+                    mTimerAdapter.getReevaluateThrottleTimerMilliseconds(), TimeUnit.MILLISECONDS);
+            logi("scheduleThrottledReevaluate: new reevaluate scheduled: "
+                    + mScheduledEvaluateFuture);
+        }
+    }
+
+    /**
+     * @return true if there is a evaluate pending, false if there is not. If evaluate has already
+     * begun, but we are waiting for it to complete, this will also return false.
+     */
+    private boolean isEvaluatePendingAndNotInProgress() {
+        boolean isEvalScheduled = mScheduledEvaluateFuture != null
+                && !mScheduledEvaluateFuture.isDone();
+        boolean isEvalInProgress = mEvaluateCompleteFuture != null
+                && !mEvaluateCompleteFuture.isDone();
+        return isEvalScheduled && !isEvalInProgress;
+    }
+
+    /**
+     * Cancel any pending re-evaluates and perform it as soon as possible. This is done in the case
+     * where we need to do something like tear down this controller or change subId.
+     */
+    private void scheduleReevaluateNow(CompletableFuture<Void> onDoneFuture) {
+        if (isEvaluatePendingAndNotInProgress()) {
+            mScheduledEvaluateFuture.cancel(false /*interrupt*/);
+            logi("scheduleReevaluateNow: cancelling pending reevaluate: "
+                    + mScheduledEvaluateFuture);
+        }
+        // we have tasks that depend on this potentially, so once the last reevaluate is done,
+        // schedule a new one right away.
+        if (mEvaluateCompleteFuture != null && !mEvaluateCompleteFuture.isDone()) {
+            mEvaluateCompleteFuture.thenRunAsync(
+                    () -> scheduleReevaluateNow(onDoneFuture), mExecutorService);
+            return;
+        }
+
+        reevaluateDelegates();
+        mEvaluateCompleteFuture.thenAccept(onDoneFuture::complete);
+    }
+
+    /**
+     * Apply all operations that have been pending by collecting pending create/destroy operations
+     * and batch applying them to the mDelegatePriorityQueue.
+     *
+     * First perform the operation of destroying all SipDelegateConnections that have been pending
+     * destroy. Next, add all pending new SipDelegateControllers to the end of
+     * mDelegatePriorityQueue and loop through all in the queue, applying feature tags to the
+     * appropriate SipDelegateController if they pass role checks and have not already been claimed
+     * by another delegate higher in the priority queue.
+     */
+    private void reevaluateDelegates() {
+        // We need to cancel the pending update now and reschedule IMS registration update for
+        // after the reevaluate is complete.
+        cancelPendingUpdateRegistration();
+        if (mEvaluateCompleteFuture != null && !mEvaluateCompleteFuture.isDone()) {
+            logw("reevaluateDelegates: last evaluate not done, deferring new request");
+            // Defer re-evaluate until after the pending re-evaluate is complete.
+            mEvaluateCompleteFuture.thenRunAsync(this::scheduleThrottledReevaluate,
+                    mExecutorService);
+            return;
+        }
+
+        // Destroy all pending destroy delegates first. Order doesn't matter.
+        List<CompletableFuture<Void>> pendingDestroyList = mDelegatePendingDestroy.stream()
+                .map(d -> triggerDestroy(d.controller, d.reason)).collect(
+                Collectors.toList());
+        CompletableFuture<Void> pendingDestroy = CompletableFuture.allOf(
+                pendingDestroyList.toArray(new CompletableFuture[mDelegatePendingDestroy.size()]));
+        mDelegatePriorityQueue.removeAll(mDelegatePendingDestroy.stream().map(d -> d.controller)
+                .collect(Collectors.toList()));
+        mDelegatePendingDestroy.clear();
+
+        // Add newly created SipDelegates to end of queue before evaluating associated features.
+        mDelegatePriorityQueue.addAll(mDelegatePendingCreate);
+        for (SipDelegateController c : mDelegatePendingCreate) {
+            logi("reevaluateDelegates: pending create: " + c);
+        }
+        mDelegatePendingCreate.clear();
+
+        // Wait for destroy stages to complete, then loop from oldest to most recent and associate
+        // feature tags that the app has requested to the SipDelegate.
+        // Each feature tag can only be associated with one SipDelegate, so as feature tags are
+        // taken, do not allow other SipDelegates to be associated with those tags as well. Each
+        // stage of the CompletableFuture chain passes the previously claimed feature tags into the
+        // next stage so that those feature tags can be denied if already claimed.
+        // Executor doesn't matter here, just composing here to transform to the next stage.
+        CompletableFuture<Set<String>> pendingChange = pendingDestroy.thenCompose((ignore) -> {
+            logi("reevaluateDelegates: destroy phase complete");
+            return CompletableFuture.completedFuture(new ArraySet<>());
+        });
+        final String cachedSmsRolePackage = mCachedSmsRolePackageName;
+        for (SipDelegateController c : mDelegatePriorityQueue) {
+            logi("reevaluateDelegates: pending reeval: " + c);
+            pendingChange = pendingChange.thenComposeAsync((takenTags) -> {
+                logi("reevaluateDelegates: last stage completed with result:" + takenTags);
+                if (takenTags == null) {
+                    // return early, the ImsService is no longer available. This will eventually be
+                    // destroyed.
+                    return CompletableFuture.completedFuture(null /*failed*/);
+                }
+                return changeSupportedFeatureTags(c, cachedSmsRolePackage, takenTags);
+            }, mExecutorService);
+        }
+
+        // Executor doesn't matter here, schedule an event to update the IMS registration.
+        mEvaluateCompleteFuture = pendingChange
+                .thenAccept((associatedFeatures) -> {
+                    logi("reevaluateDelegates: reevaluate complete," + " feature tags associated: "
+                            + associatedFeatures);
+                    scheduleUpdateRegistration();
+                });
+        logi("reevaluateDelegates: future created.");
+    }
+
+    private CompletableFuture<Void> triggerDestroy(SipDelegateController c, int reason) {
+        return c.destroy(isForcedFromReason(reason), reason)
+                // Executor doesn't matter here, just for logging.
+                .thenAccept((delegateReason) -> logi("destroy triggered with " + reason
+                        + " and finished with reason= " + delegateReason));
+    }
+
+    private boolean isForcedFromReason(int reason) {
+        switch (reason) {
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_UNKNOWN:
+                logw("isForcedFromReason, unknown reason");
+                /*intentional fallthrough*/
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP:
+                /*intentional fallthrough*/
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS:
+                return false;
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD:
+                /*intentional fallthrough*/
+            case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN:
+                return true;
+        }
+        logw("isForcedFromReason, unexpected reason: " + reason);
+        return false;
+    }
+
+    /**
+     * Called by RoleManager when a role has changed so that we can query the new role holder.
+     * @param roleName the name of the role whose holders are changed
+     * @param user the user for this role holder change
+     */
+    // Called on mExecutorThread
+    @Override
+    public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+        logi("onRoleHoldersChanged, roleName= " + roleName + ", user= " + user);
+        // Only monitor changes on the system
+        if (!UserHandle.SYSTEM.equals(user)) {
+            return;
+        }
+
+        if (!RoleManager.ROLE_SMS.equals(roleName)) {
+            logi("onRoleHoldersChanged, ignoring non SMS role change");
+            // TODO: only target default sms app for now and add new roles later using
+            // CarrierConfigManager
+            return;
+        }
+        boolean roleChanged = updateRoleCache();
+        if (roleChanged) {
+            triggerDeregistrationEvent();
+            // new denied tags will be picked up when reevaluate completes.
+            scheduleThrottledReevaluate();
+        }
+    }
+
+
+    /**
+     * @return true, if the role cache has changed, false otherwise.
+     */
+    private boolean updateRoleCache() {
+        String newSmsRolePackageName = "";
+        try {
+            // Only one app can fulfill the SMS role.
+            newSmsRolePackageName = mRoleManagerAdapter.getRoleHolders(RoleManager.ROLE_SMS)
+                    .stream().findFirst().orElse("");
+        } catch (Exception e) {
+            logi("updateRoleCache: exception=" + e);
+        }
+
+        logi("updateRoleCache: new packageName=" + newSmsRolePackageName);
+        if (TextUtils.equals(mCachedSmsRolePackageName, newSmsRolePackageName)) {
+            logi("updateRoleCache, skipping, role did not change");
+            return false;
+        }
+        mCachedSmsRolePackageName = newSmsRolePackageName;
+        return true;
+    }
+
+    /**
+     * Check the requested roles for the specified package name and return the tags that were
+     * applied to that SipDelegateController.
+     * @param controller Controller to attribute feature tags to.
+     * @param alreadyRequestedTags The feature tags that were already granted to other SipDelegates.
+     * @return Once complete, contains the set of feature tags that the SipDelegate now has
+     * associated with it along with the feature tags that previous SipDelegates had.
+     *
+     * // TODO: we currently only track SMS role, extend to support other roles as well.
+     */
+    private CompletableFuture<Set<String>> changeSupportedFeatureTags(
+            SipDelegateController controller, String smsRolePackageName,
+            Set<String> alreadyRequestedTags) {
+        Set<String> requestedFeatureTags = controller.getInitialRequest().getFeatureTags();
+        String packageName = controller.getPackageName();
+        if (!smsRolePackageName.equals(packageName)) {
+            // Deny all tags.
+            Set<FeatureTagState> deniedTags = new ArraySet<>();
+            for (String s : requestedFeatureTags) {
+                deniedTags.add(new FeatureTagState(s,
+                        SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+            }
+            CompletableFuture<Boolean> pendingDeny = controller.changeSupportedFeatureTags(
+                    Collections.emptySet(), deniedTags);
+            logi("changeSupportedFeatureTags pendingDeny=" + pendingDeny);
+            // do not worry about executor used here, this stage used to interpret result + add log.
+            return pendingDeny.thenApply((completedSuccessfully) ->  {
+                logi("changeSupportedFeatureTags: deny completed: " + completedSuccessfully);
+                if (!completedSuccessfully) return null;
+                // Return back the previous list of requested tags, as we did not add any more.
+                return alreadyRequestedTags;
+            });
+        }
+
+        ArraySet<String> previouslyGrantedTags = new ArraySet<>(alreadyRequestedTags);
+        // deny tags already used by other delegates
+        Set<FeatureTagState> deniedTags = new ArraySet<>();
+        for (String s : requestedFeatureTags) {
+            if (previouslyGrantedTags.contains(s)) {
+                deniedTags.add(new FeatureTagState(s,
+                        SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+            }
+        }
+        Set<String> nonDeniedTags = requestedFeatureTags.stream()
+                .filter(r -> !previouslyGrantedTags.contains(r))
+                .collect(Collectors.toSet());
+        // Add newly granted tags to the already requested tags list.
+        previouslyGrantedTags.addAll(nonDeniedTags);
+        CompletableFuture<Boolean> pendingChange = controller.changeSupportedFeatureTags(
+                nonDeniedTags, deniedTags);
+        logi("changeSupportedFeatureTags pendingChange=" + pendingChange);
+        // do not worry about executor used here, this stage used to interpret result + add log.
+        return pendingChange.thenApply((completedSuccessfully) ->  {
+            logi("changeSupportedFeatureTags: change completed: " + completedSuccessfully);
+            if (!completedSuccessfully) return null;
+            return previouslyGrantedTags;
+        });
+    }
+
+    /**
+     * Run a Callable on the ExecutorService Thread and wait for the result.
+     * If an ImsException is thrown, catch it and rethrow it to caller.
+     */
+    private <T> T waitForMethodToComplete(Callable<T> callable) throws ImsException {
+        Future<T> r = mExecutorService.submit(callable);
+        T result;
+        try {
+            result = r.get();
+        } catch (InterruptedException e) {
+            result = null;
+        } catch (ExecutionException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof ImsException) {
+                // Rethrow the exception
+                throw (ImsException) cause;
+            }
+            logw("Unexpected Exception, returning null: " + cause);
+            result = null;
+        }
+        return result;
+    }
+
+    /**
+     * Throw an ImsException for common scenarios where the state of the controller is not ready
+     * for communication.
+     * <p>
+     * This should only be called while running on the on the ExecutorService.
+     */
+    private void checkStateOfController(int subId) throws ImsException {
+        if (mSubId != subId) {
+            // sub ID has changed while this was in the queue.
+            throw new ImsException("subId is no longer valid for this request.",
+                    ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+        }
+        if (mRcsManager == null) {
+            throw new ImsException("Connection to ImsService is not available",
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    private void onRcsManagerChanged(RcsFeatureManager m) {
+        logi("manager changed, " + mRcsManager + "->" + m);
+        if (mRcsManager == m) return;
+        mRcsManager = m;
+        if (mRcsManager == null) {
+            logi("onRcsManagerChanged: lost connection to ImsService, tearing down...");
+            unregisterListeners();
+            scheduleDestroyDelegates(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+        } else {
+            logi("onRcsManagerChanged: registering listeners/updating role cache...");
+            registerListeners();
+            updateRoleCache();
+        }
+    }
+
+    private void registerListeners() {
+        try {
+            mRoleManagerAdapter.addOnRoleHoldersChangedListenerAsUser(mExecutorService, this,
+                    UserHandle.SYSTEM);
+        } catch (Exception e) {
+            logi("registerListeners: exception=" + e);
+        }
+    }
+
+    private void unregisterListeners() {
+        mCachedSmsRolePackageName = "";
+        mRoleManagerAdapter.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM);
+    }
+
+    /**
+     * Called when either the sub ID associated with the slot has changed or the carrier
+     * configuration associated with the same subId has changed.
+     */
+    private void onSubIdChanged(int newSubId) {
+        logi("subId changed, " + mSubId + "->" + newSubId);
+        if (mSubId != newSubId) {
+            // Swap subId, any pending create/destroy on old subId will be denied.
+            mSubId = newSubId;
+            scheduleDestroyDelegates(
+                    SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+            return;
+        }
+        // TODO: if subId hasn't changed this means that we should load in any new carrier configs
+        // that we care about and apply.
+    }
+
+    /**
+     * Destroy all tracked SipDelegateConnections due to the subscription being torn down.
+     * @return A CompletableFuture that will complete when all SipDelegates have been torn down.
+     */
+    private CompletableFuture<Void> scheduleDestroyDelegates(int reason) {
+        boolean addedDestroy = false;
+        for (SipDelegateController c : mDelegatePriorityQueue) {
+            logi("scheduleDestroyDelegates: Controller pending destroy: " + c);
+            addedDestroy |= addPendingDestroy(c, reason);
+        }
+        if (addedDestroy) {
+            CompletableFuture<Void> pendingDestroy = new CompletableFuture<>();
+            scheduleReevaluateNow(pendingDestroy);
+            return pendingDestroy;
+        } else {
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+
+    @Override
+    public void dump(PrintWriter printWriter) {
+        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
+        pw.println("SipTransportController" + "[" + mSlotId  + "->" + mSubId + "]:");
+        pw.increaseIndent();
+        pw.println("LocalLog:");
+        pw.increaseIndent();
+        mLocalLog.dump(pw);
+        pw.decreaseIndent();
+        pw.println("SipDelegateControllers (in priority order):");
+        pw.increaseIndent();
+        if (mDelegatePriorityQueue.isEmpty()) {
+            pw.println("[NONE]");
+        } else {
+            for (SipDelegateController c : mDelegatePriorityQueue) {
+                c.dump(pw);
+            }
+        }
+        pw.decreaseIndent();
+        pw.decreaseIndent();
+    }
+
+    private void logi(String log) {
+        Log.w(LOG_TAG, "[" + mSlotId  + "->" + mSubId + "] " + log);
+        mLocalLog.log("[I] " + log);
+    }
+
+    private void logw(String log) {
+        Log.w(LOG_TAG, "[" + mSlotId  + "->" + mSubId + "] " + log);
+        mLocalLog.log("[W] " + log);
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index c85e9a9..66492ae 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -33,6 +33,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.phone.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -47,21 +48,25 @@
     private static final String LOG_TAG = "TelephonyRcsService";
 
     /**
-     * Used to inject RcsFeatureController and UserCapabilityExchangeImpl instances for testing.
+     * Used to inject RcsFeatureController and UceController instances for testing.
      */
     @VisibleForTesting
     public interface FeatureFactory {
         /**
-         * @return an {@link RcsFeatureController} assoicated with the slot specified.
+         * @return an {@link RcsFeatureController} associated with the slot specified.
          */
         RcsFeatureController createController(Context context, int slotId);
 
         /**
-         * @return an instance of {@link UserCapabilityExchangeImpl} associated with the slot
+         * @return an instance of {@link UceControllerManager} associated with the slot specified.
+         */
+        UceControllerManager createUceControllerManager(Context context, int slotId, int subId);
+
+        /**
+         * @return an instance of {@link SipTransportController} for the slot and subscription
          * specified.
          */
-        UserCapabilityExchangeImpl createUserCapabilityExchange(Context context, int slotId,
-                int subId);
+        SipTransportController createSipTransportController(Context context, int slotId, int subId);
     }
 
     private FeatureFactory mFeatureFactory = new FeatureFactory() {
@@ -71,10 +76,32 @@
         }
 
         @Override
-        public UserCapabilityExchangeImpl createUserCapabilityExchange(Context context, int slotId,
+        public UceControllerManager createUceControllerManager(Context context, int slotId,
                 int subId) {
-            return new UserCapabilityExchangeImpl(context, slotId, subId);
+            return new UceControllerManager(context, slotId, subId);
         }
+
+        @Override
+        public SipTransportController createSipTransportController(Context context, int slotId,
+                int subId) {
+            return new SipTransportController(context, slotId, subId);
+        }
+    };
+
+    /**
+     * Used to inject device resource for testing.
+     */
+    @VisibleForTesting
+    public interface ResourceProxy {
+        /**
+         * @return an whether the device supports User Capability Exchange.
+         */
+        boolean getDeviceUceEnabled(Context context);
+    }
+
+    private static ResourceProxy sResourceProxy = context -> {
+        return context.getResources().getBoolean(
+                R.bool.config_rcs_user_capability_exchange_enabled);
     };
 
     // Notifies this service that there has been a change in available slots.
@@ -87,6 +114,9 @@
     // Maps slot ID -> RcsFeatureController.
     private SparseArray<RcsFeatureController> mFeatureControllers;
 
+    // Whether the device supports User Capability Exchange
+    private boolean mRcsUceEnabled;
+
     private BroadcastReceiver mCarrierConfigChangedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -129,6 +159,16 @@
         mContext = context;
         mNumSlots = numSlots;
         mFeatureControllers = new SparseArray<>(numSlots);
+        mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
+    }
+
+    @VisibleForTesting
+    public TelephonyRcsService(Context context, int numSlots, ResourceProxy resourceProxy) {
+        mContext = context;
+        mNumSlots = numSlots;
+        mFeatureControllers = new SparseArray<>(numSlots);
+        sResourceProxy = resourceProxy;
+        mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
     }
 
     /**
@@ -224,32 +264,65 @@
     }
 
     private void updateSupportedFeatures(RcsFeatureController c, int slotId, int subId) {
-        if (doesSubscriptionSupportPresence(subId)) {
-            if (c.getFeature(UserCapabilityExchangeImpl.class) == null) {
-                c.addFeature(mFeatureFactory.createUserCapabilityExchange(mContext, slotId, subId),
-                        UserCapabilityExchangeImpl.class);
+        if (isDeviceUceEnabled() && doesSubscriptionSupportPresence(subId)) {
+            if (c.getFeature(UceControllerManager.class) == null) {
+                c.addFeature(mFeatureFactory.createUceControllerManager(mContext, slotId, subId),
+                        UceControllerManager.class);
             }
         } else {
-            if (c.getFeature(UserCapabilityExchangeImpl.class) != null) {
-                c.removeFeature(UserCapabilityExchangeImpl.class);
+            if (c.getFeature(UceControllerManager.class) != null) {
+                c.removeFeature(UceControllerManager.class);
+            }
+        }
+
+        if (doesSubscriptionSupportSingleRegistration(subId)) {
+            if (c.getFeature(SipTransportController.class) == null) {
+                c.addFeature(mFeatureFactory.createSipTransportController(mContext, slotId, subId),
+                        SipTransportController.class);
+            }
+        } else {
+            if (c.getFeature(SipTransportController.class) != null) {
+                c.removeFeature(SipTransportController.class);
             }
         }
         // Only start the connection procedure if we have active features.
         if (c.hasActiveFeatures()) c.connect();
     }
 
+    /**
+     * Get whether the device supports RCS User Capability Exchange or not.
+     */
+    public boolean isDeviceUceEnabled() {
+        return mRcsUceEnabled;
+    }
+
+    /**
+     * Set the device supports RCS User Capability Exchange.
+     */
+    public void setDeviceUceEnabled(boolean isEnabled) {
+        mRcsUceEnabled = isEnabled;
+    }
+
     private boolean doesSubscriptionSupportPresence(int subId) {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
         CarrierConfigManager carrierConfigManager =
                 mContext.getSystemService(CarrierConfigManager.class);
         if (carrierConfigManager == null) return false;
         boolean supportsUce = carrierConfigManager.getConfigForSubId(subId).getBoolean(
-                CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL);
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL);
         supportsUce |= carrierConfigManager.getConfigForSubId(subId).getBoolean(
                 CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL);
         return supportsUce;
     }
 
+    private boolean doesSubscriptionSupportSingleRegistration(int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
+        CarrierConfigManager carrierConfigManager =
+                mContext.getSystemService(CarrierConfigManager.class);
+        if (carrierConfigManager == null) return false;
+        return carrierConfigManager.getConfigForSubId(subId).getBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+    }
 
     private int getSubscriptionFromSlot(int slotId) {
         SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class);
@@ -274,6 +347,7 @@
         synchronized (mLock) {
             for (int i = 0; i < mNumSlots; i++) {
                 RcsFeatureController f = mFeatureControllers.get(i);
+                if (f == null) continue;
                 pw.increaseIndent();
                 f.dump(fd, printWriter, args);
                 pw.decreaseIndent();
diff --git a/src/com/android/services/telephony/rcs/UceControllerManager.java b/src/com/android/services/telephony/rcs/UceControllerManager.java
new file mode 100644
index 0000000..09288f1
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/UceControllerManager.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.content.Context;
+import android.net.Uri;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.RcsUceAdapter.PublishState;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.util.Log;
+
+import com.android.ims.RcsFeatureManager;
+import com.android.ims.rcs.uce.UceController;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * Responsible for managing the creation and destruction of UceController. It also received the
+ * requests from {@link com.android.phone.ImsRcsController} and pass these requests to
+ * {@link UceController}
+ */
+public class UceControllerManager implements RcsFeatureController.Feature {
+
+    private static final String LOG_TAG = "UceControllerManager";
+
+    private final int mSlotId;
+    private final Context mContext;
+    private final ExecutorService mExecutorService;
+
+    private volatile UceController mUceController;
+    private volatile RcsFeatureManager mRcsFeatureManager;
+
+    public UceControllerManager(Context context, int slotId, int subId) {
+        Log.d(LOG_TAG, "create: slotId=" + slotId + ", subId=" + subId);
+
+        mSlotId = slotId;
+        mContext = context;
+        mExecutorService = Executors.newSingleThreadExecutor();
+        mUceController = new UceController(mContext, subId);
+    }
+
+    /**
+     * Constructor to inject dependencies for testing.
+     */
+    @VisibleForTesting
+    public UceControllerManager(Context context, int slotId, int subId, ExecutorService executor) {
+        mSlotId = slotId;
+        mContext = context;
+        mExecutorService = executor;
+        mUceController = new UceController(mContext, subId);
+    }
+
+    @Override
+    public void onRcsConnected(RcsFeatureManager manager) {
+        mExecutorService.submit(() -> {
+            mRcsFeatureManager = manager;
+            mUceController.onRcsConnected(manager);
+        });
+    }
+
+    @Override
+    public void onRcsDisconnected() {
+        mExecutorService.submit(() -> {
+            mRcsFeatureManager = null;
+            mUceController.onRcsDisconnected();
+        });
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(LOG_TAG, "onDestroy");
+        mExecutorService.submit(() -> mUceController.onDestroy());
+        // When the shutdown is called, it will refuse any new tasks and let existing tasks finish.
+        mExecutorService.shutdown();
+    }
+
+    /**
+     * This method will be called when either the subscription ID associated with the slot has
+     * changed or the carrier configuration associated with the same subId has changed.
+     */
+    @Override
+    public void onAssociatedSubscriptionUpdated(int subId) {
+        mExecutorService.submit(() -> {
+            Log.i(LOG_TAG, "onAssociatedSubscriptionUpdated: slotId=" + mSlotId
+                    + ", subId=" + subId);
+
+            // Destroy existing UceController and create a new one.
+            mUceController.onDestroy();
+            mUceController = new UceController(mContext, subId);
+
+            // The RCS should be connected when the mRcsFeatureManager is not null. Set it to the
+            // new UceController instance.
+            if (mRcsFeatureManager != null) {
+                mUceController.onRcsConnected(mRcsFeatureManager);
+            }
+        });
+    }
+
+    @VisibleForTesting
+    public void setUceController(UceController uceController) {
+        mUceController = uceController;
+    }
+
+    /**
+     * Request the capabilities for contacts.
+     *
+     * @param contactNumbers A list of numbers that the capabilities are being requested for.
+     * @param c A callback for when the request for capabilities completes.
+     * @throws ImsException if the ImsService connected to this controller is currently down.
+     */
+    public void requestCapabilities(List<Uri> contactNumbers, IRcsUceControllerCallback c)
+            throws ImsException {
+        Future future = mExecutorService.submit(() -> {
+            checkUceControllerState();
+            mUceController.requestCapabilities(contactNumbers, c);
+            return true;
+        });
+
+        try {
+            future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "requestCapabilities: " + e);
+            Throwable cause = e.getCause();
+            if (cause instanceof ImsException) {
+                throw (ImsException) cause;
+            }
+        }
+    }
+
+    /**
+     * Request the capabilities for the given contact.
+     * @param contactNumber The contact of the capabilities are being requested for.
+     * @param c A callback for when the request for capabilities completes.
+     * @throws ImsException if the ImsService connected to this controller is currently down.
+     */
+    public void requestNetworkAvailability(Uri contactNumber, IRcsUceControllerCallback c)
+            throws ImsException {
+        Future future = mExecutorService.submit(() -> {
+            checkUceControllerState();
+            mUceController.requestAvailability(contactNumber, c);
+            return true;
+        });
+
+        try {
+            future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "requestNetworkAvailability exception: " + e);
+            Throwable cause = e.getCause();
+            if (cause instanceof ImsException) {
+                throw (ImsException) cause;
+            }
+        }
+    }
+
+    /**
+     * Get the UCE publish state.
+     *
+     * @throws ImsException if the ImsService connected to this controller is currently down.
+     */
+    public @PublishState int getUcePublishState() throws ImsException {
+        Future future = mExecutorService.submit(() -> {
+            checkUceControllerState();
+            return mUceController.getUcePublishState();
+        });
+
+        try {
+            return (Integer) future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "requestNetworkAvailability exception: " + e);
+            Throwable cause = e.getCause();
+            if (cause instanceof ImsException) {
+                throw (ImsException) cause;
+            }
+            return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
+        }
+    }
+
+    /**
+     * Register the Publish state changed callback.
+     *
+     * @throws ImsException if the ImsService connected to this controller is currently down.
+     */
+    public void registerPublishStateCallback(IRcsUcePublishStateCallback c) throws ImsException {
+        Future future = mExecutorService.submit(() -> {
+            checkUceControllerState();
+            mUceController.registerPublishStateCallback(c);
+            return true;
+        });
+
+        try {
+            future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "registerPublishStateCallback exception: " + e);
+            Throwable cause = e.getCause();
+            if (cause instanceof ImsException) {
+                throw (ImsException) cause;
+            }
+        }
+    }
+
+    /**
+     * Unregister the existing publish state changed callback.
+     */
+    public void unregisterPublishStateCallback(IRcsUcePublishStateCallback c) {
+        Future future = mExecutorService.submit(() -> {
+            if (checkUceControllerState()) {
+                mUceController.unregisterPublishStateCallback(c);
+            }
+            return true;
+        });
+
+        try {
+            future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "unregisterPublishStateCallback exception: " + e);
+        }
+    }
+
+    private boolean checkUceControllerState() throws ImsException {
+        if (mUceController == null || mUceController.isUnavailable()) {
+            throw new ImsException("UCE controller is unavailable",
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+        return true;
+    }
+
+
+    @Override
+    public void dump(PrintWriter printWriter) {
+        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
+        pw.println("UceControllerManager" + "[" + mSlotId + "]:");
+        pw.increaseIndent();
+        pw.println("UceController available = " + mUceController != null);
+        //TODO: Add dump for UceController
+        pw.decreaseIndent();
+    }
+}
diff --git a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java b/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
deleted file mode 100644
index ac8f9bf..0000000
--- a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.services.telephony.rcs;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.telephony.ims.RcsContactUceCapability;
-import android.telephony.ims.RcsUceAdapter;
-import android.telephony.ims.aidl.IRcsUceControllerCallback;
-import android.util.Log;
-
-import com.android.ims.RcsFeatureManager;
-import com.android.ims.ResultCode;
-import com.android.phone.R;
-import com.android.service.ims.presence.ContactCapabilityResponse;
-import com.android.service.ims.presence.PresenceBase;
-import com.android.service.ims.presence.PresencePublication;
-import com.android.service.ims.presence.PresencePublisher;
-import com.android.service.ims.presence.PresenceSubscriber;
-import com.android.service.ims.presence.SubscribePublisher;
-
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-/**
- * Implements User Capability Exchange using Presence.
- */
-public class UserCapabilityExchangeImpl implements RcsFeatureController.Feature, SubscribePublisher,
-        PresencePublisher {
-
-    private static final String LOG_TAG = "RcsUceImpl";
-
-    private int mSlotId;
-    private int mSubId;
-
-    private final PresencePublication mPresencePublication;
-    private final PresenceSubscriber mPresenceSubscriber;
-
-    private final ConcurrentHashMap<Integer, IRcsUceControllerCallback> mPendingCapabilityRequests =
-            new ConcurrentHashMap<>();
-
-    UserCapabilityExchangeImpl(Context context, int slotId, int subId) {
-        mSlotId = slotId;
-        mSubId = subId;
-        logi("created");
-
-        String[] volteError = context.getResources().getStringArray(
-                R.array.config_volte_provision_error_on_publish_response);
-        String[] rcsError = context.getResources().getStringArray(
-                R.array.config_rcs_provision_error_on_publish_response);
-
-        // Initialize PresencePublication
-        mPresencePublication = new PresencePublication(null /*PresencePublisher*/, context,
-                volteError, rcsError);
-        // Initialize PresenceSubscriber
-        mPresenceSubscriber = new PresenceSubscriber(null /*SubscribePublisher*/, context,
-                volteError, rcsError);
-
-        onAssociatedSubscriptionUpdated(mSubId);
-    }
-
-
-    // Runs on main thread.
-    @Override
-    public void onRcsConnected(RcsFeatureManager rcsFeatureManager) {
-        logi("onRcsConnected");
-        mPresencePublication.updatePresencePublisher(this);
-        mPresenceSubscriber.updatePresenceSubscriber(this);
-    }
-
-    // Runs on main thread.
-    @Override
-    public void onRcsDisconnected() {
-        logi("onRcsDisconnected");
-        mPresencePublication.removePresencePublisher();
-        mPresenceSubscriber.removePresenceSubscriber();
-    }
-
-    // Runs on main thread.
-    @Override
-    public void onAssociatedSubscriptionUpdated(int subId) {
-        mPresencePublication.handleAssociatedSubscriptionChanged(subId);
-        mPresenceSubscriber.handleAssociatedSubscriptionChanged(subId);
-    }
-
-    /**
-     * Should be called before destroying this instance.
-     * This instance is not usable after this method is called.
-     */
-    // Called on main thread.
-    public void onDestroy() {
-        onRcsDisconnected();
-    }
-
-    /**
-     * @return the UCE Publish state.
-     */
-    // May happen on a Binder thread, PresencePublication locks to get result.
-    public int getUcePublishState() {
-        int publishState = mPresencePublication.getPublishState();
-        return toUcePublishState(publishState);
-    }
-
-    /**
-     * Perform a capabilities request and call {@link IRcsUceControllerCallback} with the result.
-     */
-    // May happen on a Binder thread, PresenceSubscriber locks when requesting Capabilities.
-    public void requestCapabilities(List<Uri> contactNumbers, IRcsUceControllerCallback c) {
-        List<String> numbers = contactNumbers.stream()
-                .map(UserCapabilityExchangeImpl::getNumberFromUri).collect(Collectors.toList());
-        int taskId = mPresenceSubscriber.requestCapability(numbers,
-                new ContactCapabilityResponse() {
-                    @Override
-                    public void onSuccess(int reqId) {
-                        logi("onSuccess called for reqId:" + reqId);
-                    }
-
-                    @Override
-                    public void onError(int reqId, int resultCode) {
-                        IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
-                        try {
-                            if (c != null) {
-                                c.onError(toUceError(resultCode));
-                            } else {
-                                logw("onError called for unknown reqId:" + reqId);
-                            }
-                        } catch (RemoteException e) {
-                            logi("Calling back to dead service");
-                        }
-                    }
-
-                    @Override
-                    public void onFinish(int reqId) {
-                        logi("onFinish called for reqId:" + reqId);
-                    }
-
-                    @Override
-                    public void onTimeout(int reqId) {
-                        IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
-                        try {
-                            if (c != null) {
-                                c.onError(RcsUceAdapter.ERROR_REQUEST_TIMEOUT);
-                            } else {
-                                logw("onTimeout called for unknown reqId:" + reqId);
-                            }
-                        } catch (RemoteException e) {
-                            logi("Calling back to dead service");
-                        }
-                    }
-
-                    @Override
-                    public void onCapabilitiesUpdated(int reqId,
-                            List<RcsContactUceCapability> contactCapabilities,
-                            boolean updateLastTimestamp) {
-                        IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
-                        try {
-                            if (c != null) {
-                                c.onCapabilitiesReceived(contactCapabilities);
-                            } else {
-                                logw("onCapabilitiesUpdated, unknown reqId:" + reqId);
-                            }
-                        } catch (RemoteException e) {
-                            logw("onCapabilitiesUpdated on dead service");
-                        }
-                    }
-                });
-        if (taskId < 0) {
-            try {
-                c.onError(toUceError(taskId));
-                return;
-            } catch (RemoteException e) {
-                logi("Calling back to dead service");
-            }
-        }
-        mPendingCapabilityRequests.put(taskId, c);
-    }
-
-    @Override
-    public int getPublisherState() {
-        return 0;
-    }
-
-    @Override
-    public int requestPublication(RcsContactUceCapability capabilities, String contactUri,
-            int taskId) {
-        return 0;
-    }
-
-    @Override
-    public int requestCapability(String[] formatedContacts, int taskId) {
-        return 0;
-    }
-
-    @Override
-    public int requestAvailability(String formattedContact, int taskId) {
-        return 0;
-    }
-
-    @Override
-    public int getStackStatusForCapabilityRequest() {
-        return 0;
-    }
-
-    @Override
-    public void updatePublisherState(int publishState) {
-
-    }
-
-    private static String getNumberFromUri(Uri uri) {
-        String number = uri.getSchemeSpecificPart();
-        String[] numberParts = number.split("[@;:]");
-
-        if (numberParts.length == 0) {
-            return null;
-        }
-        return numberParts[0];
-    }
-
-    private static int toUcePublishState(int publishState) {
-        switch (publishState) {
-            case PresenceBase.PUBLISH_STATE_200_OK:
-                return RcsUceAdapter.PUBLISH_STATE_OK;
-            case PresenceBase.PUBLISH_STATE_NOT_PUBLISHED:
-                return RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
-            case PresenceBase.PUBLISH_STATE_VOLTE_PROVISION_ERROR:
-                return RcsUceAdapter.PUBLISH_STATE_VOLTE_PROVISION_ERROR;
-            case PresenceBase.PUBLISH_STATE_RCS_PROVISION_ERROR:
-                return RcsUceAdapter.PUBLISH_STATE_RCS_PROVISION_ERROR;
-            case PresenceBase.PUBLISH_STATE_REQUEST_TIMEOUT:
-                return RcsUceAdapter.PUBLISH_STATE_REQUEST_TIMEOUT;
-            case PresenceBase.PUBLISH_STATE_OTHER_ERROR:
-                return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
-            default:
-                return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
-        }
-    }
-
-    private static int toUceError(int resultCode) {
-        switch (resultCode) {
-            case ResultCode.SUBSCRIBE_NOT_REGISTERED:
-                return RcsUceAdapter.ERROR_NOT_REGISTERED;
-            case ResultCode.SUBSCRIBE_REQUEST_TIMEOUT:
-                return RcsUceAdapter.ERROR_REQUEST_TIMEOUT;
-            case ResultCode.SUBSCRIBE_FORBIDDEN:
-                return RcsUceAdapter.ERROR_FORBIDDEN;
-            case ResultCode.SUBSCRIBE_NOT_FOUND:
-                return RcsUceAdapter.ERROR_NOT_FOUND;
-            case ResultCode.SUBSCRIBE_TOO_LARGE:
-                return RcsUceAdapter.ERROR_REQUEST_TOO_LARGE;
-            case ResultCode.SUBSCRIBE_INSUFFICIENT_MEMORY:
-                return RcsUceAdapter.ERROR_INSUFFICIENT_MEMORY;
-            case ResultCode.SUBSCRIBE_LOST_NETWORK:
-                return RcsUceAdapter.ERROR_LOST_NETWORK;
-            case ResultCode.SUBSCRIBE_ALREADY_IN_QUEUE:
-                return RcsUceAdapter.ERROR_ALREADY_IN_QUEUE;
-            default:
-                return RcsUceAdapter.ERROR_GENERIC_FAILURE;
-        }
-    }
-
-    private void logi(String log) {
-        Log.i(LOG_TAG, getLogPrefix().append(log).toString());
-    }
-
-    private void logw(String log) {
-        Log.w(LOG_TAG, getLogPrefix().append(log).toString());
-    }
-
-    private StringBuilder getLogPrefix() {
-        StringBuilder builder = new StringBuilder("[");
-        builder.append(mSlotId);
-        builder.append("->");
-        builder.append(mSubId);
-        builder.append("] ");
-        return builder;
-    }
-}
diff --git a/testapps/EmbmsServiceTestApp/AndroidManifest.xml b/testapps/EmbmsServiceTestApp/AndroidManifest.xml
index 91d8508..943fc78 100644
--- a/testapps/EmbmsServiceTestApp/AndroidManifest.xml
+++ b/testapps/EmbmsServiceTestApp/AndroidManifest.xml
@@ -15,30 +15,31 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-        package="com.android.phone.testapps.embmsmw"
-        coreApp="true">
+     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+     package="com.android.phone.testapps.embmsmw"
+     coreApp="true">
   <uses-permission android:name="android.permission.SEND_EMBMS_INTENTS"/>
 
   <application android:label="EmbmsTestMiddleware">
     <service android:name="com.android.phone.testapps.embmsmw.EmbmsTestStreamingService"
-            android:launchMode="singleInstance"
-            androidprv:systemUserOnly="true">
+         android:launchMode="singleInstance"
+         androidprv:systemUserOnly="true"
+         android:exported="true">
       <intent-filter>
-        <action android:name="android.telephony.action.EmbmsStreaming" />
+        <action android:name="android.telephony.action.EmbmsStreaming"/>
       </intent-filter>
     </service>
     <service android:name="com.android.phone.testapps.embmsmw.EmbmsSampleDownloadService"
-             android:launchMode="singleInstance"
-             androidprv:systemUserOnly="true">
+         android:launchMode="singleInstance"
+         androidprv:systemUserOnly="true"
+         android:exported="true">
       <intent-filter>
-        <action android:name="android.telephony.action.EmbmsDownload" />
+        <action android:name="android.telephony.action.EmbmsDownload"/>
       </intent-filter>
     </service>
 
     <receiver android:name="com.android.phone.testapps.embmsmw.SideChannelReceiver"
-              android:enabled="true"
-              android:exported="true"/>
+         android:enabled="true"
+         android:exported="true"/>
   </application>
 </manifest>
-
diff --git a/testapps/EmbmsTestDownloadApp/AndroidManifest.xml b/testapps/EmbmsTestDownloadApp/AndroidManifest.xml
index e93cd19..640fcd1 100644
--- a/testapps/EmbmsTestDownloadApp/AndroidManifest.xml
+++ b/testapps/EmbmsTestDownloadApp/AndroidManifest.xml
@@ -15,57 +15,54 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.phone.testapps.embmsdownload">
+     package="com.android.phone.testapps.embmsdownload">
     <application android:label="EmbmsTestDownloadApp">
-        <activity
-            android:name=".EmbmsTestDownloadApp"
-            android:label="EmbmsDownloadFrontend">
+        <activity android:name=".EmbmsTestDownloadApp"
+             android:label="EmbmsDownloadFrontend"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
         <!-- This is the receiver defined by the MBMS api. -->
-        <receiver
-            android:name="android.telephony.mbms.MbmsDownloadReceiver"
-            android:permission="android.permission.SEND_EMBMS_INTENTS"
-            android:enabled="true"
-            android:exported="true">
+        <receiver android:name="android.telephony.mbms.MbmsDownloadReceiver"
+             android:permission="android.permission.SEND_EMBMS_INTENTS"
+             android:enabled="true"
+             android:exported="true">
         </receiver>
 
         <!-- This is the receiver defined by app to receive the download-done intent that was
          passed into DownloadRequest. -->
-        <receiver
-            android:name="com.android.phone.testapps.embmsdownload.DownloadCompletionReceiver"
-            android:enabled="true">
+        <receiver android:name="com.android.phone.testapps.embmsdownload.DownloadCompletionReceiver"
+             android:enabled="true">
         </receiver>
 
         <!-- This is the provider that apps must declare in their manifest. It allows the
         middleware to obtain file descriptors to temp files in the app's file space -->
         <!-- grantUriPermissions must be set to true -->
-        <provider
-            android:name="android.telephony.mbms.MbmsTempFileProvider"
-            android:authorities="com.android.phone.testapps.embmsdownload"
-            android:exported="false"
-            android:grantUriPermissions="true">
+        <provider android:name="android.telephony.mbms.MbmsTempFileProvider"
+             android:authorities="com.android.phone.testapps.embmsdownload"
+             android:exported="false"
+             android:grantUriPermissions="true">
             <!-- This is a mandatory piece of metadata that contains the directory where temp
             files should be put. It should be a relative path from Context.getFilesDir() or from
             Context.getExternalStorageDir(null), depending on the value of the
             use-external-storage metadata. -->
-            <meta-data android:name="temp-file-path" android:value="/mbms-temp/"/>
+            <meta-data android:name="temp-file-path"
+                 android:value="/mbms-temp/"/>
 
             <!-- This tells the provider whether to use the sdcard partition for the temp files or
             not. -->
-            <meta-data android:name="use-external-storage" android:value="false"/>
+            <meta-data android:name="use-external-storage"
+                 android:value="false"/>
         </provider>
 
         <!-- This is a mandatory piece of metadata that contains the authority string for the
         provider declared above -->
-        <meta-data
-            android:name="mbms-file-provider-authority"
-            android:value="com.android.phone.testapps.embmsdownload"/>
+        <meta-data android:name="mbms-file-provider-authority"
+             android:value="com.android.phone.testapps.embmsdownload"/>
     </application>
 </manifest>
-
diff --git a/testapps/EmbmsTestStreamingApp/AndroidManifest.xml b/testapps/EmbmsTestStreamingApp/AndroidManifest.xml
index d13425d..9cb83f2 100644
--- a/testapps/EmbmsTestStreamingApp/AndroidManifest.xml
+++ b/testapps/EmbmsTestStreamingApp/AndroidManifest.xml
@@ -15,17 +15,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.phone.testapps.embmsfrontend">
+     package="com.android.phone.testapps.embmsfrontend">
     <application android:label="EmbmsTestStreamingApp">
-        <activity
-            android:name=".EmbmsTestStreamingApp"
-            android:label="EmbmsStreamingFrontend">
+        <activity android:name=".EmbmsTestStreamingApp"
+             android:label="EmbmsStreamingFrontend"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
     </application>
 </manifest>
-
diff --git a/testapps/GbaTestApp/Android.bp b/testapps/GbaTestApp/Android.bp
new file mode 100644
index 0000000..cb6df4e
--- /dev/null
+++ b/testapps/GbaTestApp/Android.bp
@@ -0,0 +1,26 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// 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.
+
+android_test {
+    name: "GbaTestApp",
+    static_libs: [
+        "androidx.appcompat_appcompat",
+	"androidx-constraintlayout_constraintlayout",
+	"ub-uiautomator",
+    ],
+    srcs: ["src/**/*.java"],
+    javacflags: ["-parameters"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/testapps/GbaTestApp/AndroidManifest.xml b/testapps/GbaTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..8554461
--- /dev/null
+++ b/testapps/GbaTestApp/AndroidManifest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.phone.testapps.gbatestapp">
+
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.BIND_GBA_SERVICE" />
+
+    <application
+        android:allowBackup="true"
+        android:label="@string/app_name"
+        android:theme="@style/Theme.AppCompat"
+        android:supportsRtl="true">
+        <service
+            android:name=".TestGbaService"
+            android:directBootAware="true"
+            android:permission="android.permission.BIND_GBA_SERVICE"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telephony.gba.GbaService"/>
+            </intent-filter>
+        </service>
+
+        <activity android:name=".MainActivity"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/testapps/GbaTestApp/res/layout/fragment_carrier_config.xml b/testapps/GbaTestApp/res/layout/fragment_carrier_config.xml
new file mode 100644
index 0000000..f15fa2a
--- /dev/null
+++ b/testapps/GbaTestApp/res/layout/fragment_carrier_config.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/black"
+    tools:context=".ui.main.CarrierConfigFragment">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/service_package_name" />
+
+        <EditText
+            android:id="@+id/editServicePackageName"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0"
+            android:ems="10"
+            android:gravity="start|top"
+            android:inputType="textMultiLine" />
+
+        <TextView
+            android:id="@+id/textTestLabel"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/service_release_time" />
+
+        <EditText
+            android:id="@+id/editServiceReleaseTime"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:inputType="numberSigned" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/layout_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:orientation="vertical">
+
+        <Button
+            android:id="@+id/carrier_config_clear"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_clear" />
+
+        <Button
+            android:id="@+id/carrier_config_done"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_done" />
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/testapps/GbaTestApp/res/layout/fragment_service_config.xml b/testapps/GbaTestApp/res/layout/fragment_service_config.xml
new file mode 100644
index 0000000..50090c2
--- /dev/null
+++ b/testapps/GbaTestApp/res/layout/fragment_service_config.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/black"
+    tools:context=".ui.main.ServiceConfigFragment">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_above="@id/layout_buttons"
+        android:orientation="vertical">
+
+        <CheckBox
+            android:id="@+id/checkBoxResult"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/response_success" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/response_key" />
+
+        <EditText
+            android:id="@+id/editKey"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:inputType="textPersonName" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:editable="false"
+            android:text="@string/response_btid" />
+
+        <EditText
+            android:id="@+id/editBTid"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:inputType="textPersonName" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/response_fail_reason" />
+
+        <EditText
+            android:id="@+id/editFailReason"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:inputType="numberSigned" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/layout_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_gravity="bottom"
+        android:orientation="vertical">
+
+        <Button
+            android:id="@+id/service_config_clear"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_clear" />
+
+        <Button
+            android:id="@+id/service_config_done"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_done" />
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/testapps/GbaTestApp/res/layout/fragment_test_config.xml b/testapps/GbaTestApp/res/layout/fragment_test_config.xml
new file mode 100644
index 0000000..d8016f0
--- /dev/null
+++ b/testapps/GbaTestApp/res/layout/fragment_test_config.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/black"
+    tools:context=".ui.main.TestConfigFragment">
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginBottom="8dp"
+        android:scrollbarStyle="outsideInset"
+        app:layout_constraintBottom_toTopOf="@id/layout_buttons"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_app_type" />
+
+            <EditText
+                android:id="@+id/editAppType"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="numberSigned" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_naf_url" />
+
+            <EditText
+                android:id="@+id/editUrl"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="textUri" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_org" />
+
+            <EditText
+                android:id="@+id/editOrg"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="numberSigned" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_security_protocol" />
+
+            <EditText
+                android:id="@+id/editSpId"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="numberSigned" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_tls_cipher_suite" />
+
+            <EditText
+                android:id="@+id/editTlsCs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="numberSigned" />
+
+            <CheckBox
+                android:id="@+id/checkBoxForce"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/request_force_bootstrapping" />
+
+        </LinearLayout>
+    </ScrollView>
+
+    <LinearLayout
+        android:id="@+id/layout_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="false"
+        android:layout_gravity="bottom"
+        android:orientation="vertical"
+        app:layout_constraintBottom_toBottomOf="parent">
+
+        <Button
+            android:id="@+id/client_config_clear"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_clear" />
+
+        <Button
+            android:id="@+id/client_config_done"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_done" />
+    </LinearLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/testapps/GbaTestApp/res/layout/main_activity.xml b/testapps/GbaTestApp/res/layout/main_activity.xml
new file mode 100644
index 0000000..1dfb73b
--- /dev/null
+++ b/testapps/GbaTestApp/res/layout/main_activity.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" />
\ No newline at end of file
diff --git a/testapps/GbaTestApp/res/layout/main_fragment.xml b/testapps/GbaTestApp/res/layout/main_fragment.xml
new file mode 100644
index 0000000..33bb6e1
--- /dev/null
+++ b/testapps/GbaTestApp/res/layout/main_fragment.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/main"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ui.main.MainFragment">
+
+    <LinearLayout
+        android:id="@+id/layout_config"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:orientation="vertical"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/label_settings" />
+
+        <Button
+            android:id="@+id/carrier_config_change_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/label_carrier" />
+
+        <Button
+            android:id="@+id/service_config"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/label_service" />
+
+        <Button
+            android:id="@+id/client_config"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/label_test" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/layout_test"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:orientation="vertical"
+        app:layout_constraintBottom_toTopOf="@id/layout_exit"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/layout_config">
+
+        <Button
+            android:id="@+id/send_request"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_running" />
+
+        <TextView
+            android:id="@+id/textTestLabel"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/label_test_result" />
+        <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" >
+
+                <TextView
+                    android:id="@+id/viewTestOutput"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"/>
+            </LinearLayout>
+        </ScrollView>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/layout_exit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_gravity="bottom"
+        android:orientation="vertical"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent">
+
+        <Button
+            android:id="@+id/test_exit"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/button_name_exit" />
+    </LinearLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/testapps/GbaTestApp/res/values-af/strings.xml b/testapps/GbaTestApp/res/values-af/strings.xml
new file mode 100644
index 0000000..7f690de
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-af/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Instellings"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Diensverskafferopstelling"</string>
+    <string name="label_service" msgid="2668963955237345578">"Diensopstelling"</string>
+    <string name="label_test" msgid="8425079572898571918">"Toetsopstelling"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Loop tans"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Verlaat"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Toetsresultaat"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Stel terug"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Klaar"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pakketnaam van GBA-diens"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hoe lank voor diens vrygestel word nadat gebel is"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-programtipe"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Netwerkprogramfunksie (NAF) -URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Verplig selflaai?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisasiekode"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID vir UA-sekuriteitsprotokol"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID vir TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-stawingsukses?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Foutrede-ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-sleutel (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Selflaaitransaksie-identifiseerder (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-am/strings.xml b/testapps/GbaTestApp/res/values-am/strings.xml
new file mode 100644
index 0000000..b78cd6c
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-am/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ቅንብሮች"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"የአገልግሎት አቅራቢ ውቅረት"</string>
+    <string name="label_service" msgid="2668963955237345578">"የአገልግሎት ውቅረት"</string>
+    <string name="label_test" msgid="8425079572898571918">"የሙከራ ውቅረት"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"በመስራት ላይ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ውጣ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"የሙከራ ውጤት"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ዳግም አስጀምር"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ተከናውኗል"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"የGBA አገልግሎት የጥቅል ስም"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ጥሪ ከተደረገ በኋላ አገልግሎት የሚለቀቅበት ጊዜ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC የመተግበሪያ አይነት"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"የአውታረ መረብ የመተግበሪያ ተግባር (NAF) ዩአርኤል"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"በማስነሻ ተገዶ ይነሳ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"የድርጅት ኮድ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA የደህንነት ፕሮቶኮል መታወቂያ"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"የTLS ማመስጠሪያ ጥቅል መታወቂያ"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA ማረጋገጥ ተሳክቷል?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ያለመሳካት ምክንያት መታወቂያ"</string>
+    <string name="response_key" msgid="8839847772051686309">"የGBA ቁልፍ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"የማስነሻ የግብይት መለያ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ar/strings.xml b/testapps/GbaTestApp/res/values-ar/strings.xml
new file mode 100644
index 0000000..2c0094b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ar/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"الإعدادات"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"إعداد مشغّل شبكة الجوّال"</string>
+    <string name="label_service" msgid="2668963955237345578">"إعداد الخدمة"</string>
+    <string name="label_test" msgid="8425079572898571918">"اختبار الإعداد"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"العملية جارية"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"خروج"</string>
+    <string name="label_test_result" msgid="892984695972956196">"نتيجة الاختبار"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"إعادة الضبط"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"تم"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"‏اسم الحزمة لخدمة GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"المدة الزمنية المتبقية قبل تفعيل الخدمة بعد الاتصال"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"‏نوع تطبيق UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"‏عنوان URL لوظيفة التطبيقات على الشبكة (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"هل تريد فرض التشغيل التمهيدي؟"</string>
+    <string name="request_org" msgid="8416693445448308975">"رمز المؤسسة"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"‏رقم تعريف بروتوكول أمان UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"رقم تعريف حزمة رموز طبقة النقل الآمنة"</string>
+    <string name="response_success" msgid="2469204471244527663">"‏هل تمت مصادقة GBA بنجاح؟"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"رقم تعريف سبب الإخفاق"</string>
+    <string name="response_key" msgid="8839847772051686309">"‏مفتاح ‏GBA ‏(CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"‏معرّف عملية التشغيل التمهيدي (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-as/strings.xml b/testapps/GbaTestApp/res/values-as/strings.xml
new file mode 100644
index 0000000..3fbba0f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-as/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ছেটিং"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"বাহকৰ কনফিগাৰেশ্বন"</string>
+    <string name="label_service" msgid="2668963955237345578">"সেৱাৰ কনফিগাৰেশ্বন"</string>
+    <string name="label_test" msgid="8425079572898571918">"পৰীক্ষাৰ কনফিগাৰেশ্বন"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"চলি আছে"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"বাহিৰ হওক"</string>
+    <string name="label_test_result" msgid="892984695972956196">"পৰীক্ষাৰ ফলাফল"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ৰিছেট কৰক"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"হ’ল"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA সেৱাৰ পেকেজৰ নাম"</string>
+    <string name="service_release_time" msgid="532937496122890892">"কল কৰাৰ কিমান সময়ৰ পাছত সেৱা প্ৰদান কৰা হ’ব"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC এপৰ প্ৰকাৰ"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"নেটৱৰ্ক এপ্লিকেশ্বন ফাংশ্বন (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"বলেৰে বুটষ্ট্ৰেপিং কৰিবনে?"</string>
+    <string name="request_org" msgid="8416693445448308975">"প্ৰতিষ্ঠানৰ ক’ড"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA সুৰক্ষা প্ৰ’ট’কল আইডি"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite আইডি"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA প্ৰমাণীকৰণ সফল হৈছে নেকি?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ব্যৰ্থতাৰ কাৰণৰ আইডি"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA কী (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"বুটষ্ট্ৰেপিং লেনদেন চিনাক্তকাৰী (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-az/strings.xml b/testapps/GbaTestApp/res/values-az/strings.xml
new file mode 100644
index 0000000..5d78cde
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-az/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ayarlar"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operator konfiqurasiyası"</string>
+    <string name="label_service" msgid="2668963955237345578">"Xidmət konfiqurasiyası"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test konfiqurasiyası"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Proses gedir"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Çıxın"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test nəticəsi"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Sıfırlayın"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Oldu"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA xidmətinin paket adı"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Zəngdən sonra xidməti hansı müddətə buraxmalı"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC tətbiq növü"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Şəbəkə tətbiqi funksiyası (NAF) URL-i"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Öz-özünə yükləməyə müdaxilə edilsin?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Təşkilat kodu"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA təhlükəsizlik protokolu ID-si"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS şifr dəsti ID-si"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA doğrulama alındı?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Uğursuzluq səbəbi ID-si"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA açarı (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Öz-özünə yükləmə tranzaksiyası üzrə identifikator (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-b+sr+Latn/strings.xml b/testapps/GbaTestApp/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..4ae2c86
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Podešavanja"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguracija mobilnog operatera"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguracija usluge"</string>
+    <string name="label_test" msgid="8425079572898571918">"Probna konfiguracija"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Aktivno"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Zatvori"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultat testa"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetuj"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Gotovo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Naziv paketa usluge GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Vreme dok se usluga ne aktivira posle poziva"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tip UICC aplikacije"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL funkcije mrežne aplikacije (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Želite li da nametnete samostalno uzorkovanje?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kôd organizacije"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID bezbednosnog protokola univerzalne analitike"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID TLS paketa za šifrovanje"</string>
+    <string name="response_success" msgid="2469204471244527663">"Da li je potvrda identiteta za GBA uspela?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID razloga za neuspeh"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA taster (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikator transakcije za samostalno uzorkovanje (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-be/strings.xml b/testapps/GbaTestApp/res/values-be/strings.xml
new file mode 100644
index 0000000..d9d8f35
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-be/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Налады"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Канфігурацыя аператара"</string>
+    <string name="label_service" msgid="2668963955237345578">"Канфігурацыя сэрвісу"</string>
+    <string name="label_test" msgid="8425079572898571918">"Тэставая канфігурацыя"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Выконваецца"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Выйсці"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Вынік тэсціравання"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Скінуць"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Гатова"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Назва пакета сэрвісу GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Час вызвалення сэрвісу пасля выкліку"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тып праграмы UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL-адрас функцыі сеткавай праграмы (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Выканаць пачатковую загрузку прымусова?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Код арганізацыі"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Ідэнтыфікатар пратакола бяспекі UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Ідэнтыфікатар пакета шыфравання TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Аўтэнтыфікацыя GBA выканана?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Ідэнтыфікатар прычыны памылкі"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ключ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Ідэнтыфікатар трансакцыі пачатковай загрузкі (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-bg/strings.xml b/testapps/GbaTestApp/res/values-bg/strings.xml
new file mode 100644
index 0000000..664b304
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-bg/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Настройки"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Конфигурация от оператора"</string>
+    <string name="label_service" msgid="2668963955237345578">"Конфигурация на услугата"</string>
+    <string name="label_test" msgid="8425079572898571918">"Конфигурация на теста"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Изпълнява се"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Изход"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Резултат от теста"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Повторно задаване"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Готово"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Име на пакета за услугата GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Колко време след обаждането да бъде освободена услугата"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тип на приложението в UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL адрес на функцията за мрежово приложение (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Да се извърши ли принудително начално зареждане?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Код на организацията"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Идентификатор на протокола за сигурност в UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Идентификатор на пакета за шифроване с TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Упълномощаването в GBA успя ли?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Идентификатор на причината за неуспех"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ключ за GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Идентификатор на транзакцията при начално зареждане (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-bn/strings.xml b/testapps/GbaTestApp/res/values-bn/strings.xml
new file mode 100644
index 0000000..c661312
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-bn/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"সেটিংস"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"পরিষেবা প্রদানকারী কনফিগার করুন"</string>
+    <string name="label_service" msgid="2668963955237345578">"পরিষেবা কনফিগার করুন"</string>
+    <string name="label_test" msgid="8425079572898571918">"টেস্ট কনফিগার করুন"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"চলছে"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"বেরিয়ে আসুন"</string>
+    <string name="label_test_result" msgid="892984695972956196">"টেস্টের ফলাফল"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"রিসেট করুন"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"হয়ে গেছে"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA পরিষেবা সংক্রান্ত প্যাকেজের নাম"</string>
+    <string name="service_release_time" msgid="532937496122890892">"কল করার কতক্ষণ পরে পরিষেবা পাওয়া যাবে"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC অ্যাপের ধরন"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"নেটওয়ার্ক অ্যাপ্লিকেশনের কাজ (NAF) সংক্রান্ত URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"জোর করেই বুটস্ট্র্যাপিং করবেন?"</string>
+    <string name="request_org" msgid="8416693445448308975">"অর্গানাইজেশনের কোড"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA নিরাপত্তা সংক্রান্ত আইডি"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS গোপন কোডের স্যুট ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA যাচাই করা গেছে?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ব্যর্থতার কারণ সংক্রান্ত ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA কী (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"বুটস্ট্র্যাপিং ট্রানজ্যাকশন শনাক্তকারী (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-bs/strings.xml b/testapps/GbaTestApp/res/values-bs/strings.xml
new file mode 100644
index 0000000..1cfc0d1
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-bs/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Postavke"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguracija mobilnog operatera"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguracija usluge"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testna konfiguracija"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Pokrenuto"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Izađi"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultati testa"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Vrati na zadano"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Gotovo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Ime paketa usluge GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Vrijeme prije nego se usluga aktivira nakon pozivanja"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Vrsta aplikacije UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL funkcije mrežne aplikacije (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Prisilno omogućiti metodu ponovnog uzorkovanja?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kôd organizacije"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID sigurnosnog protokola UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID paketa TLS Cipher"</string>
+    <string name="response_success" msgid="2469204471244527663">"Uspjeli ste izvršiti autorizaciju GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID razloga za neuspjeh"</string>
+    <string name="response_key" msgid="8839847772051686309">"Tipka GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikator transakcije za metodu ponovnog uzorkovanja (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ca/strings.xml b/testapps/GbaTestApp/res/values-ca/strings.xml
new file mode 100644
index 0000000..83991ac
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ca/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Configuració"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuració de l\'operador"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuració del servei"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuració de la prova"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"S\'està executant"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Surt"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultat de la prova"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Restableix"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Fet"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nom de paquet del servei de GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Temps per desvincular el servei després de la trucada"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipus d\'aplicació UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL de la funció d\'aplicació de xarxa (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Vols forçar l\'arrencada?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Codi d\'organització"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Identificador de protocol de seguretat d\'UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Identificador de sistema de xifratge TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Autenticació de GBA correcta?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Identificador de motiu d\'error"</string>
+    <string name="response_key" msgid="8839847772051686309">"Clau GBA (CK i IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador de transacció d\'arrencada (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-cs/strings.xml b/testapps/GbaTestApp/res/values-cs/strings.xml
new file mode 100644
index 0000000..59b50b5
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-cs/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Nastavení"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfigurace operátora"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfigurace služby"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfigurace testu"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Běží"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Ukončit"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Výsledek testu"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetovat"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Hotovo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Název balíčku služby GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Za jak dlouho po volání uvolnit službu"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Typ aplikace UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Adresa URL funkce síťové aplikace (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Vynutit bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kód organizace"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID protokolu zabezpečení UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID sady šifer TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Úspěšné ověření GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID důvodu selhání"</string>
+    <string name="response_key" msgid="8839847772051686309">"Klíč GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikátor transakce bootstrappingu (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-da/strings.xml b/testapps/GbaTestApp/res/values-da/strings.xml
new file mode 100644
index 0000000..1c3860d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-da/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Indstillinger"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguration af mobilselskab"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguration af tjeneste"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test konfiguration"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Kører"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Afslut"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testresultat"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Nulstil"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Udfør"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pakkenavn på GBA-tjeneste"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hvor lang tid der går, før tjenesten frigives efter opkaldet"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-apptype"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Webadresse til NAF (Network application function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Vil du gennemtvinge bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisationskode"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Id for UA-sikkerhedsprotokol"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Id for TLS-krypteringsalgoritmepakke"</string>
+    <string name="response_success" msgid="2469204471244527663">"Blev GBA godkendt?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Id for fejlårsag"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-tat (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Transaktions-id for bootstrapping (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-de/strings.xml b/testapps/GbaTestApp/res/values-de/strings.xml
new file mode 100644
index 0000000..2b575aa
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-de/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Einstellungen"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguration des Mobilfunkanbieters"</string>
+    <string name="label_service" msgid="2668963955237345578">"Dienstkonfiguration"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testkonfiguration"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Wird ausgeführt"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Beenden"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testergebnis"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Zurücksetzen"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Fertig"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Paketname des GBA-Diensts"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Dauer bis zur Freigabe des Diensts nach Aufruf"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-App-Typ"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"NAF-URL (Netzwerkanwendungsfunktion)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Bootstrapping erzwingen?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisationscode"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID für UA-Sicherheitsprotokoll"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite-ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-Authentifizierung erfolgreich?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID der Fehlerursache"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-Schlüssel (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping-Transaktions-ID (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-el/strings.xml b/testapps/GbaTestApp/res/values-el/strings.xml
new file mode 100644
index 0000000..574842d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-el/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ρυθμίσεις"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Διαμόρφωση παρόχου"</string>
+    <string name="label_service" msgid="2668963955237345578">"Διαμόρφωση υπηρεσίας"</string>
+    <string name="label_test" msgid="8425079572898571918">"Διαμόρφωση δοκιμής"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Σε εξέλιξη"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Έξοδος"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Αποτέλεσμα δοκιμής"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Επαναφορά"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Τέλος"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Όνομα πακέτου υπηρεσίας GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Διάρκεια αποδέσμευσης υπηρεσίας μετά την κλήση"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Τύπος εφαρμογής UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL λειτουργίας εφαρμογής δικτύου (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Επιβολή εκκίνησης;"</string>
+    <string name="request_org" msgid="8416693445448308975">"Κωδικός Οργανισμού"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Αναγνωριστικό πρωτοκόλλου ασφαλείας UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Αναγνωριστικό TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"Επιτυχία GBA Auth;"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Αναγνωριστικό αιτίου αποτυχίας"</string>
+    <string name="response_key" msgid="8839847772051686309">"Κλειδί GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Αναγνωριστικό συναλλαγής εκκίνησης (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-en-rAU/strings.xml b/testapps/GbaTestApp/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..6c4a199
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-en-rAU/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Settings"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operator config"</string>
+    <string name="label_service" msgid="2668963955237345578">"Service config"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test config"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Exit"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test result"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Done"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Package name of GBA service"</string>
+    <string name="service_release_time" msgid="532937496122890892">"How long to release service after calling"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC app type"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Network application function (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Force bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisation code"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA security protocol ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS cipher suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA auth success?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Fail reason ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA key (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping transaction identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-en-rCA/strings.xml b/testapps/GbaTestApp/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..6c4a199
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-en-rCA/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Settings"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operator config"</string>
+    <string name="label_service" msgid="2668963955237345578">"Service config"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test config"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Exit"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test result"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Done"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Package name of GBA service"</string>
+    <string name="service_release_time" msgid="532937496122890892">"How long to release service after calling"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC app type"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Network application function (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Force bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisation code"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA security protocol ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS cipher suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA auth success?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Fail reason ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA key (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping transaction identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-en-rGB/strings.xml b/testapps/GbaTestApp/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..6c4a199
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-en-rGB/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Settings"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operator config"</string>
+    <string name="label_service" msgid="2668963955237345578">"Service config"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test config"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Exit"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test result"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Done"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Package name of GBA service"</string>
+    <string name="service_release_time" msgid="532937496122890892">"How long to release service after calling"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC app type"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Network application function (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Force bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisation code"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA security protocol ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS cipher suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA auth success?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Fail reason ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA key (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping transaction identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-en-rIN/strings.xml b/testapps/GbaTestApp/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..6c4a199
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-en-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Settings"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operator config"</string>
+    <string name="label_service" msgid="2668963955237345578">"Service config"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test config"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Exit"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test result"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Done"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Package name of GBA service"</string>
+    <string name="service_release_time" msgid="532937496122890892">"How long to release service after calling"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC app type"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Network application function (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Force bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisation code"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA security protocol ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS cipher suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA auth success?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Fail reason ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA key (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping transaction identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-en-rXC/strings.xml b/testapps/GbaTestApp/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..e3fe56b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-en-rXC/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎GbaTestApp‎‏‎‎‏‎"</string>
+    <string name="label_settings" msgid="8030871890526865502">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎Settings‎‏‎‎‏‎"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎Carrier Config‎‏‎‎‏‎"</string>
+    <string name="label_service" msgid="2668963955237345578">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎Service Config‎‏‎‎‏‎"</string>
+    <string name="label_test" msgid="8425079572898571918">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎Test Config‎‏‎‎‏‎"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎Running‎‏‎‎‏‎"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎Exit‎‏‎‎‏‎"</string>
+    <string name="label_test_result" msgid="892984695972956196">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎Test Result‎‏‎‎‏‎"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎Reset‎‏‎‎‏‎"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎Done‎‏‎‎‏‎"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‎CarrierConfigActivity‎‏‎‎‏‎"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎ServiceConfigActivity‎‏‎‎‏‎"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎TestConfigActivity‎‏‎‎‏‎"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎Package name of GBA service‎‏‎‎‏‎"</string>
+    <string name="service_release_time" msgid="532937496122890892">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎How long to release service after calling‎‏‎‎‏‎"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎UICC App Type‎‏‎‎‏‎"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎Network application function (NAF) URL‎‏‎‎‏‎"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎Force Bootstrapping?‎‏‎‎‏‎"</string>
+    <string name="request_org" msgid="8416693445448308975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎Organization Code‎‏‎‎‏‎"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎UA Security Protocol ID‎‏‎‎‏‎"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎TLS Cipher Suite ID‎‏‎‎‏‎"</string>
+    <string name="response_success" msgid="2469204471244527663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎GBA Auth Success?‎‏‎‎‏‎"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎Fail Reason ID‎‏‎‎‏‎"</string>
+    <string name="response_key" msgid="8839847772051686309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎GBA Key (CK + IK)‎‏‎‎‏‎"</string>
+    <string name="response_btid" msgid="2550216722679350756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎Bootstrapping Transaction Identifier (B-TID)‎‏‎‎‏‎"</string>
+    <string name="sample_naf" msgid="255371174145881001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎3GPP-bootstrapping@naf1.operator.com‎‏‎‎‏‎"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎(B-TID)‎‏‎‎‏‎"</string>
+    <string name="sample_key" msgid="3337589659405527482">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎6629fae49393a05397450978507c4ef1‎‏‎‎‏‎"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-es-rUS/strings.xml b/testapps/GbaTestApp/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..cbe3542
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-es-rUS/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Configuración"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuración del proveedor"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuración del servicio"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuración de prueba"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"En ejecución"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Salir"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultado de la prueba"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Restablecer"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Listo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nombre del paquete del servicio de GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Cuánto tarda en liberarse el servicio después de llamar"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo de app UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL de función de aplicaciones de red (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"¿Quieres forzar el arranque?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Código de organización"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID del protocolo de seguridad de UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID de paquete de algoritmo de cifrado TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"¿Se completó la autenticación de GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID de motivo de error"</string>
+    <string name="response_key" msgid="8839847772051686309">"Llave de GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador de transacción de arranque (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-es/strings.xml b/testapps/GbaTestApp/res/values-es/strings.xml
new file mode 100644
index 0000000..bde5d92
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-es/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ajustes"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuración del operador"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuración del servicio"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuración de la prueba"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"En ejecución"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Salir"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultado de la prueba"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Restablecer"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Listo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nombre de paquete del servicio GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Durante cuánto tiempo se debe desenlazar el servicio tras la llamada"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo de aplicación UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL de la función de aplicación de red (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"¿Forzar arranque?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Código de la organización"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID del protocolo de seguridad de UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID del conjunto de algoritmos de cifrado TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"¿Autorización GBA correcta?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID del motivo del error"</string>
+    <string name="response_key" msgid="8839847772051686309">"Llave GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador de transacción de arranque (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-et/strings.xml b/testapps/GbaTestApp/res/values-et/strings.xml
new file mode 100644
index 0000000..d1bb73e
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-et/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Seaded"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operaatori seadistamine"</string>
+    <string name="label_service" msgid="2668963955237345578">"Teenuse seadistamine"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testi seadistamine"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Töötab"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Välju"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testi tulemus"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Lähtesta"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Valmis"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA teenuse paketi nimi"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Teenuse vabastusaeg pärast helistamist"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC rakenduse tüüp"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Võrgurakenduse funktsiooni (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Kas sundida alglaadimine?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisatsiooni kood"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA turvaprotokolli ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS-i šifrikomplekti ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"Kas GBA autentimine õnnestus?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Nurjumise põhjuse ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA võti (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Alglaadimise tehingu identifikaator (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-eu/strings.xml b/testapps/GbaTestApp/res/values-eu/strings.xml
new file mode 100644
index 0000000..6774d99
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-eu/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ezarpenak"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operadorearen konfigurazioa"</string>
+    <string name="label_service" msgid="2668963955237345578">"Zerbitzuaren konfigurazioa"</string>
+    <string name="label_test" msgid="8425079572898571918">"Probako konfigurazioa"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Abian"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Irten"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Probaren emaitza"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Berrezarri"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Eginda"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA zerbitzuaren paketearen izena"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Deitu ondoren zerbitzua libre uzteko igarotzen den denbora"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC aplikazio mota"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Sareko aplikazioaren funtzioaren (NAF) URLa"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Bootstrapping-a erabiltzera behartu nahi duzu?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Erakundearen kodea"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA segurtasun-protokoloaren IDa"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"Burutu da GBA autentifikazioa?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Hutsegitearen arrazoiaren IDa"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-ko gakoa (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-fa/strings.xml b/testapps/GbaTestApp/res/values-fa/strings.xml
new file mode 100644
index 0000000..92801e7
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-fa/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"تنظیمات"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"پیکربندی شرکت مخابراتی"</string>
+    <string name="label_service" msgid="2668963955237345578">"پیکربندی سرویس"</string>
+    <string name="label_test" msgid="8425079572898571918">"پیکربندی آزمایش"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"درحال اجرا"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"خروج"</string>
+    <string name="label_test_result" msgid="892984695972956196">"نتیجه آزمایش"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"بازنشانی"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"تمام"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"‏نام بسته سرویس «معماری خود راه‌اندازی فراگیر» (GBA)"</string>
+    <string name="service_release_time" msgid="532937496122890892">"مدت زمان عرضه سرویس بعداز تماس"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"‏نوع برنامه «کارت مدار مجتمع جهانی» (UICC)"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"‏نشانی وب «عملکرد برنامه شبکه» (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"«خود راه‌اندازی» به‌صورت اجباری اجرا شود؟"</string>
+    <string name="request_org" msgid="8416693445448308975">"کد سازمان"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"‏شناسه پروتکل امنیتی UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"شناسه مجموعه رمزنگاری امنیت لایه انتقال"</string>
+    <string name="response_success" msgid="2469204471244527663">"‏احراز هویت «معماری خود راه‌اندازی فراگیر» (GBA) موفق بود؟"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"شناسه دلیل انجام نشدن"</string>
+    <string name="response_key" msgid="8839847772051686309">"‏کلید «معماری خود راه‌اندازی فراگیر» (GBA)‏ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"‏شناسه تبادل خود راه‌اندازی (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-fi/strings.xml b/testapps/GbaTestApp/res/values-fi/strings.xml
new file mode 100644
index 0000000..ad5862d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-fi/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Asetukset"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operaattorin määritys"</string>
+    <string name="label_service" msgid="2668963955237345578">"Palvelun määritys"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testimääritys"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Käynnissä"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Sulje"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testitulokset"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Nollaa"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Valmis"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA-palvelun paketin nimi"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Kuinka pian soittamisen jälkeen palvelu vapautetaan"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-sovelluksen tyyppi"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"NAF-URL-osoite (Network Application Function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Pakotetaanko käynnistäminen?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisaation koodi"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA-suojausprotokollan tunnus"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS-salauspaketin tunnus"</string>
+    <string name="response_success" msgid="2469204471244527663">"Onnistuiko GBA-todennus?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Epäonnistumisen syyn tunnus"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-avain (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"B-TID (Bootstrapping Transaction Identifier)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-fr-rCA/strings.xml b/testapps/GbaTestApp/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..2c7abc6
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-fr-rCA/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Paramètres"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuration d\'opérateur"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuration de service"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuration de test"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"En cours d\'exécution…"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Quitter"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Résultat du test"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Réinitialiser"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"OK"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nom de l\'ensemble de service GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Délai de libération du service après un appel"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Type d\'application UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL de fonction d\'application réseau (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forcer l\'amorçage?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Code d\'organisation"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Identifiant de protocole de sécurité UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Identifiant de suite de chiffrement TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Réussite d\'autorisation GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Identifiant de motif d\'échec"</string>
+    <string name="response_key" msgid="8839847772051686309">"Clé GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifiant de transaction d\'amorçage (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-fr/strings.xml b/testapps/GbaTestApp/res/values-fr/strings.xml
new file mode 100644
index 0000000..a396bae
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-fr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Paramètres"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuration de l\'opérateur"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuration du service"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuration de test"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"En cours d\'exécution"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Quitter"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Résultat du test"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Réinitialiser"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"OK"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nom de package du service GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Intervalle entre l\'appel de l\'API et l\'activation du service"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Type d\'application UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL de la fonction d\'application réseau (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forcer l\'amorçage ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Code d\'organisation"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID de protocole de sécurité UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID de suite de chiffrement TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Réussite de l\'authentification GBA ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID du motif de l\'échec"</string>
+    <string name="response_key" msgid="8839847772051686309">"Clé GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifiant de transaction d\'amorçage (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-gl/strings.xml b/testapps/GbaTestApp/res/values-gl/strings.xml
new file mode 100644
index 0000000..d5547c7
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-gl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Configuración"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuración do operador"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuración do servizo"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuración da proba"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"En execución"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Saír"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultado da proba"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Restablecer"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Feito"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nome do paquete do servizo de GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Tempo que se tarda en desvincular o servizo despois da chamada"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo de aplicación UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL da función de aplicacións de rede (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Queres forzar o arranque?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Código da organización"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Código do protocolo de seguranza UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Código do paquete de cifraxe TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Completouse a autenticación de GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Código do motivo de erro"</string>
+    <string name="response_key" msgid="8839847772051686309">"Chave de GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador da transacción de arranque (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-gu/strings.xml b/testapps/GbaTestApp/res/values-gu/strings.xml
new file mode 100644
index 0000000..b43ecad
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-gu/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"સેટિંગ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"મોબાઇલ ઑપરેટરની ગોઠવણી"</string>
+    <string name="label_service" msgid="2668963955237345578">"સેવાની ગોઠવણી"</string>
+    <string name="label_test" msgid="8425079572898571918">"પરીક્ષણની ગોઠવણી"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ચાલે છે"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"બહાર નીકળો"</string>
+    <string name="label_test_result" msgid="892984695972956196">"પરીક્ષણનું પરિણામ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"રીસેટ કરો"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"થઈ ગયું"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA સેવાનું પૅકેજિંગ નામ"</string>
+    <string name="service_release_time" msgid="532937496122890892">"કૉલ કર્યા પછી કેટલા સમયે સેવા રિલીઝ કરવી, તે સમયગાળો"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ઍપ પ્રકાર"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"નેટવર્ક ઍપ્લિકેશન કાર્ય (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"શું બળજબરીથી બૂટસ્ટ્રેપિંગ કરીએ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"સંસ્થાનો કોડ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA સિક્યુરિટી પ્રોટોકૉલ ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS સાઇફર સ્યૂટ ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA Aપ્રમાણીકરણ સફળ થયું?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"નિષ્ફળતા કારણ ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA કી (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"બૂટસ્ટ્રેપિંગ વ્યવહાર ઓળખકર્તા (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-hi/strings.xml b/testapps/GbaTestApp/res/values-hi/strings.xml
new file mode 100644
index 0000000..442d65f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-hi/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"सेटिंग"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का कॉन्फ़िगरेशन"</string>
+    <string name="label_service" msgid="2668963955237345578">"सेवा का कॉन्फ़िगरेशन"</string>
+    <string name="label_test" msgid="8425079572898571918">"टेस्ट के लिए कॉन्फ़िगरेशन"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"चल रहा है"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"बाहर निकलें"</string>
+    <string name="label_test_result" msgid="892984695972956196">"टेस्ट का नतीजा"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"रीसेट करें"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"हो गया"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA सेवा के पैकेज का नाम"</string>
+    <string name="service_release_time" msgid="532937496122890892">"प्रोग्राम चालू करने के बाद, सेवा शुरू होने में कितना समय लगेगा"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ऐप्लिकेशन टाइप"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"नेटवर्क ऐप्लिकेशन फ़ंक्शन (NAF) यूआरएल"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"क्या आप ज़बरदस्ती बूटस्ट्रैपिंग करना चाहते हैं?"</string>
+    <string name="request_org" msgid="8416693445448308975">"संगठन कोड"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA सिक्योरिटी प्रोटोकॉल आईडी"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS साइफ़र सुइट आईडी"</string>
+    <string name="response_success" msgid="2469204471244527663">"क्या GBA की पुष्टि हुई?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ऐप्लिकेशन लोड नहीं हो पाने की वजह का आईडी"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA कुंजी (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"बूटस्ट्रैपिंग ट्रांज़ैक्शन आइडेंटिफ़ायर (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-hr/strings.xml b/testapps/GbaTestApp/res/values-hr/strings.xml
new file mode 100644
index 0000000..4215e31
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-hr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Postavke"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguracija mobilnog operatera"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguracija usluge"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfiguracija testa"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"U tijeku"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Izlaz"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultat testa"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Poništi"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Gotovo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Naziv paketa usluge GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Vrijeme do aktivacije usluge nakon poziva"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Vrsta aplikacije UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL funkcije mrežne aplikacije (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Želite li prisilno pokrenuti program?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organizacijski kod"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID sigurnosnog protokola UA-a"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID paketa šifriranja za TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Uspješna autentifikacija GBA-a?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID razloga neuspjeha"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA ključ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikator transakcije pokretanja programa (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-hu/strings.xml b/testapps/GbaTestApp/res/values-hu/strings.xml
new file mode 100644
index 0000000..a574220
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-hu/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Beállítások"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Szolgáltatói konfiguráció"</string>
+    <string name="label_service" msgid="2668963955237345578">"Szolgáltatáskonfiguráció"</string>
+    <string name="label_test" msgid="8425079572898571918">"Tesztkonfiguráció"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Fut"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Kilépés"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Teszteredmények"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Alaphelyzet"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Kész"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"A GBA-szolgáltatás csomagneve"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Ennyi idő múlva szabaduljon fel a szolgáltatás a hívás után"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-alkalmazástípus"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Hálózati alkalmazásfunkció (NAF) URL-címe"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Kényszeríti a rendszerbetöltést?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Szervezet kódja"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA biztonsági protokoll azonosítója"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS titkosítási csomag azonosítója"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-hitelesítés sikeres?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Hiba okának azonosítója"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-kulcs (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Rendszertöltési tranzakció azonosítója (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-hy/strings.xml b/testapps/GbaTestApp/res/values-hy/strings.xml
new file mode 100644
index 0000000..7c306c1
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-hy/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Կարգավորումներ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Օպերատորի կարգավորում"</string>
+    <string name="label_service" msgid="2668963955237345578">"Ծառայության կարգավորում"</string>
+    <string name="label_test" msgid="8425079572898571918">"Փորձարկման կարգավորում"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Աշխատանք"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Դուրս գալ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Փորձարկման արդյունքը"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Վերակայել"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Պատրաստ է"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA ծառայության փաթեթի անունը"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Որքան ժամանակով դադարեցնել ծառայությունը զանգից հետո"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC հավելվածի տեսակը"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Ցանցային հավելվածի գործառույթի (Network application function, NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Հարկադրե՞լ բութսթրափ"</string>
+    <string name="request_org" msgid="8416693445448308975">"Կազմակերպության կոդը"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA անվտանգության հաղորդակարգի ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS ծածկագրերի հավաքածուի ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA նույնականացումը հաջողվե՞ց"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Սխալի պատճառի ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA բանալի (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Բութսթրափի գործարքի նույնացուցիչ (Bootstrapping Transaction Identifier, B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-in/strings.xml b/testapps/GbaTestApp/res/values-in/strings.xml
new file mode 100644
index 0000000..cd5b0a8
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-in/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Setelan"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfigurasi Operator"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfigurasi Layanan"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfigurasi Pengujian"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Berjalan"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Keluar"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Hasil Uji"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Selesai"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nama paket layanan GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Berapa lama merilis layanan setelah panggilan"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Jenis Aplikasi UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL fungsi aplikasi jaringan (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Paksa Bootstrap?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kode Organisasi"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID Protokol Keamanan UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"Autentikasi GBA Berhasil?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID Alasan Gagal"</string>
+    <string name="response_key" msgid="8839847772051686309">"Tombol GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ID Transaksi Bootstrap (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-is/strings.xml b/testapps/GbaTestApp/res/values-is/strings.xml
new file mode 100644
index 0000000..926d220
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-is/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Stillingar"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Grunnstilling símafyrirtækis"</string>
+    <string name="label_service" msgid="2668963955237345578">"Grunnstilling þjónustu"</string>
+    <string name="label_test" msgid="8425079572898571918">"Grunnstilling prófs"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Í gangi"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Hætta"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Prófniðurstöður"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Endurstilla"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Lokið"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pakkaheiti GBA-þjónustu"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hversu lengi skal losa þjónustu eftir kall"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-forritsgerð"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Vefslóð NAF-þjónustu (Network application function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Þvinga ræsingu?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Fyrirtækiskóði"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Auðkenni UA-öryggisreglu"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Auðkenni TLS-dulritunarsafns"</string>
+    <string name="response_success" msgid="2469204471244527663">"Tókst GBA-auðkenning?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Auðkenni ástæðu mistaka"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-lykill (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"B-TID-auðkenni (Bootstrapping Transaction Identifier)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-it/strings.xml b/testapps/GbaTestApp/res/values-it/strings.xml
new file mode 100644
index 0000000..00409d3
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-it/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Impostazioni"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configurazione operatore"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configurazione servizio"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configurazione test"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"In esecuzione"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Esci"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Risultato test"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Reimposta"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Fine"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nome pacchetto del servizio GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Intervallo di tempo tra la chiamata dell\'API e l\'attivazione del servizio"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo di app UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL NAF (Network Application Function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forzare il bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Codice organizzazione"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID protocollo sicurezza UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID pacchetto crittografia TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Autenticazione GBA riuscita?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID motivo errore"</string>
+    <string name="response_key" msgid="8839847772051686309">"Chiave GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificatore transazione bootstrapping (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-iw/strings.xml b/testapps/GbaTestApp/res/values-iw/strings.xml
new file mode 100644
index 0000000..76412fa
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-iw/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"הגדרות"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"הגדרת הספק"</string>
+    <string name="label_service" msgid="2668963955237345578">"הגדרת השירות"</string>
+    <string name="label_test" msgid="8425079572898571918">"הגדרת הבדיקה"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"בפעולה"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"יציאה"</string>
+    <string name="label_test_result" msgid="892984695972956196">"תוצאת הבדיקה"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"איפוס"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"סיום"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"‏שם החבילה של שירות GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"תוך כמה זמן לשחרר את השירות אחרי השיחה?"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"‏סוג אפליקציית UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"‏כתובת ה-URL של פונקציית היישום של הרשת (‏NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"‏לאלץ אתחול מסוג Bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"קוד הארגון"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"‏מזהה פרוטוקול אבטחה של UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"‏מזהה חבילת הצפנה של TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"‏האם אימות GBA בוצע בהצלחה?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"מזהה סיבת כישלון"</string>
+    <string name="response_key" msgid="8839847772051686309">"‏מפתח GBA (‏CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"‏מזהה טרנזקציית אתחול מסוג Bootstrapping (‏B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ja/strings.xml b/testapps/GbaTestApp/res/values-ja/strings.xml
new file mode 100644
index 0000000..7cb53e8
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ja/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"設定"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"携帯通信会社の設定"</string>
+    <string name="label_service" msgid="2668963955237345578">"サービスの設定"</string>
+    <string name="label_test" msgid="8425079572898571918">"テストの設定"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"実行中"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"終了"</string>
+    <string name="label_test_result" msgid="892984695972956196">"テスト結果"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"リセット"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"完了"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA サービスのパッケージ名"</string>
+    <string name="service_release_time" msgid="532937496122890892">"呼び出してからサービスがリリースされるまでの時間"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC アプリの種類"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ネットワーク アプリケーション ファンクション(NAF)の URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ブートストラップを強制実行しますか?"</string>
+    <string name="request_org" msgid="8416693445448308975">"組織コード"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA セキュリティ プロトコル ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS 暗号スイート ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA 認証は成功しましたか?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"失敗理由 ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA キー(CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ブートストラップ トランザクション識別子(B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ka/strings.xml b/testapps/GbaTestApp/res/values-ka/strings.xml
new file mode 100644
index 0000000..2baf3f6
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ka/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"პარამეტრები"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"კურიერის კონფიგურაცია"</string>
+    <string name="label_service" msgid="2668963955237345578">"სერვისის კონფიგურაცია"</string>
+    <string name="label_test" msgid="8425079572898571918">"ტესტის კონფიგურაცია"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"სირბილი"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"გასვლა"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ტესტის შედეგი"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"გადაყენება"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"მზადაა"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA სერვისის პაკეტის ნომერი"</string>
+    <string name="service_release_time" msgid="532937496122890892">"რამდენ ხანში მოხდეს სერვისის გამოშვება დარეკვის შემდეგ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC აპის ტიპი"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ქსელური აპლიკაციის ფუნქციის (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"გსურთ Bootstrap-ის იძულებით გაშვება?"</string>
+    <string name="request_org" msgid="8416693445448308975">"ორგანიზაციის კოდი"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA უსაფრთხოების პროტოკოლის ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS შიფრების ნაკრების ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA ავტორიზაცია წარმატებულია?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"მარცხის მიზეზის ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA კლავიში (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrap ტრანსაქციის იდენტიფიკატორი (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-kk/strings.xml b/testapps/GbaTestApp/res/values-kk/strings.xml
new file mode 100644
index 0000000..a34d08d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-kk/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Параметрлер"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Оператор конфигурациясы"</string>
+    <string name="label_service" msgid="2668963955237345578">"Қызмет конфигурациясы"</string>
+    <string name="label_test" msgid="8425079572898571918">"Сынақ конфигурациясы"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Жұмыс істеп тұр"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Шығу"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Сынақ нәтижесі"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Қайтару"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Дайын"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA қызметі пакетінің атауы"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Қоңырау шалғаннан кейін қызметті босату ұзақтығы"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC қолданба түрі"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Желілік қолданба функциясының (NAF) URL мекенжайы"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Бастапқы жүктеуді мәжбүрлеп орындау қажет пе?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Ұйым коды"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA қауіпсіздік протоколының идентификаторы"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS шифрлар жинағының идентификаторы"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA авторизациясы орындалды ма?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Ақаулық себебінің идентификаторы"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA кілті (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Бастапқы жүктеу транзакциясының идентификаторы (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-km/strings.xml b/testapps/GbaTestApp/res/values-km/strings.xml
new file mode 100644
index 0000000..390cef0
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-km/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ការ​កំណត់"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"ការកំណត់រចនាសម្ព័ន្ធ​ក្រុមហ៊ុនសេវាទូរសព្ទ"</string>
+    <string name="label_service" msgid="2668963955237345578">"ការកំណត់រចនា​សម្ព័ន្ធសេវាកម្ម"</string>
+    <string name="label_test" msgid="8425079572898571918">"ការកំណត់រចនាសម្ព័ន្ធ​ការធ្វើតេស្ត"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"កំពុង​ដំណើរការ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ចាកចេញ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"លទ្ធផលធ្វើតេស្ត"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"កំណត់​ឡើងវិញ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"រួចរាល់"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"ឈ្មោះកញ្ចប់​នៃសេវាកម្ម GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"រយៈពេលដែល​ត្រូវបញ្ចេញសេវាកម្ម បន្ទាប់ពីហៅទូរសព្ទ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"ប្រភេទកម្មវិធី UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"មុខងារកម្មវិធីបណ្ដាញ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"បង្ខំ Bootstrapping ឬ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"កូដរៀបចំ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"លេខសម្គាល់​ប្រូតូកូលសុវត្ថិភាព UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"លេខសម្គាល់​កម្មវិធីកញ្ចប់ TLS Cipher"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA Auth ជោគជ័យដែរទេ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"លេខសម្គាល់មូលហេតុ​ដែលមិនដំណើរការ"</string>
+    <string name="response_key" msgid="8839847772051686309">"គ្រាប់ចុច GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ព័ត៌មានសម្គាល់​ប្រតិបត្តិការ Bootstrapping (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-kn/strings.xml b/testapps/GbaTestApp/res/values-kn/strings.xml
new file mode 100644
index 0000000..d37f0f5
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-kn/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"ವಾಹಕ ಕಾನ್ಫಿಗ್"</string>
+    <string name="label_service" msgid="2668963955237345578">"ಸೇವೆ ಕಾನ್ಫಿಗ್"</string>
+    <string name="label_test" msgid="8425079572898571918">"ಪರೀಕ್ಷಾ ಕಾನ್ಫಿಗ್"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ರನ್ನಿಂಗ್"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ನಿರ್ಗಮಿಸಿ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ಪರೀಕ್ಷಾ ಫಲಿತಾಂಶ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ಮರುಹೊಂದಿಸಿ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ಮುಗಿದಿದೆ"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA ಸೇವೆಯ ಪ್ಯಾಕೇಜ್ ಹೆಸರು"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ಕರೆ ಮಾಡಿದ ನಂತರ ಎಷ್ಟು ಸಮಯದವರೆಗೆ ಸೇವೆಯನ್ನು ಬಿಡುಗಡೆ ಮಾಡುವುದು"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ಆ್ಯಪ್‌ ಪ್ರಕಾರ"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ನೆಟ್‌ವರ್ಕ್ ಅಪ್ಲಿಕೇಶನ್ ಫಂಕ್ಷನ್ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ಬೂಟ್ ಸ್ಟ್ರಾಪಿಂಗ್ ಸ್ಥಗಿತಗೊಳಿಸುವುದೇ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"ಸಂಸ್ಥೆ ಕೋಡ್"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA ಭದ್ರತಾ ಪ್ರೊಟೊಕಾಲ್ ಐಡಿ"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS ಸೈಫರ್ ಸೂಟ್ ಐಡಿ"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA ಪ್ರಮಾಣೀಕರಣ ಯಶಸ್ವಿಯಾಗಿದೆಯೇ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ವಿಫಲವಾದ ಕಾರಣ ಐಡಿ"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA ಕೀ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ಬೂಟ್ ಸ್ಟ್ರಾಪಿಂಗ್ ವಹಿವಾಟು ಗುರುತಿಸುವಿಕೆ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ko/strings.xml b/testapps/GbaTestApp/res/values-ko/strings.xml
new file mode 100644
index 0000000..96ac378
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ko/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"설정"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"이동통신사 구성"</string>
+    <string name="label_service" msgid="2668963955237345578">"서비스 구성"</string>
+    <string name="label_test" msgid="8425079572898571918">"테스트 구성"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"실행 중"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"종료"</string>
+    <string name="label_test_result" msgid="892984695972956196">"테스트 결과"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"초기화"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"완료"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA 서비스의 패키지 이름"</string>
+    <string name="service_release_time" msgid="532937496122890892">"통화 후 서비스 릴리스까지 시간"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC 앱 유형"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"네트워크 애플리케이션 기능(NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"부트스트랩을 강제 시작하시겠습니까?"</string>
+    <string name="request_org" msgid="8416693445448308975">"조직 코드"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA 보안 프로토콜 ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA 인증 성공 여부"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"실패 사유 ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA 키(CK 및 IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"B-TID(Bootstrapping Transaction Identifier)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ky/strings.xml b/testapps/GbaTestApp/res/values-ky/strings.xml
new file mode 100644
index 0000000..bf5cd30
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ky/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Жөндөөлөр"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Байланыш операторунун конфигурациясы"</string>
+    <string name="label_service" msgid="2668963955237345578">"Кызматтын конфигурациясы"</string>
+    <string name="label_test" msgid="8425079572898571918">"Сыноо конфигурациясы"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Аткарылууда"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Чыгуу"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Сыноо натыйжасы"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Кайра коюу"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Бүттү"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA кызматынын топтом аталышы"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Чалуудан кийин кызматты бошотуу убакыты"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC колдонмосунун түрү"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Тармактагы колдонмонун (NAF) URL функциясы"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Баштапкы жүктөө мажбурлап күйгүзүлсүнбү?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Уюмдун коду"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA коопсуздук протоколунун идентификатору"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS шифр топтомунун идентификатору"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA авторизациясы ишке аштыбы?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Ката себебинин идентификатору"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA ачкычы (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Баштапкы жүктөөнүн транзакция идентификатору (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-lo/strings.xml b/testapps/GbaTestApp/res/values-lo/strings.xml
new file mode 100644
index 0000000..d411d52
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-lo/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ການຕັ້ງຄ່າ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"ການຕັ້ງຄ່າຜູ້ໃຫ້ບໍລິການ"</string>
+    <string name="label_service" msgid="2668963955237345578">"ການຕັ້ງຄ່າການບໍລິການ"</string>
+    <string name="label_test" msgid="8425079572898571918">"ການຕັ້ງຄ່າການທົດສອບ"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ການແລ່ນ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ອອກ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ຜົນການທົດສອບ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ຣີເຊັດ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ແລ້ວໆ"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"ຊື່ແພັກເກດຂອງການບໍລິການ GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ໄລຍະເວລາທີ່ຈະໃຫ້ບໍລິການຫຼັງຈາກການໂທ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"ປະເພດແອັບ UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL ຂອງຟັງຊັນແອັບພລິເຄຊັນເຄືອຂ່າຍ (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ບັງຄັບໃຫ້ເລີ່ມຕົ້ນບໍ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"ລະຫັດຂອງອົງການ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID ໂປຣໂຕຄໍຄວາມປອດໄພ UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID ຂອງ TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"ການກວດສອບສິດ GBA ສຳເລັດບໍ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID ເຫດຜົນທີ່ບໍ່ສຳເລັດ"</string>
+    <string name="response_key" msgid="8839847772051686309">"ປຸ່ມ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ຕົວລະບຸທຸລະກຳການບັງຄັບເລີ່ມຕົ້ນ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-lt/strings.xml b/testapps/GbaTestApp/res/values-lt/strings.xml
new file mode 100644
index 0000000..780166e
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-lt/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Nustatymai"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operatoriaus konfigūracija"</string>
+    <string name="label_service" msgid="2668963955237345578">"Paslaugos konfigūracija"</string>
+    <string name="label_test" msgid="8425079572898571918">"Bandomoji konfigūracija"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Vykdoma"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Išeiti"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Bandymo rezultatas"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Nustatyti iš naujo"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Atlikta"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA paslaugos paketo pavadinimas"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Po kiek laiko atsieti paslaugą po skambučio"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC programos tipas"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Tinklo programos funkcijos (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Priverstinai paleisti pakopinį paleidimą?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organizacijos kodas"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA saugos protokolo ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS šifrų komplekto ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA autentifikavimas sėkmingas?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Nesėkmės priežasties ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA raktas (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Pakopinio paleidimo operacijos identifikatorius (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-lv/strings.xml b/testapps/GbaTestApp/res/values-lv/strings.xml
new file mode 100644
index 0000000..2a2500a
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-lv/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Iestatījumi"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Mobilo sakaru operatora konfigurācija"</string>
+    <string name="label_service" msgid="2668963955237345578">"Pakalpojuma konfigurācija"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testa konfigurācija"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Darbojas"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Iziet"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testa rezultāts"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Atiestatīt"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Gatavs"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA pakalpojuma pakotnes nosaukums"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Cik ilgi atsaistīt pakalpojumu pēc izsaukšanas"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC lietotnes veids"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Tīkla lietojumprogrammas funkcijas (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Vai veikt piespiedu sākumpalaišanu?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organizācijas kods"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA drošības protokola ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS šifru komplekta ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"Vai GBA autorizācija ir sekmīga?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Kļūdas iemesla ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA atslēga (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Sākumpalaišanas transakcijas identifikators (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-mk/strings.xml b/testapps/GbaTestApp/res/values-mk/strings.xml
new file mode 100644
index 0000000..2acc50a
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-mk/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Поставки"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Конфигурација на оператор"</string>
+    <string name="label_service" msgid="2668963955237345578">"Конфигурација на услуга"</string>
+    <string name="label_test" msgid="8425079572898571918">"Конфигурација за тестирање"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Излези"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Резултат од тестирање"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Ресетирај"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Готово"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Име на пакет на услуга на GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"За колку време се ослободува услугата по повикување"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тип апликација UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL до функција на мрежна апликација (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Да се подигне присилно?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Код на организација"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID на безбедносен протокол на UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID на збир алгоритми на TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Дали успеа автентицирањето на GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID на причина за неуспешен обид"</string>
+    <string name="response_key" msgid="8839847772051686309">"Копче за GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Идентификатор на трансакција за подигање (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ml/strings.xml b/testapps/GbaTestApp/res/values-ml/strings.xml
new file mode 100644
index 0000000..bc93aa3
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ml/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ക്രമീകരണം"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"കാരിയർ കോൺഫിഗറേഷൻ"</string>
+    <string name="label_service" msgid="2668963955237345578">"സർവീസ് കോൺഫിഗറേഷൻ"</string>
+    <string name="label_test" msgid="8425079572898571918">"ടെസ്‌റ്റ് കോൺഫിഗറേഷൻ"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"റൺ ചെയ്യുന്നു"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"പുറത്ത് കടക്കുക"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ടെസ്‌റ്റ് ഫലം"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"റീസെറ്റ് ചെയ്യുക"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"പൂർത്തിയായി"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA സേവനത്തിന്റെ പാക്കേജ് പേര്"</string>
+    <string name="service_release_time" msgid="532937496122890892">"കോൾ ചെയ്‌തതിന് ശേഷം സേവനം റിലീസ് ചെയ്യാൻ എത്ര സമയമെടുക്കും"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ആപ്പ് തരം"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"നെറ്റ്‌വർക്ക് അപ്ലിക്കേഷൻ ഫംഗ്‌ഷൻ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ബലം പ്രയോഗിച്ച് ബൂട്ട്‌സ്‌ട്രാപ്പിംഗ് ചെയ്യണോ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"സ്ഥാപനത്തിന്റെ കോഡ്"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA സുരക്ഷാ പ്രോട്ടോക്കോൾ ഐഡി"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS സെെഫർ സ്വീറ്റ് ഐഡി"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA പരിശോധിച്ചുറപ്പിക്കൽ വിജയകരമായിരുന്നോ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"പരാജയ കാരണ ഐഡി"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA കീ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ബൂട്ട്‌സ്‌ട്രാപ്പിംഗ് ട്രാൻസാക്ഷൻ ഐഡന്‌റിഫയർ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-mn/strings.xml b/testapps/GbaTestApp/res/values-mn/strings.xml
new file mode 100644
index 0000000..0aa62b0
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-mn/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Тохиргоо"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Оператор компанийн тохируулга"</string>
+    <string name="label_service" msgid="2668963955237345578">"Үйлчилгээний тохируулга"</string>
+    <string name="label_test" msgid="8425079572898571918">"Туршилтын тохируулга"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Ажиллаж байна"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Гарах"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Туршилтын үр дүн"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Шинэчлэх"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Дууссан"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA-н үйлчилгээний багцын нэр"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Дуудлага хийсний дараа үйлчилгээг хэдий хугацааны дараа салгах вэ?"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC Аппын төрөл"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Сүлжээний аппликэйшний функц (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Хүчээр эхлүүлэх үү?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Байгууллагын код"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA-н Аюулгүй байдлын протоколын ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS-н Шифрийн цуглуулгын ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-г амжилттай баталгаажуулсан уу?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Амжилтгүй болсон шалтгааны ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-н түлхүүр (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Эхлүүлэх гүйлгээний таниулбар (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-mr/strings.xml b/testapps/GbaTestApp/res/values-mr/strings.xml
new file mode 100644
index 0000000..75aaf5f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-mr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"सेटिंग्ज"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"वाहक कॉंफिगरेशन"</string>
+    <string name="label_service" msgid="2668963955237345578">"सेवा कॉंफिगरेशन"</string>
+    <string name="label_test" msgid="8425079572898571918">"चाचणी कॉंफिगरेशन"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"रन करत आहे"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"बाहेर पडा"</string>
+    <string name="label_test_result" msgid="892984695972956196">"चाचणी परिणाम"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"रीसेट करा"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"पूर्ण झाले"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA सेवेच्या पॅकेजचे नाव"</string>
+    <string name="service_release_time" msgid="532937496122890892">"कॉलनंतर किती वेळाने रिलीझ होईल"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ॲप प्रकार"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"नेटवर्क अ‍ॅप्लिकेशन फंक्शन (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"सक्तीने बूटस्ट्रॅपिंग करायचे का?"</string>
+    <string name="request_org" msgid="8416693445448308975">"संस्थेचा कोड"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA सुरक्षा प्रोटोकॉल आयडी"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS सायफर स्वीट आयडी"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA ऑथेंटिकेशन यशस्वी झाले का?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"अयशस्वी होण्याच्या कारणाचा आयडी"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA की (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"बूटस्ट्रॅपिंग ट्रांजॅक्शन आयडेंटिफायर (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ms/strings.xml b/testapps/GbaTestApp/res/values-ms/strings.xml
new file mode 100644
index 0000000..35838b7
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ms/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Tetapan"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfigurasi Pembawa"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfigurasi Perkhidmatan"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfigurasi Ujian"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Berjalan"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Keluar"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Keputusan Ujian"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Tetapkan semula"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Selesai"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nama pakej perkhidmatan GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Tempoh untuk mengaktifkan perkhidmatan selepas panggilan"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Jenis Apl UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL fungsi aplikasi rangkaian (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Paksa Butstrap?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kod Organisasi"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID Protokol Keselamatan UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID Suite Sifer TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Pengesahan GBA Berjaya?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID Sebab Gagal"</string>
+    <string name="response_key" msgid="8839847772051686309">"Kunci GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Pengecam Transaksi Butstrap (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-my/strings.xml b/testapps/GbaTestApp/res/values-my/strings.xml
new file mode 100644
index 0000000..f39f77a
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-my/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ဆက်တင်များ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"ဖုန်းလိုင်း စီစဉ်သတ်မှတ်ချက်"</string>
+    <string name="label_service" msgid="2668963955237345578">"ဝန်ဆောင်မှု စီစဉ်သတ်မှတ်ချက်"</string>
+    <string name="label_test" msgid="8425079572898571918">"စမ်းသပ်မှု စီစဉ်သတ်မှတ်ချက်"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"လုပ်ဆောင်နေသည်"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ထွက်ရန်"</string>
+    <string name="label_test_result" msgid="892984695972956196">"စမ်းသပ်မှုရလဒ်"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ပြင်ဆင်သတ်မှတ်ရန်"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ပြီးပြီ"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA ဝန်ဆောင်မှု၏ ပက်ကေ့ဂျ်အမည်"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ခေါ်ဆိုပြီးနောက် ဝန်ဆောင်မှုကို ဖြန့်ချိရန် ကြာချိန်"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC အက်ပ်အမျိုးအစား"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ကွန်ရက်အပလီကေးရှင်း လုပ်ဆောင်ချက် (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"စနစ်စတင်ခြင်းကို မဖြစ်မနေလုပ်မလား။"</string>
+    <string name="request_org" msgid="8416693445448308975">"အဖွဲ့အစည်းကုဒ်"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA လုံခြုံရေးပရိုတိုကော ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA Auth အောင်မြင်ပါသလား။"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"မအောင်မြင်မှု အကြောင်းရင်း ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA ကီး (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"စနစ်စတင်ခြင်းလုပ်ငန်း သတ်မှတ်မှုစနစ် (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-nb/strings.xml b/testapps/GbaTestApp/res/values-nb/strings.xml
new file mode 100644
index 0000000..cbcfcb8
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-nb/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Innstillinger"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operatørkonfigurering"</string>
+    <string name="label_service" msgid="2668963955237345578">"Tjenestekonfigurering"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testkonfigurering"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Kjører"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Lukk"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testresultat"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Tilbakestill"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Ferdig"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pakkenavn for GBA-tjeneste"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hvor lenge tjenesten skal frigis etter kalling"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC-apptype"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Nettadresse til nettverksprogramfunksjon (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Vil du tvinge frem bruk av bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisasjonskode"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Sikkerhetsprotokoll-ID for UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID for TLS-chifferpakke"</string>
+    <string name="response_success" msgid="2469204471244527663">"Lyktes GBA-autentisering?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Feilårsaks-ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-nøkkel (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikator for bootstrapping-transaksjon (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ne/strings.xml b/testapps/GbaTestApp/res/values-ne/strings.xml
new file mode 100644
index 0000000..741c716
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ne/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"सेटिङ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"टेलिफोन कम्पनीसम्बन्धी कन्फिगुरेसन"</string>
+    <string name="label_service" msgid="2668963955237345578">"सेवासम्बन्धी कन्फिगुरेसन"</string>
+    <string name="label_test" msgid="8425079572898571918">"परीक्षणसम्बन्धी कन्फिगुरेसन"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"चलिरहेको छ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"बाहिरिनुहोस्"</string>
+    <string name="label_test_result" msgid="892984695972956196">"परीक्षणको नतिजा"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"रिसेट गर्नुहोस्"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"सम्पन्न भयो"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA सेवाको प्याकेजको नाम"</string>
+    <string name="service_release_time" msgid="532937496122890892">"कल गरेपछि सेवा सुरु हुन कति समय लाग्ने छ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC एपको प्रकार"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"नेटवर्क एप्लिकेसन फङ्सन (NAF) को URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"जबरजस्ती बुटस्ट्रयाप गर्ने हो?"</string>
+    <string name="request_org" msgid="8416693445448308975">"सङ्गठनको कोड"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA को सुरक्षा प्रोटोकोल ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA को पुष्टि गर्ने कार्य सफल भयो?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"कार्य असफल हुनुको कारणको ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA सुरक्षा साँचो (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"बुटस्ट्रयापिङ ट्रान्जेक्सन आइडेन्टिफायर (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-nl/strings.xml b/testapps/GbaTestApp/res/values-nl/strings.xml
new file mode 100644
index 0000000..3c8640f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-nl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Instellingen"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Providerconfiguratie"</string>
+    <string name="label_service" msgid="2668963955237345578">"Serviceconfiguratie"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testconfiguratie"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Actief"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Sluiten"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testresultaat"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetten"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Klaar"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pakketnaam van GBA-service"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hoelang de service moet worden vrijgegeven na de aanroep"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Type UICC-app"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"NAF-URL (Network application function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Bootstrapping forceren?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisatiecode"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID van UA-beveiligingsprotocol"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID van Cipher Suite voor TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-autorisatie geslaagd?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID voor reden van mislukking"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-sleutel (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-or/strings.xml b/testapps/GbaTestApp/res/values-or/strings.xml
new file mode 100644
index 0000000..456751d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-or/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ସେଟିଂସ୍"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"କ୍ୟାରିଅର୍ କନଫିଗରେସନ୍"</string>
+    <string name="label_service" msgid="2668963955237345578">"ସେବା କନଫିଗରେସନ୍"</string>
+    <string name="label_test" msgid="8425079572898571918">"ଟେଷ୍ଟ କନଫିଗରେସନ୍"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ଚାଲୁଛି"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ବାହାରି ଯାଆନ୍ତୁ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ଟେଷ୍ଟ ଫଳାଫଳ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ରିସେଟ୍ କରନ୍ତୁ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ହୋଇଗଲା"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA ସେବାର ପ୍ୟାକେଜ୍ ନାମ"</string>
+    <string name="service_release_time" msgid="532937496122890892">"କଲ୍ କରିବାର କେତେ ସମୟ ପରେ ସେବା ରିଲିଜ୍ ହେବ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ଆପ୍ ପ୍ରକାର"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ନେଟୱାର୍କ ଆପ୍ଲିକେସନ୍ ଫଙ୍କସନ୍ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ବଳପୂର୍ବକ ବୁଟଷ୍ଟ୍ରାପିଂ କରିବେ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"ସଂସ୍ଥାର କୋଡ୍"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA ସୁରକ୍ଷା ପ୍ରୋଟୋକଲ୍ ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS ସାଇଫର୍ ସୁଟ୍ ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA ଅଥୋରାଇଜେସନ୍ ସଫଳ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ବିଫଳ ହେବାର କାରଣ ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA କୀ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ବୁଟଷ୍ଟ୍ରାପିଂ ଟ୍ରାଞ୍ଜେକସନ୍ ଚିହ୍ନଟକାରୀ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-pa/strings.xml b/testapps/GbaTestApp/res/values-pa/strings.xml
new file mode 100644
index 0000000..068d8ab
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-pa/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"ਕੈਰੀਅਰ ਦਾ ਸੰਰੂਪਣ"</string>
+    <string name="label_service" msgid="2668963955237345578">"ਸੇਵਾ ਦਾ ਸੰਰੂਪਣ"</string>
+    <string name="label_test" msgid="8425079572898571918">"ਜਾਂਚ ਦਾ ਸੰਰੂਪਣ"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ਚੱਲ ਰਹੀ ਹੈ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ਬਾਹਰ ਜਾਓ"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ਜਾਂਚ ਦਾ ਨਤੀਜਾ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ਰੀਸੈੱਟ ਕਰੋ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ਹੋ ਗਿਆ"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA ਸੇਵਾ ਦਾ ਪੈਕੇਜ ਨਾਮ"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ਕਾਲ ਕਰਨ ਤੋਂ ਬਾਅਦ ਸੇਵਾ ਨੂੰ ਰਿਲੀਜ਼ ਕਰਨ ਵਿੱਚ ਕਿੰਨਾ ਸਮਾਂ ਲੱਗੇਗਾ"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ਐਪ ਦੀ ਕਿਸਮ"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ਨੈੱਟਵਰਕ ਐਪਲੀਕੇਸ਼ਨ ਫੰਕਸ਼ਨ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ਕੀ ਬੂਟਸਟ੍ਰੈਪਿੰਗ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਲਾਗੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="request_org" msgid="8416693445448308975">"ਸੰਸਥਾ ਕੋਡ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA ਸੁਰੱਖਿਆ ਪ੍ਰੋਟੋਕੋਲ ਆਈਡੀ"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS ਸਾਈਫਰ ਸੂਟ ਆਈਡੀ"</string>
+    <string name="response_success" msgid="2469204471244527663">"ਕੀ GBA ਪ੍ਰਮਾਣੀਕਰਨ ਵਿੱਚ ਸਫਲਤਾ ਪ੍ਰਾਪਤ ਹੋਈ?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ਅਸਫਲਤਾ ਕਾਰਨ ਆਈਡੀ"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA ਕੁੰਜੀ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ਬੂਟਸਟ੍ਰੈਪਿੰਗ ਲੈਣ-ਦੇਣ ਪਛਾਣਕਰਤਾ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-pl/strings.xml b/testapps/GbaTestApp/res/values-pl/strings.xml
new file mode 100644
index 0000000..9fca28f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-pl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ustawienia"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguracja operatora"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguracja usługi"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfiguracja testu"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Działa"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Wyjdź"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Wyniki testu"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetuj"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Gotowe"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nazwa pakietu usługi GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Po jakim czasie od połączenia dopuścić usługę"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Typ aplikacji UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL funkcji aplikacji sieciowych (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Wymusić Bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kod organizacji"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Identyfikator protokołu bezpieczeństwa UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Identyfikator TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"Uwierzytelnianie GBA zakończone powodzeniem?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Identyfikator powodu niepowodzenia"</string>
+    <string name="response_key" msgid="8839847772051686309">"Klucz GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identyfikator transakcji Bootstrapping (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-pt-rPT/strings.xml b/testapps/GbaTestApp/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..715aabb
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Definições"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configuração do operador"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configuração do serviço"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configuração do teste"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Em execução"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Sair"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultado do teste"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Repor"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Concluído"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nome do pacote do serviço GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Tempo de libertação do serviço após a chamada"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo de app UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL da função de aplicação de rede (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forçar bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Código de organização"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID de protocolo de segurança UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID de conjunto de cifra TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Sucesso na autenticação GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID do motivo da falha"</string>
+    <string name="response_key" msgid="8839847772051686309">"Chave GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador de transação de bootstrapping (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-pt/strings.xml b/testapps/GbaTestApp/res/values-pt/strings.xml
new file mode 100644
index 0000000..cf4ea72
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-pt/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Configurações"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configurações da operadora"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configurações do serviço"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configurações de teste"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Executando"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Sair"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resultado do teste"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Redefinir"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Concluído"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Nome do pacote de serviços da GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Tempo para liberar o serviço após a chamada"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipo de app UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL da função de aplicativo de rede (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forçar inicialização?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Código da organização"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID do protocolo de segurança UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID do pacote de criptografia TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Autenticação da GBA concluída?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID do motivo da falha"</string>
+    <string name="response_key" msgid="8839847772051686309">"Chave de segurança da GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identificador de transações de inicialização (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ro/strings.xml b/testapps/GbaTestApp/res/values-ro/strings.xml
new file mode 100644
index 0000000..d7f9e7b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ro/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Setări"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Configurația operatorului"</string>
+    <string name="label_service" msgid="2668963955237345578">"Configurația serviciului"</string>
+    <string name="label_test" msgid="8425079572898571918">"Configurație de testare"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Rulează"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Ieșiți"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultatul testului"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetați"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Terminat"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Numele de pachet al serviciului GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Durata până la lansarea serviciului după apel"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Tipul aplicației UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Adresa URL pentru funcția aplicației pentru rețea (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Forțați inițializarea?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Cod organizațional"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID-ul protocolului de securitate pentru Google Analytics universal"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID-ul suitei TLS Cipher"</string>
+    <string name="response_success" msgid="2469204471244527663">"Succes la autentificarea GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID-ul motivului eșecului"</string>
+    <string name="response_key" msgid="8839847772051686309">"Cheie GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Se inițializează identificatorul tranzacției (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ru/strings.xml b/testapps/GbaTestApp/res/values-ru/strings.xml
new file mode 100644
index 0000000..a5d0bff
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ru/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Настройки"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Конфигурация оператора связи"</string>
+    <string name="label_service" msgid="2668963955237345578">"Конфигурация сервиса"</string>
+    <string name="label_test" msgid="8425079572898571918">"Тестовая конфигурация"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Выполняется"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Выйти"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Результат тестирования"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Сбросить"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Готово"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Название пакета сервиса GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Через какое время освобождать сервис после вызова"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тип приложения UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL функции сетевого приложения (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Включить начальную загрузку принудительно?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Код организации"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Идентификатор протокола безопасности UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Идентификатор шифронабора TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Авторизация GBA выполнена?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Идентификатор причины сбоя"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ключ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Идентификатор транзакции начальной загрузки (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-si/strings.xml b/testapps/GbaTestApp/res/values-si/strings.xml
new file mode 100644
index 0000000..7a66d1f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-si/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"සැකසීම්"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"වාහකය වින්‍යාසය"</string>
+    <string name="label_service" msgid="2668963955237345578">"සේවා වින්‍යාසය"</string>
+    <string name="label_test" msgid="8425079572898571918">"පරීක්ෂණ වින්‍යාසය"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"ධාවනය වේ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"පිටවන්න"</string>
+    <string name="label_test_result" msgid="892984695972956196">"පරීක්ෂණ ප්‍රතිඵලය"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"යළි පිහිටුවන්න"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"නිමයි"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA සේවාවෙහි පැකේජයේ නම"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ඇමතුමෙන් පසු සේවාව මුදා හැරීමට කාලය"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC යෙදුම් වර්ගය"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"ජාල යෙදුම් කාර්යය (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"ඇරඹුම් පටිය බලාත්මක කරන්න ද?"</string>
+    <string name="request_org" msgid="8416693445448308975">"සංවිධාන කේතය"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA ආරක්ෂක ප්‍රොටොකෝල ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS කේතාංක කට්ටල ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA සත්‍යාපනය සාර්ථක ද?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"අසමත් හේතුව ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA යතුර (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"ඇරඹුම් පටි ගනුදෙනු හැඳුනුම්කාරකය (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sk/strings.xml b/testapps/GbaTestApp/res/values-sk/strings.xml
new file mode 100644
index 0000000..17b788f
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sk/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Nastavenia"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfigurácia operátora"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfigurácia služby"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfigurácia testu"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Spustené"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Ukončiť"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Výsledok testu"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Resetovať"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Hotovo"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Názov balíka služby GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Ako dlho trvá uvoľnenie služby po volaní"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Typ aplikácie UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Webová adresa funkcie NAF"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Chcete vynútiť bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kód organizácie"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Identifikátor bezpečnostného protokolu UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Identifikátor šifrovacieho balíka TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Bola autorizácia GBA úspešná?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Identifikátor dôvodu zlyhania"</string>
+    <string name="response_key" msgid="8839847772051686309">"Kľúč GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrappingový identifikátor transakcie (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sl/strings.xml b/testapps/GbaTestApp/res/values-sl/strings.xml
new file mode 100644
index 0000000..6e3196b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Nastavitve"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfiguracija operaterja"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfiguracija storitve"</string>
+    <string name="label_test" msgid="8425079572898571918">"Preizkusi konfiguracijo"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Se izvaja"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Zapri"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultat preizkusa"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Ponastavi"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Končano"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Ime paketa storitve GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Čas, preden se storitev aktivira po klicanju"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Vrsta aplikacije UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL funkcije uporabe v omrežju (NAF – Network application function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Želite vsiliti zagon?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Koda organizacije"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID varnostnega protokola za UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID zbirke šifriranja TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Je preverjanje pristnosti GBA uspelo?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID vzroka za napako"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ključ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikator transakcije zagona (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sq/strings.xml b/testapps/GbaTestApp/res/values-sq/strings.xml
new file mode 100644
index 0000000..402345e
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sq/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Cilësimet"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Konfigurimi i operatorit celular"</string>
+    <string name="label_service" msgid="2668963955237345578">"Konfigurimi i shërbimit"</string>
+    <string name="label_test" msgid="8425079572898571918">"Konfigurimi i testit"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Në ekzekutim"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Dil"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Rezultati i testit"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Rivendos"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"U krye"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Emri i paketës së shërbimit GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Koha për lirimin e shërbimit pas thirrjes"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Lloji i aplikacionit UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL-ja e funksionit të aplikacionit të rrjetit (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Të detyrohet nisja automatike?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kodi i organizatës"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ID-ja e protokollit të sigurisë UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID-ja e paketës së shifrimit TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Vërtetimi i shërbimit GBA me sukses?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID-ja e arsyes së dështimit"</string>
+    <string name="response_key" msgid="8839847772051686309">"Çelësi GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Identifikuesi i transaksionit të nisjes automatike (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sr/strings.xml b/testapps/GbaTestApp/res/values-sr/strings.xml
new file mode 100644
index 0000000..9d8cbd6
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Подешавања"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Конфигурација мобилног оператера"</string>
+    <string name="label_service" msgid="2668963955237345578">"Конфигурација услуге"</string>
+    <string name="label_test" msgid="8425079572898571918">"Пробна конфигурација"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Активно"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Затвори"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Резултат теста"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Ресетуј"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Готово"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Назив пакета услуге GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Време док се услуга не активира после позива"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тип UICC апликације"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL функције мрежне апликације (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Желите ли да наметнете самостално узорковање?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Кôд организације"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"ИД безбедносног протокола универзалне аналитике"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"ИД TLS пакета за шифровање"</string>
+    <string name="response_success" msgid="2469204471244527663">"Да ли је потврда идентитета за GBA успела?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ИД разлога за неуспех"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA тастер (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Идентификатор трансакције за самостално узорковање (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sv/strings.xml b/testapps/GbaTestApp/res/values-sv/strings.xml
new file mode 100644
index 0000000..d228f8e
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sv/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Inställningar"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operatörskonfiguration"</string>
+    <string name="label_service" msgid="2668963955237345578">"Tjänstkonfiguration"</string>
+    <string name="label_test" msgid="8425079572898571918">"Testkonfiguration"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Körs"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Stäng"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Testresultat"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Återställ"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Klar"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA-tjänstens paketnamn"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Hur länge tjänsten frigörs efter uppringning"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Apptyp UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"NAF-URL (Network application function)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Tvinga start?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organisationsnummer"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA säkerhetsprotokoll-ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS chiffersvit-ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA-aut. slutförd?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Felorsaks-ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA-nyckel (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-sw/strings.xml b/testapps/GbaTestApp/res/values-sw/strings.xml
new file mode 100644
index 0000000..9dcd5cb
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-sw/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Mipangilio"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Mipangilio ya Mtoa huduma"</string>
+    <string name="label_service" msgid="2668963955237345578">"Mipangilio ya Huduma"</string>
+    <string name="label_test" msgid="8425079572898571918">"Mipangilio ya Jaribio"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Inatekeleza"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Funga"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Matokeo ya Jaribio"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Weka upya"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Imemaliza"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Jina la kifurushi cha huduma ya GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Muda wa kutoa huduma baada ya kupiga simu"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Aina ya Programu ya UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL ya kipengele cha programu ya mtandao (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Ungependa Kulazimisha Bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Msimbo wa Shirika"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Kitambulisho cha Itifaki ya Usalama cha UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Kitambulisho cha TLS cha Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"Je, GBA Auth Imefaulu?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Kitambulisho cha Sababu ya Kufeli"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ufunguo wa GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Kitambulishi cha Shughuli za Utatuzi kwa Rasilimali Zilizopo (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ta/strings.xml b/testapps/GbaTestApp/res/values-ta/strings.xml
new file mode 100644
index 0000000..147078e
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ta/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"அமைப்புகள்"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"மொபைல் நிறுவன உள்ளமைவு"</string>
+    <string name="label_service" msgid="2668963955237345578">"சேவை உள்ளமைவு"</string>
+    <string name="label_test" msgid="8425079572898571918">"சோதனை உள்ளமைவு"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"இயங்குகிறது"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"வெளியேறு"</string>
+    <string name="label_test_result" msgid="892984695972956196">"சோதனை முடிவு"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"மீட்டமை"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"முடிந்தது"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA சேவையின் தொகுப்புப் பெயர்"</string>
+    <string name="service_release_time" msgid="532937496122890892">"அழைத்தபிறகு எவ்வளவு நேரத்தில் சேவை வெளியிடப்படும்?"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ஆப்ஸ் வகை"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"நெட்வொர்க் ஆப்ஸ் செயல்பாட்டின் (NAF - Network application function) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"உடனே பூட்ஸ்ட்ராப்பிங் செய்யவா?"</string>
+    <string name="request_org" msgid="8416693445448308975">"நிறுவனக் குறியீடு"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA பாதுகாப்பு நெறிமுறை ஐடி"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS சைஃபர் தொகுப்பு ஐடி"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA அங்கீகரிக்கப்பட்டதா?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"தோல்வியின் காரணத்திற்கான ஐடி"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA விசை (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"பூட்ஸ்ட்ராப்பிங் பரிமாற்ற அடையாளங்காட்டி (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-te/strings.xml b/testapps/GbaTestApp/res/values-te/strings.xml
new file mode 100644
index 0000000..7434bca
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-te/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"సెట్టింగ్‌లు"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"క్యారియర్ కాన్ఫిగరేషన్"</string>
+    <string name="label_service" msgid="2668963955237345578">"సర్వీస్ కాన్ఫిగరేషన్"</string>
+    <string name="label_test" msgid="8425079572898571918">"పరీక్ష కాన్ఫిగరేషన్"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"రన్ అవుతోంది"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"నిష్క్రమించు"</string>
+    <string name="label_test_result" msgid="892984695972956196">"పరీక్ష ఫలితం"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"రీసెట్ చేయి"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"పూర్తయింది"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA సర్వీస్ ప్యాకేజీ పేరు"</string>
+    <string name="service_release_time" msgid="532937496122890892">"కాల్ చేసిన తర్వాత సర్వీస్‌ను రిలీజ్ చేయడానికి ఎంత సమయం పడుతుంది"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC యాప్ రకం"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"నెట్‌వర్క్ యాప్ ఫంక్షన్ (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"బూట్‌స్ట్రాపింగ్ ఫోర్స్ చేయాలా?"</string>
+    <string name="request_org" msgid="8416693445448308975">"సంస్థ కోడ్"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA సెక్యూరిటీ ప్రోటోకాల్ ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS సైఫర్ Suite ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA Auth విజయవంతమైందా?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"వైఫల్యానికి కారణమైన ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA కీ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"బూట్‌స్ట్రాపింగ్ ట్రాన్జాక్షన్ ఐడెంటిఫయర్ (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-th/strings.xml b/testapps/GbaTestApp/res/values-th/strings.xml
new file mode 100644
index 0000000..4e58913
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-th/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"การตั้งค่า"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"กำหนดผู้ให้บริการ"</string>
+    <string name="label_service" msgid="2668963955237345578">"กำหนดบริการ"</string>
+    <string name="label_test" msgid="8425079572898571918">"กำหนดการทดสอบ"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"วิ่ง"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"ออก"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ผลการทดสอบ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"รีเซ็ต"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"เสร็จ"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"ชื่อแพ็กเกจบริการ GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"ระยะเวลาที่จะให้บริการหลังจากโทร"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"ประเภทแอป UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL ของ Network Application Function (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"บังคับให้เริ่มต้นไหม"</string>
+    <string name="request_org" msgid="8416693445448308975">"รหัสองค์กร"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"รหัสโปรโตคอลความปลอดภัยของ UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"รหัสของ TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"การตรวจสอบสิทธิ์ GBA สำเร็จไหม"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"รหัสเหตุผลที่ล้มเหลว"</string>
+    <string name="response_key" msgid="8839847772051686309">"คีย์ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-tl/strings.xml b/testapps/GbaTestApp/res/values-tl/strings.xml
new file mode 100644
index 0000000..d96464b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-tl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Mga Setting"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Config ng Carrier"</string>
+    <string name="label_service" msgid="2668963955237345578">"Config ng Serbisyo"</string>
+    <string name="label_test" msgid="8425079572898571918">"Config ng Pagsubok"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Tumatakbo"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Lumabas"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Resulta ng Pagsubok"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"I-reset"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Tapos na"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Pangalan ng package ng serbisyo ng GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Gaano katagal ire-release ang serbisyo pagkatapos ng pagtawag"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Uri ng UICC App"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL ng Network application function (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Puwersahin ang Pag-bootstrap?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Organization Code"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Security Protocol ID ng UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Suite ID ng TLS Cipher"</string>
+    <string name="response_success" msgid="2469204471244527663">"Matagumpay ba ang GBA Auth?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"ID ng Dahilan ng Pagkabigo"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA Key (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-tr/strings.xml b/testapps/GbaTestApp/res/values-tr/strings.xml
new file mode 100644
index 0000000..8078563
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-tr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Ayarlar"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Operatör Yapılandırması"</string>
+    <string name="label_service" msgid="2668963955237345578">"Hizmet Yapılandırması"</string>
+    <string name="label_test" msgid="8425079572898571918">"Test Yapılandırması"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Çalışıyor"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Çık"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Test Sonucu"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Sıfırla"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Bitti"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA hizmetinin paket adı"</string>
+    <string name="service_release_time" msgid="532937496122890892">"API çağrısından sonra hizmetin ne süreyle serbest bırakılacağı"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC Uygulaması Türü"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Ağ uygulaması işlevi (NAF) URL\'si"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Önyüklemeye Zorlansın mı?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Kuruluş Kodu"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA Güvenlik Protokolü Kimliği"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Şifre Paketi Kimliği"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA Kimlik Doğrulaması Başarılı mı?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Hata Nedeni Kimliği"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA Anahtarı (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Önyükleme İşlem Tanımlayıcısı (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-uk/strings.xml b/testapps/GbaTestApp/res/values-uk/strings.xml
new file mode 100644
index 0000000..fa2e23c
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-uk/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Налаштування"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Конфігурація оператора"</string>
+    <string name="label_service" msgid="2668963955237345578">"Конфігурація сервісу"</string>
+    <string name="label_test" msgid="8425079572898571918">"Конфігурація перевірки"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Виконується"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Вийти"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Результат перевірки"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Скинути"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Готово"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Назва пакета сервісу GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Скільки має працювати сервіс після виклику"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Тип додатка UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL-адреса функції додатка мережі (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Ініціювати початкове завантаження примусово?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Код організації"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Ідентифікатор протоколу безпеки UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Ідентифікатор пакета шифрування TLS"</string>
+    <string name="response_success" msgid="2469204471244527663">"Чи успішно пройшла автентифікація GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Ідентифікатор причини помилки"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ключ GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Ідентифікатор транзакції початкового завантаження (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-ur/strings.xml b/testapps/GbaTestApp/res/values-ur/strings.xml
new file mode 100644
index 0000000..26e5c04
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-ur/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"ترتیبات"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"کیریئر کنفیگریشن"</string>
+    <string name="label_service" msgid="2668963955237345578">"سروس کنفیگریشن"</string>
+    <string name="label_test" msgid="8425079572898571918">"ٹیسٹ کنفیگریشن"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"دوڑ"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"باہر نکلیں"</string>
+    <string name="label_test_result" msgid="892984695972956196">"ٹیسٹ کا نتیجہ"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"ری سیٹ کریں"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"ہو گیا"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"‏GBA سروس کا پیکیج نام"</string>
+    <string name="service_release_time" msgid="532937496122890892">"فون کرنے کے بعد سروس کب تک ریلیز کی جائے"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"‏UICC ایپ کی قسم"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"‏نیٹ ورک ایپلیکیشن فنکشن (NAF‏) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"بوٹ اسٹراپنگ فورس کریں؟"</string>
+    <string name="request_org" msgid="8416693445448308975">"آرگنائزیشن کوڈ"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"‏UA سکیورٹی پروٹوکول ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"‏TLS Cipher سوئیٹ ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"‏GBA کی توثیق کامیاب کریں؟"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"‏ناکامی کی وجہ ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"‏GBA کلید‏ (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"‏بوٹ اسٹراپنگ ٹرانزیکشن شناخت کار (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-uz/strings.xml b/testapps/GbaTestApp/res/values-uz/strings.xml
new file mode 100644
index 0000000..369cfaa
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-uz/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Sozlamalar"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Aloqa operatorini sozlash"</string>
+    <string name="label_service" msgid="2668963955237345578">"Xizmatni sozlash"</string>
+    <string name="label_test" msgid="8425079572898571918">"Sinovli sozlash"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Bajarilmoqda"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Chiqish"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Sinov natijalari"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Asliga qaytarish"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Tayyor"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA xizmati paketi nomi"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Chaqiruvdan keyin xizmatni bo‘shatish uchun muddat"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC ilovasi turi"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Tarmoq ilovasi funksiyasining (NAF) URL manzili"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Avtomatik yuklash majburiy yoqilsinmi?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Tashkilot kodi"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA xavfsizlik protokoli identifikatori"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS shifrli terish identifikatori"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA tekshiruvi bajarildimi?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Nosozlik sababi identifikatori"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA kaliti (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Avtomatik yuklash tranzaksiyasining identifikatori (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-vi/strings.xml b/testapps/GbaTestApp/res/values-vi/strings.xml
new file mode 100644
index 0000000..e826f7b
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-vi/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Cài đặt"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Cấu hình nhà mạng"</string>
+    <string name="label_service" msgid="2668963955237345578">"Cấu hình dịch vụ"</string>
+    <string name="label_test" msgid="8425079572898571918">"Cấu hình thử nghiệm"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Đang chạy"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Thoát"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Kết quả thử nghiệm"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Đặt lại"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Xong"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Tên gói của dịch vụ GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Mất bao lâu để hủy liên kết dịch vụ sau khi thực hiện lệnh gọi"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Loại ứng dụng UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"URL chức năng ứng dụng mạng (NAF)"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Buộc dùng phương pháp tự thân?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Mã tổ chức"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"Mã giao thức bảo mật UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"Mã bộ thuật toán TLS (Bảo mật tầng truyền tải)"</string>
+    <string name="response_success" msgid="2469204471244527663">"Xác thực thành công GBA?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"Mã lý do bị lỗi"</string>
+    <string name="response_key" msgid="8839847772051686309">"Mã kiến trúc tự thân chung (GBA) (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"Giá trị nhận dạng giao dịch theo phương thức tự thân (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-zh-rCN/strings.xml b/testapps/GbaTestApp/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..ae99979
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-zh-rCN/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"设置"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"运营商配置"</string>
+    <string name="label_service" msgid="2668963955237345578">"服务配置"</string>
+    <string name="label_test" msgid="8425079572898571918">"测试配置"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"正在运行"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"退出"</string>
+    <string name="label_test_result" msgid="892984695972956196">"测试结果"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"重置"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"完成"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA 服务的软件包名称"</string>
+    <string name="service_release_time" msgid="532937496122890892">"调用 API 后释放服务所需的时间"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC 应用类型"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"网络应用功能 (NAF) 网址"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"要强制使用引导吗?"</string>
+    <string name="request_org" msgid="8416693445448308975">"单位代码"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA 安全协议 ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"传输层安全协议 (TLS) 加密套件 ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA 身份验证成功了吗?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"失败原因 ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA 密钥 (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"引导事务标识符 (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-zh-rHK/strings.xml b/testapps/GbaTestApp/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..eb93a5d
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-zh-rHK/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"設定"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"流動網絡供應商設定"</string>
+    <string name="label_service" msgid="2668963955237345578">"服務設定"</string>
+    <string name="label_test" msgid="8425079572898571918">"測試設定"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"正在執行"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"結束"</string>
+    <string name="label_test_result" msgid="892984695972956196">"測試結果"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"重設"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"完成"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA 服務套件名稱"</string>
+    <string name="service_release_time" msgid="532937496122890892">"調用後多久才釋出服務"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC 應用程式類型"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"網絡應用功能 (NAF) 網址"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"要強制啟動嗎?"</string>
+    <string name="request_org" msgid="8416693445448308975">"機構代碼"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA 安全性通訊協定 ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS 密碼套件 ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"GBA 驗證成功?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"失敗原因 ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA 鍵 (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"啟動交易識別碼 (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-zh-rTW/strings.xml b/testapps/GbaTestApp/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..d0a6a76
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-zh-rTW/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"設定"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"電信業者設定"</string>
+    <string name="label_service" msgid="2668963955237345578">"服務設定"</string>
+    <string name="label_test" msgid="8425079572898571918">"測試設定"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Running"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"結束"</string>
+    <string name="label_test_result" msgid="892984695972956196">"測試結果"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"重設"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"完成"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"GBA 服務的套件名稱"</string>
+    <string name="service_release_time" msgid="532937496122890892">"呼叫後多久釋出服務"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"UICC 應用程式類型"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"網路應用程式功能 (NAF) 網址"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"要強制引導嗎?"</string>
+    <string name="request_org" msgid="8416693445448308975">"機構代碼"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"UA 安全通訊協定 ID"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"傳輸層安全標準 (TLS) 加密套裝組合 ID"</string>
+    <string name="response_success" msgid="2469204471244527663">"是否通過 GBA 驗證?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"失敗原因 ID"</string>
+    <string name="response_key" msgid="8839847772051686309">"GBA 金鑰 (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"引導交易 ID (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values-zu/strings.xml b/testapps/GbaTestApp/res/values-zu/strings.xml
new file mode 100644
index 0000000..8a221a2
--- /dev/null
+++ b/testapps/GbaTestApp/res/values-zu/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2922839697457005451">"I-GbaTestApp"</string>
+    <string name="label_settings" msgid="8030871890526865502">"Amasethingi"</string>
+    <string name="label_carrier" msgid="1470455313066422804">"Ukulungiswa Kwenkampani Yenethiwekhi"</string>
+    <string name="label_service" msgid="2668963955237345578">"Ukulungiswa Kwesevisi"</string>
+    <string name="label_test" msgid="8425079572898571918">"Ukulungiswa Kohlolo"</string>
+    <string name="button_name_running" msgid="4557363091224858010">"Uyagijima"</string>
+    <string name="button_name_exit" msgid="8025683733431538975">"Phuma"</string>
+    <string name="label_test_result" msgid="892984695972956196">"Umphumela wokuhlolwa"</string>
+    <string name="button_name_clear" msgid="436313515327318537">"Setha kabusha"</string>
+    <string name="button_name_done" msgid="6030406534322497491">"Kwenziwe"</string>
+    <string name="title_activity_carrier_config" msgid="7807803900475957717">"I-CarrierConfigActivity"</string>
+    <string name="title_activity_service_config" msgid="5394662739555577279">"I-ServiceConfigActivity"</string>
+    <string name="title_activity_test_config" msgid="7585204485536359713">"I-TestConfigActivity"</string>
+    <string name="service_package_name" msgid="7204809439090483315">"Igama lephakheji lesevisi ye-GBA"</string>
+    <string name="service_release_time" msgid="532937496122890892">"Uyikhulula isikhathi eside kangakanani isevisi ngemuva kokushaya"</string>
+    <string name="request_app_type" msgid="3975978141673475612">"Uhlobo Lohlelo Lokusebenza lwe-UICC"</string>
+    <string name="request_naf_url" msgid="4487793541217737042">"Umsebenzi wohlelo lokusebenza lenethiwekhi (NAF) URL"</string>
+    <string name="request_force_bootstrapping" msgid="206043602616214325">"Phoqelela i-Bootstrapping?"</string>
+    <string name="request_org" msgid="8416693445448308975">"Ikhodi yenhlangano"</string>
+    <string name="request_security_protocol" msgid="1444164827561010482">"I-ID Yephrothokholi Yokuphepha ye-UA"</string>
+    <string name="request_tls_cipher_suite" msgid="6659854717595308404">"I-ID ye-TLS Cipher Suite"</string>
+    <string name="response_success" msgid="2469204471244527663">"Ukuphumelela kwe-GBA Auth?"</string>
+    <string name="response_fail_reason" msgid="3401426967253202496">"I-ID Yesizathu Sokwahluleka"</string>
+    <string name="response_key" msgid="8839847772051686309">"Ukhiye we-GBA (CK + IK)"</string>
+    <string name="response_btid" msgid="2550216722679350756">"I-Bootstrapping Transaction Identifier (B-TID)"</string>
+    <string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
+    <string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
+    <string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
+</resources>
diff --git a/testapps/GbaTestApp/res/values/colors.xml b/testapps/GbaTestApp/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/testapps/GbaTestApp/res/values/colors.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="purple_200">#FFBB86FC</color>
+    <color name="purple_500">#FF6200EE</color>
+    <color name="purple_700">#FF3700B3</color>
+    <color name="teal_200">#FF03DAC5</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
diff --git a/testapps/GbaTestApp/res/values/strings.xml b/testapps/GbaTestApp/res/values/strings.xml
new file mode 100644
index 0000000..e74c181
--- /dev/null
+++ b/testapps/GbaTestApp/res/values/strings.xml
@@ -0,0 +1,30 @@
+<resources>
+    <string name="app_name">GbaTestApp</string>
+    <string name="label_settings">Settings</string>
+    <string name="label_carrier">Carrier Config</string>
+    <string name="label_service">Service Config</string>
+    <string name="label_test">Test Config</string>
+    <string name="button_name_running">Running</string>
+    <string name="button_name_exit">Exit</string>
+    <string name="label_test_result">Test Result</string>
+    <string name="button_name_clear">Reset</string>
+    <string name="button_name_done">Done</string>
+    <string name="title_activity_carrier_config">CarrierConfigActivity</string>
+    <string name="title_activity_service_config">ServiceConfigActivity</string>
+    <string name="title_activity_test_config">TestConfigActivity</string>
+    <string name="service_package_name">Package name of GBA service</string>
+    <string name="service_release_time">How long to release service after calling</string>
+    <string name="request_app_type">UICC App Type</string>
+    <string name="request_naf_url">Network application function (NAF) URL</string>
+    <string name="request_force_bootstrapping">Force Bootstrapping?</string>
+    <string name="request_org">Organization Code</string>
+    <string name="request_security_protocol">UA Security Protocol ID</string>
+    <string name="request_tls_cipher_suite">TLS Cipher Suite ID</string>
+    <string name="response_success">GBA Auth Success?</string>
+    <string name="response_fail_reason">Fail Reason ID</string>
+    <string name="response_key">GBA Key (CK + IK)</string>
+    <string name="response_btid">Bootstrapping Transaction Identifier (B-TID)</string>
+    <string name="sample_naf">3GPP-bootstrapping@naf1.operator.com</string>
+    <string name="sample_btid">(B-TID)</string>
+    <string name="sample_key">6629fae49393a05397450978507c4ef1</string>
+</resources>
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/MainActivity.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/MainActivity.java
new file mode 100644
index 0000000..72cbf5c
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/MainActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.phone.testapps.gbatestapp.ui.main.MainFragment;
+
+/** main activity of the gba test app */
+public class MainActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main_activity);
+        if (savedInstanceState == null) {
+            getSupportFragmentManager().beginTransaction()
+                    .replace(R.id.container, MainFragment.newInstance())
+                    .commitNow();
+        }
+    }
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/Settings.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/Settings.java
new file mode 100644
index 0000000..eaa424a
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/Settings.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.ITelephony;
+
+import java.util.Locale;
+
+/** class to load and save the settings */
+public class Settings {
+
+    private static final String TAG = "SETTINGS";
+
+    private static final String PREF_CARRIER_CONFIG = "pref_carrier_config";
+    private static final String KEY_SERVICE_PACKAGE = "key_service_package";
+    private static final String KEY_RELEASE_TIME = "key_release_time";
+
+    private static final String PREF_TEST_CONFIG = "pref_test_config";
+    private static final String KEY_APP_TYPE = "key_app_type";
+    private static final String KEY_NAF_URL = "key_naf_url";
+    private static final String KEY_FORCE_BT = "key_force_bt";
+    private static final String KEY_ORG = "org";
+    private static final String KEY_SP_ID = "key_sp_id";
+    private static final String KEY_TLS_CS = "key_tls_cs";
+
+    private static final String PREF_SERVICE_CONFIG = "pref_carrier_config";
+    private static final String KEY_AUTH_RESULT = "key_auth_result";
+    private static final String KEY_GBA_KEY = "key_gba_key";
+    private static final String KEY_B_TID = "key_b_tid";
+    private static final String KEY_FAIL_REASON = "key_fail_reason";
+
+    private ITelephony mTelephony;
+    private int mSubId;
+    private String mServicePackageName;
+    private int mReleaseTime;
+    private int mAppType;
+    private String mNafUrl;
+    private boolean mForceBootstrap;
+    private int mOrg;
+    private int mSpId;
+    private int mTlsCs;
+    private boolean mIsAuthSuccess;
+    private String mGbaKey;
+    private String mBTid;
+    private int mFailReason;
+
+    private static Settings sInstance;
+
+    private Settings(Context cxt) {
+        mTelephony = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
+                .getTelephonyServiceManager().getTelephonyServiceRegisterer().get());
+        mSubId = SubscriptionManager.getDefaultSubscriptionId();
+        SharedPreferences sharedPref = cxt.getSharedPreferences(
+                PREF_CARRIER_CONFIG, Context.MODE_PRIVATE);
+        mServicePackageName = loadServicePackageName(mSubId, sharedPref);
+        mReleaseTime = loadReleaseTime(mSubId, sharedPref);
+
+        sharedPref = cxt.getSharedPreferences(PREF_TEST_CONFIG, Context.MODE_PRIVATE);
+        mAppType = sharedPref.getInt(KEY_APP_TYPE, TelephonyManager.APPTYPE_SIM);
+        mNafUrl = sharedPref.getString(KEY_NAF_URL, null);
+        mForceBootstrap = sharedPref.getBoolean(KEY_FORCE_BT, false);
+        mOrg = sharedPref.getInt(KEY_ORG, 0);
+        mSpId = sharedPref.getInt(KEY_SP_ID, 0);
+        mTlsCs = sharedPref.getInt(KEY_TLS_CS, 0);
+
+        sharedPref = cxt.getSharedPreferences(PREF_SERVICE_CONFIG, Context.MODE_PRIVATE);
+        mIsAuthSuccess = sharedPref.getBoolean(KEY_AUTH_RESULT, false);
+        mFailReason = sharedPref.getInt(KEY_FAIL_REASON, 0);
+        mGbaKey = sharedPref.getString(KEY_GBA_KEY, null);
+        mBTid = sharedPref.getString(KEY_B_TID, null);
+    }
+
+    /** Get the instance of Settings*/
+    public static Settings getSettings(Context cxt) {
+        if (sInstance == null) {
+            sInstance = new Settings(cxt);
+        }
+
+        return sInstance;
+    }
+
+    /** update carrier config settings */
+    public void updateCarrierConfig(Context cxt, String packageName, int releaseTime) {
+        new Thread(() -> {
+            synchronized (PREF_CARRIER_CONFIG) {
+
+                if (TextUtils.equals(mServicePackageName, packageName)
+                        && (mReleaseTime == releaseTime)) {
+                    return;
+                }
+
+                if (!TextUtils.equals(mServicePackageName, packageName)) {
+                    mServicePackageName = packageName;
+
+                    try {
+                        mTelephony.setBoundGbaServiceOverride(mSubId, packageName);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "fail to set package name due to " + e);
+                    }
+
+                }
+
+                if (mReleaseTime != releaseTime) {
+                    mReleaseTime = releaseTime;
+
+                    try {
+                        mTelephony.setGbaReleaseTimeOverride(mSubId, releaseTime);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "fail to set release time due to " + e);
+                    }
+                }
+
+                SharedPreferences sharedPref = cxt.getSharedPreferences(
+                        PREF_CARRIER_CONFIG, Context.MODE_PRIVATE);
+                SharedPreferences.Editor editor = sharedPref.edit();
+                editor.putString(KEY_SERVICE_PACKAGE, packageName);
+                editor.putInt(KEY_RELEASE_TIME, releaseTime);
+                editor.commit();
+            }
+        }).start();
+    }
+
+    /** get the config of gba service package name */
+    public String getServicePackageName() {
+        synchronized (PREF_CARRIER_CONFIG) {
+            return mServicePackageName;
+        }
+    }
+
+    /** get the config of gba release time */
+    public int getReleaseTime() {
+        synchronized (PREF_CARRIER_CONFIG) {
+            return mReleaseTime;
+        }
+    }
+
+    /** get the config of gba service package name used for now*/
+    public String loadServicePackageName(int subId, SharedPreferences sharedPref) {
+        try {
+            return mTelephony.getBoundGbaService(subId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "fail to get package name due to " + e);
+        }
+        return sharedPref != null ? sharedPref.getString(KEY_SERVICE_PACKAGE, null) : null;
+    }
+
+    /** get the config of gba release time used for now */
+    public int loadReleaseTime(int subId, SharedPreferences sharedPref) {
+        try {
+            return mTelephony.getGbaReleaseTime(subId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "fail to get package name due to " + e);
+        }
+        return sharedPref != null ? sharedPref.getInt(KEY_RELEASE_TIME, 0) : 0;
+    }
+
+    /** update the config of test gba service */
+    public void updateServiceConfig(Context cxt, boolean success, int reason,
+                String key, String btId) {
+        new Thread(() -> {
+            synchronized (PREF_SERVICE_CONFIG) {
+                mIsAuthSuccess = success;
+                mFailReason = reason;
+                mGbaKey = key;
+                mBTid = btId;
+                SharedPreferences sharedPref = cxt.getSharedPreferences(
+                        PREF_SERVICE_CONFIG, Context.MODE_PRIVATE);
+                SharedPreferences.Editor editor = sharedPref.edit();
+                editor.putBoolean(KEY_AUTH_RESULT, success);
+                editor.putInt(KEY_FAIL_REASON, reason);
+                editor.putString(KEY_GBA_KEY, key);
+                editor.putString(KEY_B_TID, btId);
+                editor.commit();
+            }
+        }).start();
+    }
+
+    /** get the config of the authentication result */
+    public boolean getAuthResult() {
+        synchronized (PREF_SERVICE_CONFIG) {
+            return mIsAuthSuccess;
+        }
+    }
+
+    /** get the config of authentication fail cause */
+    public int getFailReason() {
+        synchronized (PREF_SERVICE_CONFIG) {
+            return mFailReason;
+        }
+    }
+
+    /** get the config of GBA key */
+    public String getGbaKey() {
+        synchronized (PREF_SERVICE_CONFIG) {
+            return mGbaKey;
+        }
+    }
+
+    /** get the config of B-Tid */
+    public String getBTid() {
+        synchronized (PREF_SERVICE_CONFIG) {
+            return mBTid;
+        }
+    }
+
+    /** update the config of the test */
+    public void updateTestConfig(Context cxt, int appType, String url,
+            boolean force, int org, int spId, int tlsCs) {
+        new Thread(() -> {
+            synchronized (PREF_TEST_CONFIG) {
+                mAppType = appType;
+                mNafUrl = url;
+                mForceBootstrap = force;
+                mOrg = org;
+                mSpId = spId;
+                mTlsCs = tlsCs;
+
+                SharedPreferences sharedPref = cxt.getSharedPreferences(
+                        PREF_TEST_CONFIG, Context.MODE_PRIVATE);
+                SharedPreferences.Editor editor = sharedPref.edit();
+                editor.putInt(KEY_APP_TYPE, appType);
+                editor.putString(KEY_NAF_URL, url);
+                editor.putBoolean(KEY_FORCE_BT, force);
+                editor.putInt(KEY_ORG, org);
+                editor.putInt(KEY_SP_ID, spId);
+                editor.putInt(KEY_TLS_CS, tlsCs);
+                editor.commit();
+            }
+        }).start();
+    }
+
+    /** get the config of the uicc application type*/
+    public int getAppType() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mAppType;
+        }
+    }
+
+    /** get the config of NAF url */
+    public String getNafUrl() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mNafUrl;
+        }
+    }
+
+    /** get the config if bootstrap is forced */
+    public boolean isForceBootstrap() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mForceBootstrap;
+        }
+    }
+
+    /** get the config of the organization code */
+    public int getOrg() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mOrg;
+        }
+    }
+
+    /** get the config of the security protocol id */
+    public int getSpId() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mSpId;
+        }
+    }
+
+    /** get the config of the tls ciper suite id */
+    public int getTlsCs() {
+        synchronized (PREF_TEST_CONFIG) {
+            return mTlsCs;
+        }
+    }
+
+    /** convert byte arry to hex string */
+    public static String byteArrayToHexString(byte[] data) {
+        if (data == null || data.length == 0) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (byte b : data) {
+            sb.append(String.format(Locale.US, "%02X", b));
+        }
+        return sb.toString();
+    }
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/TestGbaService.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/TestGbaService.java
new file mode 100644
index 0000000..4b0636c
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/TestGbaService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.telephony.gba.GbaService;
+import android.util.Log;
+
+/** test GbaService to be used for Gba api test */
+public class TestGbaService extends GbaService {
+
+    private static final String TAG = "TestGbaService";
+
+    private Settings mSettings;
+
+    @Override
+    public void onCreate() {
+        Log.i(TAG, "TestGbaService: onCreate");
+        mSettings = Settings.getSettings(getApplicationContext());
+    }
+
+    @Override
+    public void onAuthenticationRequest(int subId, int token, int appType,
+            @NonNull Uri nafUrl, @NonNull byte[] securityProtocol, boolean forceBootStrapping) {
+        boolean isSuccess = mSettings.getAuthResult();
+        int reason = mSettings.getFailReason();
+        String key = mSettings.getGbaKey();
+        String btid = mSettings.getBTid();
+
+        if (isSuccess) {
+            reportKeysAvailable(token, key.getBytes(), btid);
+        } else {
+            reportAuthenticationFailure(token, reason);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind intent:" + intent);
+        return super.onBind(intent);
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, "onDestroy!");
+        super.onDestroy();
+    }
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/CarrierConfigFragment.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/CarrierConfigFragment.java
new file mode 100644
index 0000000..b0bfc32
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/CarrierConfigFragment.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp.ui.main;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.phone.testapps.gbatestapp.R;
+import com.android.phone.testapps.gbatestapp.Settings;
+import com.android.phone.testapps.gbatestapp.TestGbaService;
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link CarrierConfigFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class CarrierConfigFragment extends Fragment {
+    private static final String TAG = "CARRIER";
+
+    private static CarrierConfigFragment sInstance;
+
+    private Settings mSettings;
+    private EditText mEditPackageName;
+    private EditText mEditReleaseTime;
+
+    /** get the instance of CarrierConfigFragment */
+    public static CarrierConfigFragment newInstance() {
+        if (sInstance == null) {
+            Log.d(TAG, "new instance:");
+            sInstance = new CarrierConfigFragment();
+        }
+        return sInstance;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSettings = Settings.getSettings(getActivity());
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        View viewHierarchy = inflater.inflate(R.layout.fragment_carrier_config, container, false);
+        mEditPackageName = viewHierarchy.findViewById(R.id.editServicePackageName);
+        mEditReleaseTime = viewHierarchy.findViewById(R.id.editServiceReleaseTime);
+        getConfig(false);
+
+        Button buttonDone = viewHierarchy.findViewById(R.id.carrier_config_done);
+        buttonDone.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mSettings.updateCarrierConfig(getActivity(),
+                                mEditPackageName.getText().toString(),
+                                Integer.parseInt(mEditReleaseTime.getText().toString()));
+                        getFragmentManager().beginTransaction().remove(
+                                CarrierConfigFragment.this).commitNow();
+                    }
+                }
+        );
+
+        Button buttonClear = viewHierarchy.findViewById(R.id.carrier_config_clear);
+        buttonClear.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        getConfig(true);
+                    }
+                }
+        );
+        return viewHierarchy;
+    }
+
+    private void getConfig(boolean isDefault) {
+        String packagename = mSettings.getServicePackageName();
+        if (isDefault || packagename == null) {
+            packagename = TestGbaService.class.getPackage().getName();
+        }
+        mEditPackageName.setText(packagename);
+        mEditReleaseTime.setText(isDefault ? "0" : Integer.toString(mSettings.getReleaseTime()));
+    }
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/MainFragment.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/MainFragment.java
new file mode 100644
index 0000000..ff50f5c
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/MainFragment.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp.ui.main;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.telephony.TelephonyManager;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.android.phone.testapps.gbatestapp.R;
+import com.android.phone.testapps.gbatestapp.Settings;
+
+/** main fragent to update settings and run the test */
+public class MainFragment extends Fragment {
+
+    private static final String TAG = "GBATestApp";
+    private static final String TAG_CARRIER = "carrier";
+    private static final String TAG_SERVICE = "service";
+    private static final String TAG_CLIENT = "client";
+
+    private static MainFragment sInstance;
+
+    private Settings mSettings;
+    private TelephonyManager mTelephonyManager;
+
+    /** Get the instance of MainFragment*/
+    public static MainFragment newInstance() {
+        if (sInstance == null) {
+            sInstance = new MainFragment();
+        }
+        return sInstance;
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+                             @Nullable Bundle savedInstanceState) {
+        View viewHierarchy = inflater.inflate(R.layout.main_fragment, container, false);
+
+        Button buttonCarrier = viewHierarchy.findViewById(R.id.carrier_config_change_button);
+        buttonCarrier.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Fragment carrierFrag = getChildFragmentManager()
+                                .findFragmentByTag(TAG_CARRIER);
+                        if (carrierFrag == null) {
+                            carrierFrag = CarrierConfigFragment.newInstance();
+                        }
+                        getChildFragmentManager()
+                                .beginTransaction()
+                                .replace(R.id.main, carrierFrag, TAG_CARRIER)
+                                .commitNow();
+                    }
+                }
+        );
+
+        Button buttonService = viewHierarchy.findViewById(R.id.service_config);
+        buttonService.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Fragment serviceFrag = getChildFragmentManager()
+                                .findFragmentByTag(TAG_SERVICE);
+                        if (serviceFrag == null) {
+                            serviceFrag = ServiceConfigFragment.newInstance();
+                        }
+                        getChildFragmentManager()
+                                .beginTransaction()
+                                .replace(R.id.main, serviceFrag, TAG_SERVICE)
+                                .commitNow();
+                    }
+                }
+        );
+
+        Button buttonClient = viewHierarchy.findViewById(R.id.client_config);
+        buttonClient.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Fragment testFrag = getChildFragmentManager()
+                                .findFragmentByTag(TAG_CLIENT);
+                        if (testFrag == null) {
+                            testFrag = TestConfigFragment.newInstance();
+                        }
+
+                        getChildFragmentManager()
+                                .beginTransaction()
+                                .replace(R.id.main, testFrag, TAG_CLIENT)
+                                .commitNow();
+                    }
+                }
+        );
+
+        Button buttonExit = viewHierarchy.findViewById(R.id.test_exit);
+        buttonExit.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        getActivity().finish();
+                    }
+                }
+        );
+
+        Button buttonRunning = viewHierarchy.findViewById(R.id.send_request);
+        buttonRunning.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Log.d(TAG, "starting test...");
+                        TelephonyManager.BootstrapAuthenticationCallback cb = new
+                                TelephonyManager.BootstrapAuthenticationCallback() {
+                                    @Override
+                                    public void onKeysAvailable(byte[] gbaKey, String btId) {
+                                        String result = "onKeysAvailable, key:"
+                                                + Settings.byteArrayToHexString(gbaKey)
+                                                + ", btid:" + btId;
+                                        Log.d(TAG, result);
+                                        getActivity().runOnUiThread(()-> {
+                                            mTestLog.append(result + "\n");
+                                        });
+                                    }
+
+                                    @Override
+                                    public void onAuthenticationFailure(int reason) {
+                                        String result = "onAuthFailure, cause:" + reason;
+                                        Log.d(TAG, result);
+                                        getActivity().runOnUiThread(
+                                                () -> mTestLog.append(result + "\n"));
+                                    }
+                                };
+                        UaSecurityProtocolIdentifier.Builder builder =
+                                new UaSecurityProtocolIdentifier.Builder();
+                        try {
+                            if (mSettings.getOrg() != 0 || mSettings.getSpId() != 0
+                                    || mSettings.getTlsCs() != 0) {
+                                builder.setOrg(mSettings.getOrg())
+                                        .setProtocol(mSettings.getSpId())
+                                        .setTlsCipherSuite(mSettings.getTlsCs());
+                            }
+                        } catch (IllegalArgumentException e) {
+                            getActivity().runOnUiThread(() -> mTestLog.append(
+                                    "Fail to create UaSecurityProtocolIdentifier " + e + "\n"));
+                            return;
+                        }
+
+                        UaSecurityProtocolIdentifier spId = builder.build();
+                        Log.d(TAG, "bootstrapAuthenticationRequest with parameters [appType:"
+                                + mSettings.getAppType() + ", NAF:" + mSettings.getNafUrl()
+                                + ", spId:" + spId + ", isForceBootstrap:"
+                                + mSettings.isForceBootstrap() + "]");
+                        try {
+                            mTelephonyManager.bootstrapAuthenticationRequest(
+                                    mSettings.getAppType(), Uri.parse(mSettings.getNafUrl()),
+                                    spId, mSettings.isForceBootstrap(),
+                                    AsyncTask.SERIAL_EXECUTOR, cb);
+                        } catch (NullPointerException e) {
+                            getActivity().runOnUiThread(() -> mTestLog.append(
+                                    "Invalid parameters, please check!" + "\n"));
+                        }
+                    }
+                }
+        );
+
+        return viewHierarchy;
+    }
+
+    TextView mTestLog;
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mTelephonyManager = (TelephonyManager)
+                getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        mSettings = Settings.getSettings(getContext());
+        mTestLog = getActivity().findViewById(R.id.viewTestOutput);
+    }
+
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/ServiceConfigFragment.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/ServiceConfigFragment.java
new file mode 100644
index 0000000..5e7f2fa
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/ServiceConfigFragment.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp.ui.main;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.phone.testapps.gbatestapp.R;
+import com.android.phone.testapps.gbatestapp.Settings;
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link ServiceConfigFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class ServiceConfigFragment extends Fragment {
+
+    private static final String TAG = "SERVICE";
+
+    private static ServiceConfigFragment sInstance;
+
+    private Settings mSettings;
+
+    private CheckBox mAuthResult;
+    private EditText mGbaKey;
+    private EditText mBTid;
+    private EditText mFailReason;
+
+    /** get the instance of ServiceConfigFragment */
+    public static ServiceConfigFragment newInstance() {
+        if (sInstance == null) {
+            sInstance = new ServiceConfigFragment();
+        }
+        return sInstance;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSettings = Settings.getSettings(getActivity());
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View  viewHierarchy = inflater.inflate(R.layout.fragment_service_config, container, false);
+
+        mAuthResult = viewHierarchy.findViewById(R.id.checkBoxResult);
+        mFailReason = viewHierarchy.findViewById(R.id.editFailReason);
+        mGbaKey = viewHierarchy.findViewById(R.id.editKey);
+        mBTid = viewHierarchy.findViewById(R.id.editBTid);
+
+        setDefault();
+
+        Button buttonDone = viewHierarchy.findViewById(R.id.service_config_done);
+        buttonDone.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mSettings.updateServiceConfig(getActivity(), mAuthResult.isChecked(),
+                                Integer.parseInt(mFailReason.getText().toString()),
+                                mGbaKey.getText().toString(), mBTid.getText().toString());
+                        getFragmentManager().beginTransaction()
+                                .remove(ServiceConfigFragment.this).commitNow();
+                    }
+                }
+        );
+
+        Button buttonClear = viewHierarchy.findViewById(R.id.service_config_clear);
+        buttonClear.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        setDefault();
+                    }
+                }
+        );
+
+        return viewHierarchy;
+    }
+
+    private void setDefault() {
+        mAuthResult.setChecked(mSettings.getAuthResult());
+        String key = mSettings.getGbaKey();
+        if (key == null || key.isEmpty()) {
+            key = getString(R.string.sample_key);
+        }
+        mGbaKey.setText(key);
+        String id = mSettings.getBTid();
+        if (id == null || id.isEmpty()) {
+            id = getString(R.string.sample_btid);
+        }
+        mBTid.setText(id);
+        mFailReason.setText(Integer.toString(mSettings.getFailReason()));
+    }
+}
diff --git a/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/TestConfigFragment.java b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/TestConfigFragment.java
new file mode 100644
index 0000000..4049082
--- /dev/null
+++ b/testapps/GbaTestApp/src/com/android/phone/testapps/gbatestapp/ui/main/TestConfigFragment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.gbatestapp.ui.main;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.phone.testapps.gbatestapp.R;
+import com.android.phone.testapps.gbatestapp.Settings;
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link TestConfigFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class TestConfigFragment extends Fragment {
+
+    private static final String TAG = "TEST_CONFIG";
+
+    private static TestConfigFragment sInstance;
+
+    private Settings mSettings;
+
+    private EditText mAppType;
+    private EditText mUrl;
+    private EditText mOrg;
+    private EditText mSpId;
+    private EditText mTlsCs;
+    private CheckBox mForce;
+
+    /** get the instance of TestConfigFragment */
+    public static TestConfigFragment newInstance() {
+        if (sInstance == null) {
+            sInstance = new TestConfigFragment();
+        }
+        return sInstance;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSettings = Settings.getSettings(getActivity());
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View viewHierarchy = inflater.inflate(R.layout.fragment_test_config, container, false);
+        mAppType = viewHierarchy.findViewById(R.id.editAppType);
+        mUrl = viewHierarchy.findViewById(R.id.editUrl);
+        mOrg = viewHierarchy.findViewById(R.id.editOrg);
+        mSpId = viewHierarchy.findViewById(R.id.editSpId);
+        mTlsCs = viewHierarchy.findViewById(R.id.editTlsCs);
+        mForce = viewHierarchy.findViewById(R.id.checkBoxForce);
+
+        setDefault();
+
+        Button buttonDone = viewHierarchy.findViewById(R.id.client_config_done);
+        buttonDone.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Log.d(TAG, "updateTestConfig");
+                        mSettings.updateTestConfig(getActivity(),
+                                Integer.parseInt(mAppType.getText().toString()),
+                                mUrl.getText().toString(),
+                                mForce.isChecked(),
+                                Integer.parseInt(mOrg.getText().toString()),
+                                Integer.parseInt(mSpId.getText().toString()),
+                                Integer.parseInt(mTlsCs.getText().toString()));
+                        getFragmentManager().beginTransaction().remove(
+                                TestConfigFragment.this).commitNow();
+                    }
+                }
+        );
+
+        Button buttonClear = viewHierarchy.findViewById(R.id.client_config_clear);
+        buttonClear.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        setDefault();
+                    }
+                }
+        );
+
+        return viewHierarchy;
+    }
+
+    void setDefault() {
+        Log.d(TAG, "setDefault");
+        mAppType.setText(Integer.toString(mSettings.getAppType()));
+        String naf = mSettings.getNafUrl();
+        if (naf == null || naf.isEmpty()) {
+            naf = getString(R.string.sample_naf);
+        }
+        mUrl.setText(naf);
+        mOrg.setText(Integer.toString(mSettings.getOrg()));
+        mSpId.setText(Integer.toString(mSettings.getSpId()));
+        mTlsCs.setText(Integer.toString(mSettings.getTlsCs()));
+        mForce.setChecked(mSettings.isForceBootstrap());
+    }
+}
diff --git a/testapps/ImsTestService/AndroidManifest.xml b/testapps/ImsTestService/AndroidManifest.xml
index eea54b8..6177e73 100644
--- a/testapps/ImsTestService/AndroidManifest.xml
+++ b/testapps/ImsTestService/AndroidManifest.xml
@@ -16,40 +16,42 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          coreApp="true"
-          package="com.android.phone.testapps.imstestapp">
+     coreApp="true"
+     package="com.android.phone.testapps.imstestapp">
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <!--Beware, declaring the below permission will cause the device to not boot unless you add
         this app and permission to frameworks/base/data/etc/privapp-permissions-platform.xml-->
-    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
-    <application
-        android:label="ImsTestService"
-        android:directBootAware="true">
-        <activity
-            android:name=".ImsTestServiceApp"
-            android:label="ImsTestService">
+    <!--uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/-->
+    <application android:label="ImsTestService"
+         android:directBootAware="true">
+        <activity android:name=".ImsTestServiceApp"
+             android:label="ImsTestService"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
-        <activity android:name=".ImsRegistrationActivity" android:label="IMS Registration" />
-        <activity android:name=".ImsCallingActivity" android:label="IMS Calling" />
-        <activity android:name=".ImsConfigActivity" android:label="IMS Config" />
+        <activity android:name=".ImsRegistrationActivity"
+             android:label="IMS Registration"/>
+        <activity android:name=".ImsCallingActivity"
+             android:label="IMS Calling"/>
+        <activity android:name=".ImsConfigActivity"
+             android:label="IMS Config"/>
 
         <service android:name=".TestImsService"
-                 android:exported="true"
-                 android:enabled="true"
-                 android:persistent="true"
-                 android:permission="android.permission.BIND_IMS_SERVICE">
-            <!--meta-data android:name="android.telephony.ims.MMTEL_FEATURE" android:value="true"/-->
+             android:exported="true"
+             android:enabled="true"
+             android:persistent="true"
+             android:permission="android.permission.BIND_IMS_SERVICE">
+            <!--meta-data android:name="android.telephony.ims.MMTEL_FEATURE"
+                 android:value="true"/-->
             <!-- No features means we will get queried for dynamic config. -->
             <intent-filter>
-                <action android:name="android.telephony.ims.ImsService" />
+                <action android:name="android.telephony.ims.ImsService"/>
             </intent-filter>
         </service>
     </application>
 </manifest>
-
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
index 0ff6cc1..477bbc0 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
@@ -188,6 +188,9 @@
         sb.append("}, \nIWLAN: ");
         sb.append("{");
         sb.append(caps.get(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN));
+        sb.append("}, \nCROSS-SIM: ");
+        sb.append("{");
+        sb.append(caps.get(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM));
         sb.append("}");
         mCapEnabledText.setText(sb.toString());
     }
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java
new file mode 100644
index 0000000..1ae2594
--- /dev/null
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.imstestapp;
+
+import android.telephony.ims.stub.SipTransportImplBase;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test stub implementation of SipTransport.
+ */
+public class SipTransportImpl extends SipTransportImplBase {
+
+    private static SipTransportImpl sSipTransportInstance;
+
+    public static SipTransportImpl getInstance(Executor e) {
+        if (sSipTransportInstance == null) {
+            sSipTransportInstance = new SipTransportImpl(e);
+        }
+        return sSipTransportInstance;
+    };
+
+    public SipTransportImpl(Executor e) {
+        super(e);
+    }
+}
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
index 71323d8..477c638 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
@@ -39,6 +39,7 @@
     public TestMmTelFeatureImpl mTestMmTelFeature;
     public TestRcsFeatureImpl mTestRcsFeature;
     public TestImsConfigImpl mTestImsConfig;
+    public SipTransportImpl mSipTransportImpl;
 
     public static TestImsService getInstance() {
         return mInstance;
@@ -51,7 +52,8 @@
         mTestMmTelFeature = TestMmTelFeatureImpl.getInstance();
         mTestRcsFeature = new TestRcsFeatureImpl();
         mTestImsConfig = TestImsConfigImpl.getInstance();
-
+        mSipTransportImpl = SipTransportImpl.getInstance(
+                getApplicationContext().getMainExecutor());
         mInstance = this;
     }
 
@@ -60,10 +62,16 @@
         return new ImsFeatureConfiguration.Builder()
                 .addFeature(0, ImsFeature.FEATURE_EMERGENCY_MMTEL)
                 .addFeature(0, ImsFeature.FEATURE_MMTEL)
+                .addFeature(0, ImsFeature.FEATURE_RCS)
                 .build();
     }
 
     @Override
+    public long getImsServiceCapabilities() {
+        return CAPABILITY_SIP_DELEGATE_CREATION;
+    }
+
+    @Override
     public MmTelFeature createMmTelFeature(int slotId) {
         Log.i(LOG_TAG, "TestImsService: onCreateMmTelImsFeature");
         return mTestMmTelFeature;
@@ -84,4 +92,9 @@
     public ImsConfigImplBase getConfig(int slotId) {
         return mTestImsConfig;
     }
+
+    @Override
+    public SipTransportImpl getSipTransport(int slotId) {
+        return mSipTransportImpl;
+    }
 }
diff --git a/testapps/SmsManagerTestApp/AndroidManifest.xml b/testapps/SmsManagerTestApp/AndroidManifest.xml
index c5f4621..7dc717f 100644
--- a/testapps/SmsManagerTestApp/AndroidManifest.xml
+++ b/testapps/SmsManagerTestApp/AndroidManifest.xml
@@ -16,29 +16,86 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.phone.testapps.smsmanagertestapp">
-    <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="29" />
+     package="com.android.phone.testapps.smsmanagertestapp">
+    <uses-sdk android:minSdkVersion="24"
+         android:targetSdkVersion="29"/>
     <uses-permission android:name="android.permission.SEND_SMS"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <application android:label="SmsManagerTestApp">
-        <activity
-            android:name=".SmsManagerTestApp"
-            android:label="SmsManagerTestApp">
+        <activity android:name=".SmsManagerTestApp"
+             android:label="SmsManagerTestApp"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
-        <service android:name=".SmsManagerTestService" android:exported="false" />
+        <service android:name=".SmsManagerTestService"
+             android:exported="false"/>
         <receiver android:name=".SendStatusReceiver"
-                  android:exported="false">
+             android:exported="false">
             <intent-filter>
-                <action android:name="com.android.phone.testapps.smsmanagertestapp.message_sent_action" />
-                <data android:scheme="content" />
+                <action android:name="com.android.phone.testapps.smsmanagertestapp.message_sent_action"/>
+                <data android:scheme="content"/>
+            </intent-filter>
+        </receiver>
+        <service android:name=".PersistentService"
+                 android:exported="false"
+                 android:process=":persistent"
+                 android:permission="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE">
+            <intent-filter>
+                <action android:name="android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE" />
+            </intent-filter>
+        </service>
+
+        <!-- Stuff required to become the default messaging app defined below, doesn't actually do
+             anything useful for now. -->
+
+        <!-- Fake BroadcastReceiver that listens for incoming SMS messages -->
+        <receiver android:name=".SmsReceiver"
+                  android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_DELIVER" />
             </intent-filter>
         </receiver>
 
+        <!-- Fake BroadcastReceiver that listens for incoming MMS messages -->
+        <receiver android:name=".MmsReceiver"
+                  android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Fake Activity that allows the user to send new SMS/MMS messages -->
+        <activity android:name=".ComposeSmsActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SENDTO" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </activity>
+
+        <!-- Fake Service that delivers messages from the phone "quick response" -->
+        <service android:name=".HeadlessSmsSendService"
+                 android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+                 android:exported="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </service>
+
     </application>
 </manifest>
-
diff --git a/testapps/SmsManagerTestApp/res/layout/activity_main.xml b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
index 39fb6c6..185e0e2 100644
--- a/testapps/SmsManagerTestApp/res/layout/activity_main.xml
+++ b/testapps/SmsManagerTestApp/res/layout/activity_main.xml
@@ -63,5 +63,17 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/get_sub_for_result_button"/>
+        <Button
+            android:id="@+id/enable_persistent_service"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/enable_persistent_service"/>
+        <Button
+            android:id="@+id/disable_persistent_service"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/disable_persistent_service"/>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
index d6497a3..c8b9f91 100644
--- a/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
+++ b/testapps/SmsManagerTestApp/res/values/donottranslate_strings.xml
@@ -19,4 +19,6 @@
     <string name="send_text_button">Send Outgoing Text Now.</string>
     <string name="send_text_service_button">Send Outgoing Text after 5 sec.</string>
     <string name="get_sub_for_result_button">Ask user for sub id.</string>
+    <string name="enable_persistent_service">Enable Persistent Service</string>
+    <string name="disable_persistent_service">Disable Persistent Service</string>
 </resources>
\ No newline at end of file
diff --git a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java
new file mode 100644
index 0000000..16b7ecd
--- /dev/null
+++ b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/PersistentService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.smsmanagertestapp;
+
+import android.content.Intent;
+import android.service.carrier.CarrierMessagingClientService;
+import android.util.Log;
+
+/**
+ * A test persistent service that should be started by the framework when this app becomes the
+ * default SMS app and destroyed when it is removed. See {@link CarrierMessagingClientService} for
+ * more information.
+ */
+public class PersistentService extends CarrierMessagingClientService {
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.i("SmsTestApp", "onCreate");
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.i("SmsTestApp", "onDestroy");
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.i("SmsTestApp", "onUnbind");
+        return false;
+    }
+}
diff --git a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
index 75536f3..785fe3f 100644
--- a/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
+++ b/testapps/SmsManagerTestApp/src/com/android/phone/testapps/smsmanagertestapp/SmsManagerTestApp.java
@@ -66,6 +66,10 @@
         findViewById(R.id.send_text_button_service)
                 .setOnClickListener(this::sendOutgoingSmsService);
         findViewById(R.id.get_sub_for_result_button).setOnClickListener(this::getSubIdForResult);
+        findViewById(R.id.enable_persistent_service)
+                .setOnClickListener(this::setPersistentServiceComponentEnabled);
+        findViewById(R.id.disable_persistent_service)
+                .setOnClickListener(this::setPersistentServiceComponentDisabled);
         mPhoneNumber = (EditText) findViewById(R.id.phone_number_text);
     }
 
@@ -183,6 +187,21 @@
         }
     }
 
+    private void setPersistentServiceComponentEnabled(View view) {
+        getPackageManager().setComponentEnabledSetting(
+                new ComponentName(this, PersistentService.class),
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+    private void setPersistentServiceComponentDisabled(View view) {
+        getPackageManager().setComponentEnabledSetting(
+                new ComponentName(this, PersistentService.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+
     private Intent getSendStatusIntent() {
         // Encode requestId in intent data
         return new Intent(SendStatusReceiver.MESSAGE_SENT_ACTION, null, this,
diff --git a/testapps/TelephonyManagerTestApp/AndroidManifest.xml b/testapps/TelephonyManagerTestApp/AndroidManifest.xml
index 044d0b2..40fc549 100644
--- a/testapps/TelephonyManagerTestApp/AndroidManifest.xml
+++ b/testapps/TelephonyManagerTestApp/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.phone.testapps.telephonymanagertestapp">
+     package="com.android.phone.testapps.telephonymanagertestapp">
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
@@ -26,31 +26,29 @@
     <uses-permission android:name="android.permission.CALL_PRIVILEGED"/>
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
 
-    android.Manifest.permission.ACCESS_FINE_LOCATION
+            android.Manifest.permission.ACCESS_FINE_LOCATION
     <application android:label="TelephonyManagerTestApp">
-        <activity
-            android:name=".TelephonyManagerTestApp"
-            android:label="TelephonyManagerTestApp">
+        <activity android:name=".TelephonyManagerTestApp"
+             android:label="TelephonyManagerTestApp"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.intent.action.SEARCH" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.intent.action.SEARCH"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
-            <meta-data
-                android:name="android.app.searchable"
-                android:resource="@xml/searchable">
+            <meta-data android:name="android.app.searchable"
+                 android:resource="@xml/searchable">
             </meta-data>
         </activity>
 
-        <activity
-            android:name=".CallingMethodActivity"
-            android:label="CallingMethodActivity">
+        <activity android:name=".CallingMethodActivity"
+             android:label="CallingMethodActivity"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
     </application>
 </manifest>
-
diff --git a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
index 550c9f0..7432156 100644
--- a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
+++ b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
@@ -15,24 +15,23 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.phone.testapps.telephonyregistry">
+     package="com.android.phone.testapps.telephonyregistry">
     <uses-sdk android:minSdkVersion="25"
-          android:targetSdkVersion="25"/>
+         android:targetSdkVersion="25"/>
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
     <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE"/>
     <application android:label="TelephonyRegistryTestApp">
-        <activity
-            android:name=".TelephonyRegistryTestApp"
-            android:label="TelephonyRegistryTestApp">
+        <activity android:name=".TelephonyRegistryTestApp"
+             android:label="TelephonyRegistryTestApp"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
     </application>
 </manifest>
-
diff --git a/tests/Android.bp b/tests/Android.bp
index 7ed234e..4eacf6d 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -33,10 +33,15 @@
     instrumentation_for: "TeleService",
 
     static_libs: [
+        "androidx.test.core",
+        "androidx.test.espresso.core",
+        "androidx.test.ext.junit",
         "androidx.test.rules",
         "mockito-target-minus-junit4",
-        "androidx.test.espresso.core",
+        "telephony-common-testing",
+        "testng",
         "truth-prebuilt",
+	"testables",
     ],
 
     test_suites: [
@@ -45,3 +50,4 @@
     ],
 
 }
+
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index d434650..174d22e 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -31,6 +31,7 @@
                 adb shell am start -n com.android.phone.tests/.CallDialTest
         -->
         <activity android:name="CallDialTest"
+                  android:exported="true"
                   android:label="@string/callDialTestLabel">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -39,6 +40,7 @@
         </activity>
 
         <service android:name="SendInstantTextTestService"
+                 android:exported="true"
                  android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" >
             <intent-filter>
                 <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index 132d893..09abb15 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -27,6 +27,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -58,6 +59,21 @@
         PhoneConfigurationManager.unregisterAllMultiSimConfigChangeRegistrants();
     }
 
+    protected final boolean waitForExecutorAction(Executor executor, long timeoutMillis) {
+        final CountDownLatch lock = new CountDownLatch(1);
+        executor.execute(() -> {
+            lock.countDown();
+        });
+        while (lock.getCount() > 0) {
+            try {
+                return lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                // do nothing
+            }
+        }
+        return true;
+    }
+
     protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
         final CountDownLatch lock = new CountDownLatch(1);
         h.post(lock::countDown);
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index c5b9b1e..9d712d3 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -17,9 +17,10 @@
 package com.android;
 
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doAnswer;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -29,10 +30,13 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsManager;
 import android.test.mock.MockContext;
+import android.util.SparseArray;
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 import java.util.concurrent.Executor;
 
@@ -42,12 +46,21 @@
     @Mock TelecomManager mMockTelecomManager;
     @Mock TelephonyManager mMockTelephonyManager;
     @Mock SubscriptionManager mMockSubscriptionManager;
+    @Mock ImsManager mMockImsManager;
 
-    private PersistableBundle mCarrierConfig = new PersistableBundle();
+    private SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
 
     public TestContext() {
         MockitoAnnotations.initMocks(this);
-        doReturn(mCarrierConfig).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+        doAnswer((Answer<PersistableBundle>) invocation -> {
+            int subId = (int) invocation.getArguments()[0];
+            if (subId < 0) {
+                return new PersistableBundle();
+            }
+            PersistableBundle b = mCarrierConfigs.get(subId);
+
+            return (b != null ? b : new PersistableBundle());
+        }).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
     }
 
     @Override
@@ -94,6 +107,11 @@
     }
 
     @Override
+    public ContentResolver getContentResolver() {
+        return null;
+    }
+
+    @Override
     public Object getSystemService(String name) {
         switch (name) {
             case (Context.CARRIER_CONFIG_SERVICE) : {
@@ -108,6 +126,9 @@
             case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
                 return mMockSubscriptionManager;
             }
+            case(Context.TELEPHONY_IMS_SERVICE) : {
+                return mMockImsManager;
+            }
         }
         return null;
     }
@@ -129,7 +150,15 @@
         return null;
     }
 
-    public PersistableBundle getCarrierConfig() {
-        return mCarrierConfig;
+    /**
+     * @return CarrierConfig PersistableBundle for the subscription specified.
+     */
+    public PersistableBundle getCarrierConfig(int subId) {
+        PersistableBundle b = mCarrierConfigs.get(subId);
+        if (b == null) {
+            b = new PersistableBundle();
+            mCarrierConfigs.put(subId, b);
+        }
+        return b;
     }
 }
diff --git a/tests/src/com/android/TestExecutorService.java b/tests/src/com/android/TestExecutorService.java
new file mode 100644
index 0000000..fec502a
--- /dev/null
+++ b/tests/src/com/android/TestExecutorService.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An implementation of ExecutorService that just runs the requested task on the thread that it
+ * was called on for testing purposes.
+ */
+public class TestExecutorService implements ScheduledExecutorService {
+
+    private static class CompletedFuture<T> implements Future<T>, ScheduledFuture<T> {
+
+        private final Callable<T> mTask;
+        private final long mDelayMs;
+
+        CompletedFuture(Callable<T> task) {
+            mTask = task;
+            mDelayMs = 0;
+        }
+
+        CompletedFuture(Callable<T> task, long delayMs) {
+            mTask = task;
+            mDelayMs = delayMs;
+        }
+
+        @Override
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            return false;
+        }
+
+        @Override
+        public boolean isCancelled() {
+            return false;
+        }
+
+        @Override
+        public boolean isDone() {
+            return true;
+        }
+
+        @Override
+        public T get() throws InterruptedException, ExecutionException {
+            try {
+                return mTask.call();
+            } catch (Exception e) {
+                throw new ExecutionException(e);
+            }
+        }
+
+        @Override
+        public T get(long timeout, TimeUnit unit)
+                throws InterruptedException, ExecutionException, TimeoutException {
+            try {
+                return mTask.call();
+            } catch (Exception e) {
+                throw new ExecutionException(e);
+            }
+        }
+
+        @Override
+        public long getDelay(TimeUnit unit) {
+            if (unit == TimeUnit.MILLISECONDS) {
+                return mDelayMs;
+            } else {
+                // not implemented
+                return 0;
+            }
+        }
+
+        @Override
+        public int compareTo(Delayed o) {
+            if (o == null) return 1;
+            if (o.getDelay(TimeUnit.MILLISECONDS) > mDelayMs) return -1;
+            if (o.getDelay(TimeUnit.MILLISECONDS) < mDelayMs) return 1;
+            return 0;
+        }
+    }
+
+    @Override
+    public void shutdown() {
+    }
+
+    @Override
+    public List<Runnable> shutdownNow() {
+        return null;
+    }
+
+    @Override
+    public boolean isShutdown() {
+        return false;
+    }
+
+    @Override
+    public boolean isTerminated() {
+        return false;
+    }
+
+    @Override
+    public boolean awaitTermination(long timeout, TimeUnit unit) {
+        return false;
+    }
+
+    @Override
+    public <T> Future<T> submit(Callable<T> task) {
+        return new CompletedFuture<>(task);
+    }
+
+    @Override
+    public <T> Future<T> submit(Runnable task, T result) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public Future<?> submit(Runnable task) {
+        task.run();
+        return new CompletedFuture<>(() -> null);
+    }
+
+    @Override
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
+            TimeUnit unit) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+        // No need to worry about delays yet
+        command.run();
+        return new CompletedFuture<>(() -> null, delay);
+    }
+
+    @Override
+    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+        return new CompletedFuture<>(callable, delay);
+    }
+
+    @Override
+    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
+            TimeUnit unit) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
+            long delay, TimeUnit unit) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public void execute(Runnable command) {
+        command.run();
+    }
+}
diff --git a/tests/src/com/android/phone/LocationAccessPolicyBuilderTest.java b/tests/src/com/android/phone/LocationAccessPolicyBuilderTest.java
new file mode 100644
index 0000000..4fe2da9
--- /dev/null
+++ b/tests/src/com/android/phone/LocationAccessPolicyBuilderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static org.junit.Assert.fail;
+
+import android.os.Build;
+import android.telephony.LocationAccessPolicy;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class LocationAccessPolicyBuilderTest {
+    @Test
+    public void testBuilderMissingMinCoarse() {
+        try {
+            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                    .setMethod("test")
+                    .setCallingPackage("com.android.test")
+                    .setCallingFeatureId(null)
+                    .setCallingPid(0)
+                    .setCallingUid(0)
+                    .setMinSdkVersionForFine(Build.VERSION_CODES.N)
+                    .build();
+            fail("Should have failed without specifying min version for coarse");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testBuilderMissingMinFine() {
+        try {
+            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                    .setMethod("test")
+                    .setCallingPackage("com.android.test")
+                    .setCallingFeatureId(null)
+                    .setCallingPid(0)
+                    .setCallingUid(0)
+                    .setMinSdkVersionForCoarse(Build.VERSION_CODES.N)
+                    .build();
+            fail("Should have failed without specifying min version for fine");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testBuilderMissingMinEnforcement() {
+        try {
+            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                    .setMethod("test")
+                    .setCallingPackage("com.android.test")
+                    .setCallingFeatureId(null)
+                    .setCallingPid(0)
+                    .setCallingUid(0)
+                    .setMinSdkVersionForFine(Build.VERSION_CODES.N)
+                    .setMinSdkVersionForCoarse(Build.VERSION_CODES.N)
+                    .build();
+            fail("Should have failed without specifying min version for any enforcement");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/tests/src/com/android/phone/LocationAccessPolicyTest.java b/tests/src/com/android/phone/LocationAccessPolicyTest.java
index b2489e7..84bf619 100644
--- a/tests/src/com/android/phone/LocationAccessPolicyTest.java
+++ b/tests/src/com/android/phone/LocationAccessPolicyTest.java
@@ -242,6 +242,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(false)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.N)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.N)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.N).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.DENIED_SOFT)
@@ -254,6 +255,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.N)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.N)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.N).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.ALLOWED)
@@ -266,6 +268,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.JELLY_BEAN)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.JELLY_BEAN)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.M)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.JELLY_BEAN).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.ALLOWED)
@@ -278,6 +281,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.N)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.N)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.N).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.DENIED_HARD)
@@ -292,6 +296,7 @@
                 .setQuery(getDefaultQueryBuilder()
                         .setMinSdkVersionForFine(
                                 LocationAccessPolicy.MAX_SDK_FOR_ANY_ENFORCEMENT + 1)
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.N)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.N).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.ALLOWED)
                 .build());
@@ -303,6 +308,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.N)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.P)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.N).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.DENIED_HARD)
@@ -316,6 +322,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.O)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.P)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.O).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.DENIED_HARD)
@@ -326,6 +333,7 @@
                 .setAppSdkLevel(Build.VERSION_CODES.N)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.O)
                         .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.O).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.ALLOWED)
@@ -338,6 +346,9 @@
                 .setAppSdkLevel(Build.VERSION_CODES.P)
                 .setIsDynamicLocationEnabled(true)
                 .setQuery(getDefaultQueryBuilder()
+                        .setMinSdkVersionForEnforcement(Build.VERSION_CODES.P)
+                        .setMinSdkVersionForFine(
+                                LocationAccessPolicy.MAX_SDK_FOR_ANY_ENFORCEMENT + 1)
                         .setMinSdkVersionForCoarse(Build.VERSION_CODES.P).build())
                 .setExpectedResult(LocationAccessPolicy.LocationPermissionResult.ALLOWED)
                 .build());
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
new file mode 100644
index 0000000..6c36c2c
--- /dev/null
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -0,0 +1,570 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.provider.Telephony.SimInfo;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyRegistryManager;
+import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.RcsConfig;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IRcsConfigCallback;
+import android.telephony.ims.feature.ImsFeature;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+import android.util.Log;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.ims.ImsResolver;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Unit tests for RcsProvisioningMonitor
+ */
+public class RcsProvisioningMonitorTest {
+    private static final String TAG = "RcsProvisioningMonitorTest";
+    private static final String SAMPLE_CONFIG = "<RCSConfig>\n"
+            + "\t<rcsVolteSingleRegistration>1</rcsVolteSingleRegistration>\n"
+            + "\t<SERVICES>\n"
+            + "\t\t<SupportedRCSProfileVersions>UP_2.0</SupportedRCSProfileVersions>\n"
+            + "\t\t<ChatAuth>1</ChatAuth>\n"
+            + "\t\t<GroupChatAuth>1</GroupChatAuth>\n"
+            + "\t\t<ftAuth>1</ftAuth>\n"
+            + "\t\t<standaloneMsgAuth>1</standaloneMsgAuth>\n"
+            + "\t\t<geolocPushAuth>1</geolocPushAuth>\n"
+            + "\t\t<Ext>\n"
+            + "\t\t\t<DataOff>\n"
+            + "\t\t\t\t<rcsMessagingDataOff>1</rcsMessagingDataOff>\n"
+            + "\t\t\t\t<fileTransferDataOff>1</fileTransferDataOff>\n"
+            + "\t\t\t\t<mmsDataOff>1</mmsDataOff>\n"
+            + "\t\t\t\t<syncDataOff>1</syncDataOff>\n"
+            + "\t\t\t</DataOff>\n"
+            + "\t\t</Ext>\n"
+            + "\t</SERVICES>\n"
+            + "</RCSConfig>";
+    private static final int FAKE_SUB_ID_BASE = 0x0FFFFFF0;
+    private static final String DEFAULT_MESSAGING_APP1 = "DMA1";
+    private static final String DEFAULT_MESSAGING_APP2 = "DMA2";
+
+    private RcsProvisioningMonitor mRcsProvisioningMonitor;
+    private Handler mHandler;
+    private HandlerThread mHandlerThread;
+    private TestableLooper mLooper;
+    private PersistableBundle mBundle;
+    private MockContentResolver mContentResolver = new MockContentResolver();
+    private SimInfoContentProvider mProvider;
+    private BroadcastReceiver mReceiver;
+    @Mock
+    private Cursor mCursor;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
+    @Mock
+    private TelephonyRegistryManager mTelephonyRegistryManager;
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+    private OnRoleHoldersChangedListener mRoleHolderChangedListener;
+    @Mock
+    private RcsProvisioningMonitor.RoleManagerAdapter mRoleManager;
+    @Mock
+    private ITelephony.Stub mITelephony;
+    @Mock
+    private ImsResolver mImsResolver;
+    @Mock
+    private IImsConfig.Stub mIImsConfig;
+    @Mock
+    private Resources mResources;
+    @Mock
+    private PhoneGlobals mPhone;
+    @Mock
+    private IRcsConfigCallback mCallback;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private Executor mExecutor = new Executor() {
+        @Override
+        public void execute(Runnable r) {
+            r.run();
+        }
+    };
+
+    private class SimInfoContentProvider extends MockContentProvider {
+        private Cursor mCursor;
+        private ContentValues mValues;
+
+        SimInfoContentProvider(Context context) {
+            super(context);
+        }
+
+        public void setCursor(Cursor cursor) {
+            mCursor = cursor;
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection,
+                String[] selectionArgs, String sortOrder) {
+            return mCursor;
+        }
+
+        @Override
+        public int update(Uri uri, ContentValues values,
+                String selection, String[] selectionArgs) {
+            mValues = values;
+            return 1;
+        }
+
+        ContentValues getContentValues() {
+            return mValues;
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mPhone.getResources()).thenReturn(mResources);
+        when(mPhone.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        when(mPhone.getMainExecutor()).thenReturn(mExecutor);
+        when(mPhone.getSystemServiceName(eq(CarrierConfigManager.class)))
+                .thenReturn(Context.CARRIER_CONFIG_SERVICE);
+        when(mPhone.getSystemServiceName(eq(SubscriptionManager.class)))
+                .thenReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        when(mPhone.getSystemServiceName(eq(TelephonyRegistryManager.class)))
+                .thenReturn(Context.TELEPHONY_REGISTRY_SERVICE);
+        when(mPhone.getSystemServiceName(eq(RoleManager.class)))
+                .thenReturn(Context.ROLE_SERVICE);
+        when(mPhone.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE)))
+                .thenReturn(mCarrierConfigManager);
+        when(mPhone.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
+                .thenReturn(mSubscriptionManager);
+        when(mPhone.getSystemService(eq(Context.TELEPHONY_REGISTRY_SERVICE)))
+                .thenReturn(mTelephonyRegistryManager);
+
+        mBundle = new PersistableBundle();
+        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                mReceiver = (BroadcastReceiver) invocation.getArguments()[0];
+                return null;
+            }
+        }).when(mPhone).registerReceiver(any(BroadcastReceiver.class), any());
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                mSubChangedListener = (SubscriptionManager.OnSubscriptionsChangedListener)
+                        invocation.getArguments()[0];
+                return null;
+            }
+        }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(
+                any(SubscriptionManager.OnSubscriptionsChangedListener.class),
+                any());
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                mRoleHolderChangedListener = (OnRoleHoldersChangedListener)
+                        invocation.getArguments()[1];
+                return null;
+            }
+        }).when(mRoleManager).addOnRoleHoldersChangedListenerAsUser(any(Executor.class),
+                any(OnRoleHoldersChangedListener.class), any(UserHandle.class));
+        List<String> dmas = new ArrayList<>();
+        dmas.add(DEFAULT_MESSAGING_APP1);
+        when(mRoleManager.getRoleHolders(eq(RoleManager.ROLE_SMS))).thenReturn(dmas);
+
+        mProvider = new SimInfoContentProvider(mPhone);
+        mProvider.setCursor(mCursor);
+        mContentResolver.addProvider(SimInfo.CONTENT_URI.getAuthority(), mProvider);
+        when(mPhone.getContentResolver()).thenReturn(mContentResolver);
+        when(mCursor.moveToFirst()).thenReturn(true);
+        when(mCursor.getColumnIndexOrThrow(any())).thenReturn(1);
+        when(mCursor.getBlob(anyInt())).thenReturn(
+                RcsConfig.compressGzip(SAMPLE_CONFIG.getBytes()));
+        when(mPhone.getImsResolver()).thenReturn(mImsResolver);
+        when(mImsResolver.getImsConfig(anyInt(), anyInt())).thenReturn(mIImsConfig);
+        mHandlerThread = new HandlerThread("RcsProvisioningMonitorTest");
+        mHandlerThread.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (mRcsProvisioningMonitor != null) {
+            mRcsProvisioningMonitor.destroy();
+            mRcsProvisioningMonitor = null;
+        }
+
+        if (mLooper != null) {
+            mLooper.destroy();
+            mLooper = null;
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testInitWithSavedConfig() throws Exception {
+        createMonitor(3);
+        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        for (int i = 0; i < 3; i++) {
+            assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+                    mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
+        }
+
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        Intent capturedIntent = captorIntent.getAllValues().get(1);
+        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
+                capturedIntent.getAction());
+        PhoneGlobals.getInstance().getImsResolver();
+        verify(mPhone, atLeastOnce()).getImsResolver();
+        verify(mIImsConfig, times(3)).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testInitWithoutSavedConfig() throws Exception {
+        when(mCursor.getBlob(anyInt())).thenReturn(null);
+        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        createMonitor(3);
+
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        Intent capturedIntent = captorIntent.getAllValues().get(1);
+        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
+                capturedIntent.getAction());
+        //Should not notify null config
+        verify(mIImsConfig, never()).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testSubInfoChanged() throws Exception {
+        createMonitor(3);
+        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        mExecutor.execute(() -> mSubChangedListener.onSubscriptionsChanged());
+        processAllMessages();
+        for (int i = 0; i < 3; i++) {
+            assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+                    mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
+        }
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture());
+        Intent capturedIntent = captorIntent.getAllValues().get(1);
+        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
+                capturedIntent.getAction());
+        verify(mIImsConfig, times(3)).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+
+        makeFakeActiveSubIds(1);
+        mExecutor.execute(() -> mSubChangedListener.onSubscriptionsChanged());
+        processAllMessages();
+
+        for (int i = 1; i < 3; i++) {
+            assertNull(mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i));
+        }
+        verify(mIImsConfig, times(2)).notifyRcsAutoConfigurationRemoved();
+    }
+
+    @Test
+    @SmallTest
+    public void testDefaultMessagingApplicationChangedWithAcs() throws Exception {
+        createMonitor(1);
+        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
+        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, true);
+        processAllMessages();
+        byte[] configCached = mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE);
+
+        assertNull(configCached);
+        assertNull(mProvider.getContentValues().get(SimInfo.COLUMN_RCS_CONFIG));
+        verify(mIImsConfig, atLeastOnce()).notifyRcsAutoConfigurationRemoved();
+        verify(mIImsConfig, atLeastOnce()).triggerRcsReconfiguration();
+        // The api should only be called when monitor is initilized.
+        verify(mIImsConfig, times(1))
+                .notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testDefaultMessagingApplicationChangedWithoutAcs() throws Exception {
+        createMonitor(1);
+        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
+        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, false);
+        processAllMessages();
+        byte[] configCached = mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE);
+
+        assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), configCached));
+        verify(mIImsConfig, never()).notifyRcsAutoConfigurationRemoved();
+        // The api should be called 2 times, one happens when monitor is initilized,
+        // Another happens when DMS is changed.
+        verify(mIImsConfig, times(2))
+                .notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testCarrierConfigChanged() throws Exception {
+        createMonitor(1);
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        Intent capturedIntent = captorIntent.getValue();
+        assertEquals(capturedIntent.getAction(),
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
+        assertEquals(FAKE_SUB_ID_BASE, capturedIntent.getIntExtra(
+                ProvisioningManager.EXTRA_SUBSCRIPTION_ID, -1));
+        assertEquals(ProvisioningManager.STATUS_CAPABLE,
+                capturedIntent.getIntExtra(ProvisioningManager.EXTRA_STATUS, -1));
+
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        capturedIntent = captorIntent.getValue();
+        assertEquals(capturedIntent.getAction(),
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
+        assertEquals(FAKE_SUB_ID_BASE, capturedIntent.getIntExtra(
+                ProvisioningManager.EXTRA_SUBSCRIPTION_ID, -1));
+        assertEquals(ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE,
+                capturedIntent.getIntExtra(ProvisioningManager.EXTRA_STATUS, -1));
+
+
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture());
+        capturedIntent = captorIntent.getValue();
+        assertEquals(capturedIntent.getAction(),
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
+        assertEquals(FAKE_SUB_ID_BASE, capturedIntent.getIntExtra(
+                ProvisioningManager.EXTRA_SUBSCRIPTION_ID, -1));
+        assertEquals(ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE
+                | ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE,
+                capturedIntent.getIntExtra(ProvisioningManager.EXTRA_STATUS, -1));
+    }
+
+    @Test
+    @SmallTest
+    public void testUpdateConfig() throws Exception {
+        createMonitor(1);
+        final ArgumentCaptor<byte[]> argumentBytes = ArgumentCaptor.forClass(byte[].class);
+
+        mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+        processAllMessages();
+
+        verify(mImsResolver, atLeastOnce()).getImsConfig(
+                anyInt(), eq(ImsFeature.FEATURE_RCS));
+        verify(mIImsConfig, atLeastOnce()).notifyRcsAutoConfigurationReceived(
+                argumentBytes.capture(), eq(false));
+        assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), argumentBytes.getValue()));
+    }
+
+    @Test
+    @SmallTest
+    public void testRequestReconfig() throws Exception {
+        createMonitor(1);
+
+        mRcsProvisioningMonitor.requestReconfig(FAKE_SUB_ID_BASE);
+        processAllMessages();
+
+        verify(mImsResolver, atLeastOnce()).getImsConfig(
+                anyInt(), eq(ImsFeature.FEATURE_RCS));
+        verify(mIImsConfig, times(1)).notifyRcsAutoConfigurationRemoved();
+        verify(mIImsConfig, times(1)).triggerRcsReconfiguration();
+    }
+
+    @Test
+    @SmallTest
+    public void testIsRcsVolteSingleRegistrationEnabled() throws Exception {
+        createMonitor(1);
+
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        assertTrue(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+    }
+
+    @Test
+    @SmallTest
+    public void testRegisterThenUnregisterCallback() throws Exception {
+        createMonitor(1);
+
+        boolean result = mRcsProvisioningMonitor.registerRcsProvisioningChangedCallback(
+                FAKE_SUB_ID_BASE, mCallback);
+
+        assertTrue(result);
+        verify(mIImsConfig, times(1)).addRcsConfigCallback(eq(mCallback));
+
+        result = mRcsProvisioningMonitor.unregisterRcsProvisioningChangedCallback(
+                FAKE_SUB_ID_BASE, mCallback);
+
+        assertTrue(result);
+        verify(mIImsConfig, times(1)).removeRcsConfigCallback(eq(mCallback));
+        verify(mCallback, times(1)).onRemoved();
+    }
+
+    @Test
+    @SmallTest
+    public void testCallbackRemovedWhenSubInfoChanged() throws Exception {
+        createMonitor(1);
+
+        boolean result = mRcsProvisioningMonitor.registerRcsProvisioningChangedCallback(
+                FAKE_SUB_ID_BASE, mCallback);
+        makeFakeActiveSubIds(0);
+        mExecutor.execute(() -> mSubChangedListener.onSubscriptionsChanged());
+        processAllMessages();
+
+        assertTrue(result);
+        verify(mIImsConfig, times(1)).removeRcsConfigCallback(eq(mCallback));
+        verify(mCallback, times(1)).onRemoved();
+    }
+
+    @Test
+    @SmallTest
+    public void testCallbackRemovedWhenDmaChanged() throws Exception {
+        createMonitor(1);
+
+        boolean result = mRcsProvisioningMonitor.registerRcsProvisioningChangedCallback(
+                FAKE_SUB_ID_BASE, mCallback);
+        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
+        processAllMessages();
+
+        assertTrue(result);
+        verify(mIImsConfig, times(1)).removeRcsConfigCallback(eq(mCallback));
+        verify(mCallback, times(1)).onRemoved();
+    }
+
+    private void createMonitor(int subCount) {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        makeFakeActiveSubIds(subCount);
+        mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper(),
+                mRoleManager);
+        mHandler = mRcsProvisioningMonitor.getHandler();
+        try {
+            mLooper = new TestableLooper(mHandler.getLooper());
+        } catch (Exception e) {
+            logd("Unable to create looper from handler.");
+        }
+    }
+
+    private void broadcastCarrierConfigChange(int subId) {
+        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+        mExecutor.execute(() -> {
+            mReceiver.onReceive(mPhone, intent);
+        });
+    }
+
+    private void makeFakeActiveSubIds(int count) {
+        final int[] subIds = new int[count];
+        for (int i = 0; i < count; i++) {
+            subIds[i] = FAKE_SUB_ID_BASE + i;
+        }
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(subIds);
+    }
+
+    private void updateDefaultMessageApplication(String packageName) {
+        List<String> dmas = new ArrayList<>();
+        dmas.add(packageName);
+        when(mRoleManager.getRoleHolders(eq(RoleManager.ROLE_SMS))).thenReturn(dmas);
+        mExecutor.execute(() -> mRoleHolderChangedListener.onRoleHoldersChanged(
+                RoleManager.ROLE_SMS, UserHandle.ALL));
+    }
+
+    private void processAllMessages() {
+        while (!mLooper.getLooper().getQueue().isIdle()) {
+            mLooper.processAllMessages();
+        }
+    }
+
+    private static void logd(String str) {
+        Log.d(TAG, str);
+    }
+}
diff --git a/tests/src/com/android/phone/SimPhonebookProviderTest.java b/tests/src/com/android/phone/SimPhonebookProviderTest.java
new file mode 100644
index 0000000..1d48694
--- /dev/null
+++ b/tests/src/com/android/phone/SimPhonebookProviderTest.java
@@ -0,0 +1,1490 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static android.provider.SimPhonebookContract.ElementaryFiles.EF_ADN;
+import static android.provider.SimPhonebookContract.ElementaryFiles.EF_FDN;
+import static android.provider.SimPhonebookContract.ElementaryFiles.EF_SDN;
+
+import static com.android.internal.telephony.testing.CursorSubject.assertThat;
+import static com.android.internal.telephony.testing.TelephonyAssertions.assertThrows;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.ElementaryFiles;
+import android.provider.SimPhonebookContract.SimRecords;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.util.Pair;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.provider.ProviderTestRule;
+
+import com.android.internal.telephony.IIccPhoneBook;
+import com.android.internal.telephony.uicc.AdnRecord;
+import com.android.internal.telephony.uicc.IccConstants;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.truth.Correspondence;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@RunWith(AndroidJUnit4.class)
+public final class SimPhonebookProviderTest {
+
+    // Emojis aren't currently supported for the ADN record label.
+    private static final String EMOJI = new String(Character.toChars(0x1F642));
+    private static final String UNSUPPORTED_NAME = ":)=" + EMOJI + ";ni=日;hon=本;";
+    private static final String UNSUPPORTED_NAME2 = "日本" + EMOJI;
+    private static final Correspondence<AdnRecord, AdnRecord> ADN_RECORD_IS_EQUAL =
+            Correspondence.from(AdnRecord::isEqual, "isEqual");
+
+    @Rule
+    public final ProviderTestRule mProviderRule = new ProviderTestRule.Builder(
+            TestableSimPhonebookProvider.class, SimPhonebookContract.AUTHORITY).build();
+
+    private ContentResolver mResolver;
+    private FakeIccPhoneBook mIccPhoneBook;
+    private SubscriptionManager mMockSubscriptionManager;
+
+    private static List<SubscriptionInfo> createSubscriptionsWithIds(int... subscriptionIds) {
+        ImmutableList.Builder<SubscriptionInfo> builder = ImmutableList.builderWithExpectedSize(
+                subscriptionIds.length);
+        for (int i = 0; i < subscriptionIds.length; i++) {
+            builder.add(createSubscriptionInfo(i, subscriptionIds[i]));
+        }
+        return builder.build();
+    }
+
+    private static SubscriptionInfo createSubscriptionInfo(int slotIndex, int subscriptiondId) {
+        return new SubscriptionInfo(
+                subscriptiondId, "", slotIndex, null, null, 0, 0, null, 0, null, null, null, null,
+                false, null, null);
+    }
+
+    @Before
+    public void setUp() {
+        mMockSubscriptionManager = spy(
+                Objects.requireNonNull(ApplicationProvider.getApplicationContext()
+                        .getSystemService(SubscriptionManager.class)));
+        mIccPhoneBook = new FakeIccPhoneBook();
+        mResolver = mProviderRule.getResolver();
+
+        TestableSimPhonebookProvider.setup(mResolver, mMockSubscriptionManager, mIccPhoneBook);
+    }
+
+    @Test
+    public void query_entityFiles_returnsCursorWithCorrectProjection() {
+        // Empty projection
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, new String[0], null,
+                null)) {
+            assertThat(cursor).hasColumnNames();
+        }
+
+        // Single column
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, new String[]{
+                ElementaryFiles.EF_TYPE
+        }, null, null)) {
+            assertThat(cursor).hasColumnNames(ElementaryFiles.EF_TYPE);
+        }
+
+        // Duplicate column
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, new String[]{
+                ElementaryFiles.SUBSCRIPTION_ID, ElementaryFiles.SUBSCRIPTION_ID
+        }, null, null)) {
+            assertThat(cursor).hasColumnNames(ElementaryFiles.SUBSCRIPTION_ID,
+                    ElementaryFiles.SUBSCRIPTION_ID);
+        }
+
+        // Random order of all columns
+        String[] projection = Arrays.copyOf(
+                SimPhonebookProvider.ELEMENTARY_FILES_ALL_COLUMNS,
+                SimPhonebookProvider.ELEMENTARY_FILES_ALL_COLUMNS.length);
+        Collections.shuffle(Arrays.asList(projection));
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, projection, null, null)) {
+            assertThat(cursor).hasColumnNames(projection);
+        }
+    }
+
+    @Test
+    public void query_entityFiles_unrecognizedColumn_throwsIllegalArgumentException() {
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(ElementaryFiles.CONTENT_URI, new String[]{"invalid_column"}, null,
+                        null));
+    }
+
+    @Test
+    public void query_entityFiles_noSim_returnsEmptyCursor() {
+        when(mMockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
+                ImmutableList.of());
+
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, null, null, null)) {
+            assertThat(cursor).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_entityFiles_multiSim_returnsCursorWithRowForEachSimEf() {
+        setupSimsWithSubscriptionIds(2, 3, 7);
+
+        mIccPhoneBook.setRecordsSize(2, IccConstants.EF_ADN, 10, 25);
+        mIccPhoneBook.setRecordsSize(2, IccConstants.EF_FDN, 5, 20);
+        mIccPhoneBook.setRecordsSize(2, IccConstants.EF_SDN, 15, 20);
+        mIccPhoneBook.setRecordsSize(3, IccConstants.EF_ADN, 100, 30);
+        // These Will be omitted from results because zero size indicates the EF is not supported.
+        mIccPhoneBook.setRecordsSize(3, IccConstants.EF_FDN, 0, 0);
+        mIccPhoneBook.setRecordsSize(3, IccConstants.EF_SDN, 0, 0);
+        mIccPhoneBook.setRecordsSize(7, IccConstants.EF_ADN, 0, 0);
+        mIccPhoneBook.setRecordsSize(7, IccConstants.EF_FDN, 0, 0);
+        mIccPhoneBook.setRecordsSize(7, IccConstants.EF_SDN, 0, 0);
+
+        String[] projection = {
+                ElementaryFiles.SLOT_INDEX, ElementaryFiles.SUBSCRIPTION_ID,
+                ElementaryFiles.EF_TYPE, ElementaryFiles.MAX_RECORDS,
+                ElementaryFiles.NAME_MAX_LENGTH, ElementaryFiles.PHONE_NUMBER_MAX_LENGTH
+        };
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, projection, null, null)) {
+            assertThat(cursor).hasColumnNames(projection);
+
+            assertThat(cursor)
+                    .atRow(0).hasRowValues(0, 2, ElementaryFiles.EF_ADN, 10, 11, 20)
+                    .atRow(1).hasRowValues(0, 2, ElementaryFiles.EF_FDN, 5, 6, 20)
+                    .atRow(2).hasRowValues(0, 2, ElementaryFiles.EF_SDN, 15, 6, 20)
+                    .atRow(3).hasRowValues(1, 3, ElementaryFiles.EF_ADN, 100, 16, 20);
+        }
+    }
+
+    @Test
+    public void query_entityFiles_simWithZeroSizes_returnsEmptyCursor() {
+        setupSimsWithSubscriptionIds(1);
+
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 0, 0);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_FDN, 0, 0);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_SDN, 0, 0);
+
+        try (Cursor cursor = mResolver.query(ElementaryFiles.CONTENT_URI, null, null, null)) {
+            assertThat(cursor).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_adnRecords_returnsCursorWithMatchingProjection() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        Uri contentAdn = SimRecords.getContentUri(1, EF_ADN);
+
+        // Empty projection
+        try (Cursor cursor = mResolver.query(contentAdn, new String[0], null, null)) {
+            assertThat(cursor).hasColumnNames();
+        }
+
+        // Single column
+        try (Cursor cursor = mResolver.query(contentAdn, new String[] {
+                SimRecords.PHONE_NUMBER
+        }, null, null)) {
+            assertThat(cursor).hasColumnNames(SimRecords.PHONE_NUMBER);
+        }
+
+        // Duplicate column
+        try (Cursor cursor = mResolver.query(contentAdn, new String[]{
+                SimRecords.PHONE_NUMBER, SimRecords.PHONE_NUMBER
+        }, null, null)) {
+            assertThat(cursor).hasColumnNames(SimRecords.PHONE_NUMBER, SimRecords.PHONE_NUMBER);
+        }
+
+        // Random order of all columns
+        String[] projection = Arrays.copyOf(
+                SimPhonebookProvider.SIM_RECORDS_ALL_COLUMNS,
+                SimPhonebookProvider.SIM_RECORDS_ALL_COLUMNS.length);
+        Collections.shuffle(Arrays.asList(projection));
+        try (Cursor cursor = mResolver.query(contentAdn, projection, null, null)) {
+            assertThat(cursor).hasColumnNames(projection);
+        }
+    }
+
+    @Test
+    public void query_adnRecords_noRecords_returnsEmptyCursor() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        try (Cursor cursor = mResolver.query(SimRecords.getContentUri(1, EF_ADN), null, null,
+                null)) {
+            assertThat(cursor).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_simRecords_nullRecordList_returnsEmptyCursor() throws Exception {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        // Use a mock so that a null list can be returned
+        IIccPhoneBook mockIccPhoneBook = mock(
+                IIccPhoneBook.class, AdditionalAnswers.delegatesTo(mIccPhoneBook));
+        when(mockIccPhoneBook.getAdnRecordsInEfForSubscriber(anyInt(), anyInt())).thenReturn(null);
+        TestableSimPhonebookProvider.setup(mResolver, mMockSubscriptionManager, mockIccPhoneBook);
+
+        try (Cursor adnCursor = mResolver.query(SimRecords.getContentUri(1, EF_ADN), null, null,
+                null);
+             Cursor fdnCursor = mResolver.query(SimRecords.getContentUri(1, EF_FDN), null, null,
+                     null);
+             Cursor sdnCursor = mResolver.query(SimRecords.getContentUri(1, EF_SDN), null, null,
+                     null)
+        ) {
+            assertThat(adnCursor).hasCount(0);
+            assertThat(fdnCursor).hasCount(0);
+            assertThat(sdnCursor).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_simRecords_singleSim_returnsDataForCorrectEf() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Person Adn1", "8005550101");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Person Adn2", "8005550102");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_FDN, "Person Fdn", "8005550103");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_SDN, "Person Sdn", "8005550104");
+        mIccPhoneBook.setDefaultSubscriptionId(1);
+
+        String[] projection = {
+                SimRecords.SUBSCRIPTION_ID,
+                SimRecords.ELEMENTARY_FILE_TYPE,
+                SimRecords.RECORD_NUMBER,
+                SimRecords.NAME,
+                SimRecords.PHONE_NUMBER
+        };
+        try (Cursor adnCursor = mResolver.query(SimRecords.getContentUri(1, EF_ADN),
+                projection, null, null);
+             Cursor fdnCursor = mResolver.query(SimRecords.getContentUri(1, EF_FDN),
+                     projection, null, null);
+             Cursor sdnCursor = mResolver.query(SimRecords.getContentUri(1, EF_SDN),
+                     projection, null, null)
+        ) {
+
+            assertThat(adnCursor)
+                    .atRow(0).hasRowValues(1, ElementaryFiles.EF_ADN, 1, "Person Adn1",
+                    "8005550101")
+                    .atRow(1).hasRowValues(1, ElementaryFiles.EF_ADN, 2, "Person Adn2",
+                    "8005550102");
+            assertThat(fdnCursor)
+                    .atRow(0).hasRowValues(1, ElementaryFiles.EF_FDN, 1, "Person Fdn",
+                    "8005550103");
+            assertThat(sdnCursor)
+                    .atRow(0).hasRowValues(1, ElementaryFiles.EF_SDN, 1, "Person Sdn",
+                    "8005550104");
+        }
+    }
+
+    @Test
+    public void query_adnRecords_returnsAdnData() {
+        setupSimsWithSubscriptionIds(1, 2, 4);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Person Sim1", "8005550101");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_FDN, "Omitted Sim1", "8005550199");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_ADN, "Person Sim2a", "8005550103");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_ADN, "Person Sim2b", "8005550104");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_ADN, "Person Sim2c", "8005550105");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_SDN, "Omitted Sim2", "8005550198");
+        mIccPhoneBook.addRecord(4, IccConstants.EF_ADN, "Person Sim4", "8005550106");
+        mIccPhoneBook.setDefaultSubscriptionId(1);
+
+        String[] projection = {
+                SimRecords.SUBSCRIPTION_ID,
+                SimRecords.ELEMENTARY_FILE_TYPE,
+                SimRecords.RECORD_NUMBER,
+                SimRecords.NAME,
+                SimRecords.PHONE_NUMBER
+        };
+        try (Cursor cursorSim1 = mResolver.query(SimRecords.getContentUri(1, EF_ADN),
+                projection, null, null);
+             Cursor cursorSim2 = mResolver.query(SimRecords.getContentUri(2, EF_ADN),
+                     projection, null, null);
+             Cursor cursorSim4 = mResolver.query(SimRecords.getContentUri(4, EF_ADN),
+                     projection, null, null)
+        ) {
+
+            assertThat(cursorSim1).hasData(new Object[][]{
+                    {1, ElementaryFiles.EF_ADN, 1, "Person Sim1", "8005550101"},
+            });
+            assertThat(cursorSim2).hasData(new Object[][]{
+                    {2, ElementaryFiles.EF_ADN, 1, "Person Sim2a", "8005550103"},
+                    {2, ElementaryFiles.EF_ADN, 2, "Person Sim2b", "8005550104"},
+                    {2, ElementaryFiles.EF_ADN, 3, "Person Sim2c", "8005550105"},
+            });
+            assertThat(cursorSim4).hasData(new Object[][]{
+                    {4, ElementaryFiles.EF_ADN, 1, "Person Sim4", "8005550106"},
+            });
+        }
+    }
+
+    @Test
+    public void query_fdnRecords_returnsFdnData() {
+        setupSimsWithSubscriptionIds(1, 2, 4);
+        mIccPhoneBook.makeAllEfsSupported(1, 2, 4);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Person Sim1", "8005550101");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_ADN, "Person Sim2a", "8005550103");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_FDN, "Person Sim2b", "8005550104");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_FDN, "Person Sim2c", "8005550105");
+        mIccPhoneBook.addRecord(4, IccConstants.EF_SDN, "Person Sim4", "8005550106");
+        mIccPhoneBook.setDefaultSubscriptionId(1);
+
+        String[] projection = {
+                SimRecords.SUBSCRIPTION_ID,
+                SimRecords.ELEMENTARY_FILE_TYPE,
+                SimRecords.RECORD_NUMBER,
+                SimRecords.NAME,
+                SimRecords.PHONE_NUMBER
+        };
+        try (Cursor cursorSim1Fdn = mResolver.query(SimRecords.getContentUri(1, EF_FDN),
+                projection, null, null);
+             Cursor cursorSim2Fdn = mResolver.query(SimRecords.getContentUri(2, EF_FDN),
+                     projection, null, null);
+             Cursor cursorSim4Fdn = mResolver.query(SimRecords.getContentUri(4, EF_FDN),
+                     projection, null, null)
+        ) {
+
+            assertThat(cursorSim1Fdn).hasCount(0);
+            assertThat(cursorSim2Fdn).hasData(new Object[][]{
+                    {2, ElementaryFiles.EF_FDN, 1, "Person Sim2b", "8005550104"},
+                    {2, ElementaryFiles.EF_FDN, 2, "Person Sim2c", "8005550105"},
+            });
+            assertThat(cursorSim4Fdn).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_sdnRecords_returnsSdnData() {
+        setupSimsWithSubscriptionIds(1, 2, 4);
+        mIccPhoneBook.makeAllEfsSupported(1, 2, 4);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Person Adn1", "8005550101");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_FDN, "Person Fdn1", "8005550102");
+        mIccPhoneBook.addRecord(1, IccConstants.EF_SDN, "Person Sdn1", "8005550103");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_ADN, "Person Adn2a", "8005550104");
+        mIccPhoneBook.addRecord(2, IccConstants.EF_FDN, "Person Fdn2b", "8005550105");
+        mIccPhoneBook.addRecord(4, IccConstants.EF_SDN, "Person Sdn4a", "8005550106");
+        mIccPhoneBook.addRecord(4, IccConstants.EF_SDN, "Person Sdn4b", "8005550107");
+        mIccPhoneBook.setDefaultSubscriptionId(1);
+
+        String[] projection = {
+                SimRecords.SUBSCRIPTION_ID,
+                SimRecords.ELEMENTARY_FILE_TYPE,
+                SimRecords.RECORD_NUMBER,
+                SimRecords.NAME,
+                SimRecords.PHONE_NUMBER
+        };
+        try (Cursor cursorSim1Sdn = mResolver.query(SimRecords.getContentUri(1, EF_SDN),
+                projection, null, null);
+             Cursor cursorSim2Sdn = mResolver.query(SimRecords.getContentUri(2, EF_SDN),
+                     projection, null, null);
+             Cursor cursorSim4Sdn = mResolver.query(SimRecords.getContentUri(4, EF_SDN),
+                     projection, null, null)
+        ) {
+
+            assertThat(cursorSim1Sdn)
+                    .atRow(0).hasRowValues(1, ElementaryFiles.EF_SDN, 1, "Person Sdn1",
+                    "8005550103");
+            assertThat(cursorSim2Sdn).hasCount(0);
+            assertThat(cursorSim4Sdn)
+                    .atRow(0).hasRowValues(4, ElementaryFiles.EF_SDN, 1, "Person Sdn4a",
+                    "8005550106")
+                    .atRow(1).hasRowValues(4, ElementaryFiles.EF_SDN, 2, "Person Sdn4b",
+                    "8005550107");
+        }
+    }
+
+    @Test
+    public void query_adnRecords_nonExistentSim_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.query(SimRecords.getContentUri(123, EF_ADN), null, null, null));
+        assertThat(e).hasMessageThat().isEqualTo("No active SIM with subscription ID 123");
+    }
+
+    @Test
+    public void insert_nonExistentSim_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "123");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(123, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo("No active SIM with subscription ID 123");
+    }
+
+    @Test
+    public void update_nonExistentSim_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "123");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.update(SimRecords.getItemUri(123, EF_ADN, 1), values, null));
+        assertThat(e).hasMessageThat().isEqualTo("No active SIM with subscription ID 123");
+    }
+
+    @Test
+    public void delete_nonExistentSim_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.delete(SimRecords.getItemUri(123, EF_ADN, 1), null));
+        assertThat(e).hasMessageThat().isEqualTo("No active SIM with subscription ID 123");
+    }
+
+    @Test
+    public void query_adnRecords_zeroSizeEf_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 0, 0);
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.query(SimRecords.getContentUri(1, EF_ADN), null, null, null));
+        assertThat(e).hasMessageThat().isEqualTo(
+                "adn is not supported for SIM with subscription ID 1");
+    }
+
+    @Test
+    public void query_itemUri_returnsCorrectRow() {
+        setupSimsWithSubscriptionIds(1, 2);
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_ADN, 1, "Name@Adn1[1]", "8005550101"));
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_ADN, 2, "Name@Adn1[2]", "8005550102"));
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_ADN, 3, "Name@Adn1[3]", "8005550103"));
+        mIccPhoneBook.addRecord(2,
+                new AdnRecord(IccConstants.EF_ADN, 3, "Name@Adn2[3]", "8005550104"));
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_FDN, 1, "Name@Fdn1[1]", "8005550105"));
+        mIccPhoneBook.addRecord(2,
+                new AdnRecord(IccConstants.EF_SDN, 1, "Name@Sdn2[1]", "8005550106"));
+
+        String[] projection = {
+                SimRecords.SUBSCRIPTION_ID, SimRecords.ELEMENTARY_FILE_TYPE,
+                SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER
+        };
+        try (Cursor item1 = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
+                projection, null, null);
+             Cursor item2 = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 3),
+                     projection, null, null);
+             Cursor item3 = mResolver.query(SimRecords.getItemUri(2, ElementaryFiles.EF_ADN, 3),
+                     projection, null, null);
+             Cursor item4 = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 1),
+                     projection, null, null);
+             Cursor item5 = mResolver.query(SimRecords.getItemUri(2, ElementaryFiles.EF_SDN, 1),
+                     projection, null, null)
+        ) {
+            assertThat(item1).hasSingleRow(1, ElementaryFiles.EF_ADN, 1, "Name@Adn1[1]",
+                    "8005550101");
+            assertThat(item2).hasSingleRow(1, ElementaryFiles.EF_ADN, 3, "Name@Adn1[3]",
+                    "8005550103");
+            assertThat(item3).hasSingleRow(2, ElementaryFiles.EF_ADN, 3, "Name@Adn2[3]",
+                    "8005550104");
+            assertThat(item4).hasSingleRow(1, ElementaryFiles.EF_FDN, 1, "Name@Fdn1[1]",
+                    "8005550105");
+            assertThat(item5).hasSingleRow(2, ElementaryFiles.EF_SDN, 1, "Name@Sdn2[1]",
+                    "8005550106");
+        }
+    }
+
+    @Test
+    public void query_itemUriEmptyRecord_returnsEmptyCursor() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 30);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_FDN, 1, 30);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_SDN, 1, 30);
+
+        try (Cursor adnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
+                null, null, null);
+             Cursor fdnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 1),
+                     null, null, null);
+             Cursor sdnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 1),
+                     null, null, null)
+        ) {
+            assertThat(adnItem).hasCount(0);
+            assertThat(fdnItem).hasCount(0);
+            assertThat(sdnItem).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_itemUriIndexExceedsMax_returnsEmptyCursor() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 30);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_FDN, 1, 30);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_SDN, 1, 30);
+
+        try (Cursor adnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2),
+                null, null, null);
+             Cursor fdnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 2),
+                     null, null, null);
+             Cursor sdnItem = mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 2),
+                     null, null, null)
+        ) {
+            assertThat(adnItem).hasCount(0);
+            assertThat(fdnItem).hasCount(0);
+            assertThat(sdnItem).hasCount(0);
+        }
+    }
+
+    @Test
+    public void query_invalidItemIndex_throwsIllegalArgumentException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, -1),
+                        null, null, null));
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, -1),
+                        null, null, null));
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, -1),
+                        null, null, null));
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 0),
+                        null, null, null));
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 0),
+                        null, null, null));
+        assertThrows(IllegalArgumentException.class, () ->
+                mResolver.query(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 0),
+                        null, null, null));
+    }
+
+    @Test
+    public void insert_adnRecord_addsAdnRecordAndReturnsUriForNewRecord() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "First Last");
+        values.put(SimRecords.PHONE_NUMBER, "8005550101");
+
+        Uri uri = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        List<AdnRecord> records = mIccPhoneBook.getAdnRecordsInEfForSubscriber(
+                1, IccConstants.EF_ADN).stream()
+                .filter(((Predicate<AdnRecord>) AdnRecord::isEmpty).negate())
+                .collect(Collectors.toList());
+
+        assertThat(records)
+                .comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsExactly(new AdnRecord(IccConstants.EF_ADN, 1, "First Last", "8005550101"));
+
+        assertThat(uri).isEqualTo(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1));
+    }
+
+    @Test
+    public void insert_adnRecordWithExistingRecords_returnsUriWithCorrectIndex() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setDefaultSubscriptionId(1);
+        mIccPhoneBook.addRecord(new AdnRecord(IccConstants.EF_ADN, 2, "Existing1", "8005550101"));
+        mIccPhoneBook.addRecord(new AdnRecord(IccConstants.EF_ADN, 3, "Existing2", "8005550102"));
+        mIccPhoneBook.addRecord(new AdnRecord(IccConstants.EF_ADN, 5, "Existing3", "8005550103"));
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "New1");
+        values.put(SimRecords.PHONE_NUMBER, "8005550104");
+
+        Uri insert1 = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+        values.put(SimRecords.NAME, "New2");
+        values.put(SimRecords.PHONE_NUMBER, "8005550105");
+        Uri insert2 = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+        values.put(SimRecords.NAME, "New3");
+        values.put(SimRecords.PHONE_NUMBER, "8005550106");
+        Uri insert3 = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        assertThat(
+                mIccPhoneBook.getAdnRecordsInEfForSubscriber(1, IccConstants.EF_ADN).subList(0, 6))
+                .comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsExactly(
+                        new AdnRecord(IccConstants.EF_ADN, 1, "New1", "8005550104"),
+                        new AdnRecord(IccConstants.EF_ADN, 2, "Existing1", "8005550101"),
+                        new AdnRecord(IccConstants.EF_ADN, 3, "Existing2", "8005550102"),
+                        new AdnRecord(IccConstants.EF_ADN, 4, "New2", "8005550105"),
+                        new AdnRecord(IccConstants.EF_ADN, 5, "Existing3", "8005550103"),
+                        new AdnRecord(IccConstants.EF_ADN, 6, "New3", "8005550106"));
+        assertThat(insert1).isEqualTo(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1));
+        assertThat(insert2).isEqualTo(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 4));
+        assertThat(insert3).isEqualTo(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 6));
+    }
+
+    @Test
+    public void insert_efFull_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 30);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Existing", "8005550101");
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "New");
+        values.put(SimRecords.PHONE_NUMBER, "8005550102");
+
+        Uri uri = SimRecords.getContentUri(1, EF_ADN);
+        IllegalStateException e = assertThrows(IllegalStateException.class,
+                () -> mResolver.insert(uri, values));
+        assertThat(e).hasMessageThat().isEqualTo(
+                uri + " is full. Please delete records to add new ones.");
+    }
+
+    @Test
+    public void insert_nullValues_returnsNull() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        Uri result = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), null);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void update_nullValues_returnsZero() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        mIccPhoneBook.addAdnRecord(1, "Name", "5550101");
+
+        int result = mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1), null,
+                null);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void insert_emptyValues_returnsNull() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        Uri result = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), new ContentValues());
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void insert_nameOmitted_createsRecordWithJustPhoneNumber() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        // No name
+        values.put(SimRecords.PHONE_NUMBER, "18005550101");
+
+        mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        // Null name
+        values.putNull(SimRecords.NAME);
+        values.put(SimRecords.PHONE_NUMBER, "18005550102");
+        mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        // Empty name
+        values.put(SimRecords.NAME, "");
+        values.put(SimRecords.PHONE_NUMBER, "18005550103");
+        mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        assertThat(mIccPhoneBook.getAllValidRecords())
+                .comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsExactly(
+                        new AdnRecord(IccConstants.EF_ADN, 1, "", "18005550101"),
+                        new AdnRecord(IccConstants.EF_ADN, 2, "", "18005550102"),
+                        new AdnRecord(IccConstants.EF_ADN, 3, "", "18005550103"));
+    }
+
+    @Test
+    public void insert_phoneNumberOmitted_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo(SimRecords.PHONE_NUMBER + " is required.");
+    }
+
+    @Test
+    public void insert_nameTooLong_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
+
+        ContentValues values = new ContentValues();
+        // Name is limited to 11 characters
+        values.put(SimRecords.NAME, "1234567890ab");
+        values.put(SimRecords.PHONE_NUMBER, "8005550102");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+
+        assertThat(e).hasMessageThat().isEqualTo(SimRecords.NAME + " is too long.");
+    }
+
+    @Test
+    public void insert_phoneNumberTooLong_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        // 21 digits is longer than max of 20
+        values.put(SimRecords.PHONE_NUMBER, "123456789012345678901");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+
+        assertThat(e).hasMessageThat().isEqualTo(SimRecords.PHONE_NUMBER + " is too long.");
+    }
+
+    @Test
+    public void insert_illegalCharacters_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 32);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "1800J550A0B");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo(
+                SimRecords.PHONE_NUMBER + " contains unsupported characters.");
+
+        values.put(SimRecords.NAME, UNSUPPORTED_NAME);
+        values.put(SimRecords.PHONE_NUMBER, "18005550101");
+
+        e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo(
+                SimRecords.NAME + " contains unsupported characters.");
+
+        values.put(SimRecords.NAME, UNSUPPORTED_NAME2);
+        values.put(SimRecords.PHONE_NUMBER, "18005550101");
+
+        e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo(
+                SimRecords.NAME + " contains unsupported characters.");
+
+        // The inserts didn't actually add any data.
+        assertThat(mIccPhoneBook.getAllValidRecords()).isEmpty();
+    }
+
+    @Test
+    public void insert_unsupportedColumn_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "18005550101");
+        values.put(SimRecords.RECORD_NUMBER, 8);
+        values.put("extra_phone2", "18005550102");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+        assertThat(e).hasMessageThat().isEqualTo("Unsupported columns: "
+                + SimRecords.RECORD_NUMBER + ",extra_phone2");
+    }
+
+    @Test
+    public void update_existingRecord_updatesRecord() {
+        setupSimsWithSubscriptionIds(1, 2);
+        AdnRecord[] unchanged = new AdnRecord[]{
+                new AdnRecord(IccConstants.EF_ADN, 3, "Other1", "8005550102"),
+                new AdnRecord(IccConstants.EF_ADN, 2, "Other2", "8005550103"),
+                new AdnRecord(IccConstants.EF_FDN, 2, "Other3", "8005550104")
+        };
+        mIccPhoneBook.addRecord(1, unchanged[0]);
+        mIccPhoneBook.addRecord(2, unchanged[1]);
+        mIccPhoneBook.addRecord(2, unchanged[2]);
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_ADN, 2, "Initial Name", "8005550101"));
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Updated Name");
+        values.put(SimRecords.PHONE_NUMBER, "8005550105");
+
+        int result = mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2), values,
+                null);
+
+        assertThat(result).isEqualTo(1);
+
+        List<AdnRecord> finalRecords = mIccPhoneBook.getAllValidRecords();
+
+        assertThat(finalRecords).comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsAtLeastElementsIn(unchanged);
+        assertThat(finalRecords).comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .doesNotContain(
+                        new AdnRecord(IccConstants.EF_ADN, 2, "Initial Name", "80005550101"));
+        assertThat(finalRecords).comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .contains(new AdnRecord(IccConstants.EF_ADN, 2, "Updated Name", "8005550105"));
+    }
+
+    @Test
+    public void update_emptyRecord_updatesRecord() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "name");
+        values.put(SimRecords.PHONE_NUMBER, "18005550101");
+        // No record actually exists with record number 10 but we allow clients to update it
+        // as a way to set the information at a specific record number.
+        int result = mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 10),
+                values, null);
+
+        assertThat(result).isEqualTo(1);
+        List<AdnRecord> finalRecords = mIccPhoneBook.getAllValidRecords();
+        assertThat(finalRecords).comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsExactly(new AdnRecord(IccConstants.EF_ADN, 10, "name", "18005550101"));
+    }
+
+    @Test
+    public void delete_existingRecord_deletesRecord() {
+        setupSimsWithSubscriptionIds(1, 2);
+        AdnRecord[] unchanged = new AdnRecord[]{
+                new AdnRecord(IccConstants.EF_ADN, 3, "Other1", "8005550102"),
+                new AdnRecord(IccConstants.EF_ADN, 2, "Other2", "8005550103"),
+                new AdnRecord(IccConstants.EF_FDN, 2, "Other3", "8005550104")
+        };
+        mIccPhoneBook.addRecord(1,
+                new AdnRecord(IccConstants.EF_ADN, 2, "Initial Name", "8005550101"));
+        mIccPhoneBook.addRecord(1, unchanged[0]);
+        mIccPhoneBook.addRecord(2, unchanged[1]);
+        mIccPhoneBook.addRecord(2, unchanged[2]);
+
+        int result = mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2), null);
+
+        assertThat(result).isEqualTo(1);
+
+        assertThat(mIccPhoneBook.getAllValidRecords()).comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+                .containsExactlyElementsIn(unchanged);
+    }
+
+    @Test
+    public void update_indexExceedingMax_returnsZero() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 30);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "name");
+        values.put(SimRecords.PHONE_NUMBER, "18005551010");
+        int result = mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2),
+                values, null);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void update_indexOverflow_throwsIllegalArgumentException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "name");
+        values.put(SimRecords.PHONE_NUMBER, "18005551010");
+        assertThrows(IllegalArgumentException.class, () -> mResolver.update(
+                SimRecords.getContentUri(1, EF_ADN).buildUpon().appendPath(
+                        String.valueOf((Long.MAX_VALUE))).build(),
+                values, null));
+    }
+
+    @Test
+    public void delete_emptyRecord_returnsZero() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        int result = mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2), null);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void delete_indexExceedingMax_returnsZero() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 30);
+
+        int result = mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 2), null);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void delete_indexOverflow_throwsIllegalArgumentException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        assertThrows(IllegalArgumentException.class, () -> mResolver.delete(
+                SimRecords.getContentUri(1, EF_ADN).buildUpon().appendPath(
+                        String.valueOf((Long.MAX_VALUE))).build(),
+                null));
+    }
+
+    @Test
+    public void update_nameOrNumberTooLong_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Initial", "8005550101");
+
+        ContentValues values = new ContentValues();
+        // Name is limited to 11 characters
+        values.put(SimRecords.NAME, "1234567890ab");
+        values.put(SimRecords.PHONE_NUMBER, "8005550102");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.update(SimRecords.getItemUri(
+                        1, ElementaryFiles.EF_ADN, 1), values, null));
+        assertThat(e).hasMessageThat().isEqualTo(SimRecords.NAME + " is too long.");
+
+        values.put(SimRecords.NAME, "abc");
+        values.put(SimRecords.PHONE_NUMBER, "123456789012345678901");
+
+        e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
+                        values,
+                        null));
+        assertThat(e).hasMessageThat().isEqualTo(SimRecords.PHONE_NUMBER + " is too long.");
+        // The updates didn't actually change the data
+        assertThat(mIccPhoneBook.getAllValidRecords())
+                .comparingElementsUsing(Correspondence.from(AdnRecord::isEqual, "isEqual"))
+                .containsExactly(new AdnRecord(IccConstants.EF_ADN, 1, "Initial", "8005550101"));
+    }
+
+    @Test
+    public void update_nameOrNumberWithInvalidCharacters_throwsCorrectException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 32);
+        mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Initial", "8005550101");
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "(800)555-0190 x7777");
+
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
+                        values,
+                        null));
+        assertThat(e).hasMessageThat().isEqualTo(
+                SimRecords.PHONE_NUMBER + " contains unsupported characters.");
+
+        // Unicode fffe is a unicode non-character
+        values.put(SimRecords.NAME, UNSUPPORTED_NAME);
+        values.put(SimRecords.PHONE_NUMBER, "18005550102");
+
+        e = assertThrows(IllegalArgumentException.class,
+                () -> mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
+                        values,
+                        null));
+        assertThat(e).hasMessageThat().isEqualTo(
+                SimRecords.NAME + " contains unsupported characters.");
+
+        // The updates didn't actually change the data.
+        assertThat(mIccPhoneBook.getAllValidRecords())
+                .comparingElementsUsing(Correspondence.from(AdnRecord::isEqual, "isEqual"))
+                .containsExactly(new AdnRecord(IccConstants.EF_ADN, 1, "Initial", "8005550101"));
+    }
+
+    @Test
+    public void insert_nonAdnDirUris_throwsUnsupportedOperationException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "8005550101");
+
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.insert(ElementaryFiles.CONTENT_URI, values));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_FDN), values));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.insert(SimRecords.getContentUri(1, EF_SDN), values));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.insert(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 1), values));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.insert(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 1), values));
+    }
+
+    @Test
+    public void update_nonAdnDirUris_throwsUnsupportedOperationException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "8005550101");
+
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.update(ElementaryFiles.CONTENT_URI, values, null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.update(SimRecords.getContentUri(1, EF_FDN), values, null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.update(SimRecords.getContentUri(1, EF_SDN), values, null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.update(SimRecords.getContentUri(1, EF_SDN), values, null));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 1), values,
+                        null));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 1), values,
+                        null));
+    }
+
+    @Test
+    public void delete_nonAdnDirUris_throwsUnsupportedOperationException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Name");
+        values.put(SimRecords.PHONE_NUMBER, "8005550101");
+
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.delete(ElementaryFiles.CONTENT_URI, null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.delete(SimRecords.getContentUri(1, EF_FDN), null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.delete(SimRecords.getContentUri(1, EF_SDN), null));
+        assertThrows(UnsupportedOperationException.class,
+                () -> mResolver.delete(SimRecords.getContentUri(1, EF_SDN), null));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_FDN, 1), null));
+        assertThrows(UnsupportedOperationException.class, () ->
+                mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_SDN, 1), null));
+    }
+
+    @Test
+    public void subscriptionsChange_callsNotifyChange() {
+        // Clear invocations that happened in setUp
+        Mockito.reset(mMockSubscriptionManager);
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        SimPhonebookProvider.ContentNotifier mockNotifier = mock(
+                SimPhonebookProvider.ContentNotifier.class);
+        ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> listenerCaptor =
+                ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
+
+        TestableSimPhonebookProvider.setup(
+                mResolver, mMockSubscriptionManager, mIccPhoneBook, mockNotifier);
+        verify(mMockSubscriptionManager).addOnSubscriptionsChangedListener(
+                any(), listenerCaptor.capture());
+        listenerCaptor.getValue().onSubscriptionsChanged();
+        setupSimsWithSubscriptionIds(1, 2);
+        listenerCaptor.getValue().onSubscriptionsChanged();
+        listenerCaptor.getValue().onSubscriptionsChanged();
+
+        verify(mockNotifier, times(2)).notifyChange(eq(SimPhonebookContract.AUTHORITY_URI));
+    }
+
+    @Test
+    public void insert_callsNotifyChange() {
+        // Clear invocations that happened in setUp
+        Mockito.reset(mMockSubscriptionManager);
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        SimPhonebookProvider.ContentNotifier mockNotifier = mock(
+                SimPhonebookProvider.ContentNotifier.class);
+
+        TestableSimPhonebookProvider.setup(
+                mResolver, mMockSubscriptionManager, mIccPhoneBook, mockNotifier);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "name");
+        values.put(SimRecords.PHONE_NUMBER, "5550101");
+        mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+        verify(mockNotifier).notifyChange(eq(SimPhonebookContract.AUTHORITY_URI));
+    }
+
+    @Test
+    public void update_callsNotifyChange() {
+        // Clear invocations that happened in setUp
+        Mockito.reset(mMockSubscriptionManager);
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.addAdnRecord(1, "Initial", "5550101");
+        SimPhonebookProvider.ContentNotifier mockNotifier = mock(
+                SimPhonebookProvider.ContentNotifier.class);
+
+        TestableSimPhonebookProvider.setup(
+                mResolver, mMockSubscriptionManager, mIccPhoneBook, mockNotifier);
+
+        ContentValues values = new ContentValues();
+        values.put(SimRecords.NAME, "Updated");
+        values.put(SimRecords.PHONE_NUMBER, "5550102");
+        mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1), values, null);
+
+        verify(mockNotifier).notifyChange(eq(SimPhonebookContract.AUTHORITY_URI));
+    }
+
+    @Test
+    public void delete_callsNotifyChange() {
+        // Clear invocations that happened in setUp
+        Mockito.reset(mMockSubscriptionManager);
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.addAdnRecord(1, "Initial", "5550101");
+        SimPhonebookProvider.ContentNotifier mockNotifier = mock(
+                SimPhonebookProvider.ContentNotifier.class);
+
+        TestableSimPhonebookProvider.setup(
+                mResolver, mMockSubscriptionManager, mIccPhoneBook, mockNotifier);
+
+        mResolver.delete(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1), null);
+
+        verify(mockNotifier).notifyChange(eq(SimPhonebookContract.AUTHORITY_URI));
+    }
+
+    @Test
+    public void validateName_validName_returnsValueIsCorrect() {
+        setupSimsWithSubscriptionIds(1);
+        String validName = "First Last";
+        // See AdnRecord#FOOTER_SIZE_BYTES
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, validName.length() + 14);
+        SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
+                EF_ADN, validName);
+
+        assertThat(validationResult.isValid()).isTrue();
+        assertThat(validationResult.getName()).isEqualTo(validName);
+        assertThat(validationResult.getSanitizedName()).isEqualTo(validName);
+        assertThat(validationResult.getEncodedLength()).isEqualTo(validName.length());
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(validName.length());
+
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
+        validationResult = SimRecords.validateName(mResolver, 1, EF_ADN, validName);
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(40 - 14);
+    }
+
+    @Test
+    public void validateName_nameTooLong_returnsValueIsCorrect() {
+        setupSimsWithSubscriptionIds(1);
+        String tooLongName = "First Last";
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, tooLongName.length() + 14 - 1);
+        SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
+                EF_ADN, tooLongName);
+
+        assertThat(validationResult.isValid()).isFalse();
+        assertThat(validationResult.getName()).isEqualTo(tooLongName);
+        assertThat(validationResult.getSanitizedName()).isEqualTo(tooLongName);
+        assertThat(validationResult.getEncodedLength()).isEqualTo(tooLongName.length());
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(tooLongName.length() - 1);
+    }
+
+    @Test
+    public void validateName_nameWithUnsupportedCharacters_returnsValueIsCorrect() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
+        SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
+                EF_ADN, UNSUPPORTED_NAME);
+
+        assertThat(validationResult.isValid()).isFalse();
+        assertThat(validationResult.getName()).isEqualTo(UNSUPPORTED_NAME);
+        assertThat(validationResult.getSanitizedName()).isEqualTo(":)=  ;ni= ;hon= ;");
+        assertThat(validationResult.getEncodedLength()).isEqualTo(UNSUPPORTED_NAME.length());
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
+                AdnRecord.getMaxAlphaTagBytes(40));
+    }
+
+    @Test
+    public void validateName_emptyString_returnsValueIsCorrect() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
+        SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
+                EF_ADN, "");
+
+        assertThat(validationResult.isValid()).isTrue();
+        assertThat(validationResult.getName()).isEqualTo("");
+        assertThat(validationResult.getSanitizedName()).isEqualTo("");
+        assertThat(validationResult.getEncodedLength()).isEqualTo(0);
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
+                AdnRecord.getMaxAlphaTagBytes(40));
+
+        // Null is equivalent to empty
+        validationResult = SimRecords.validateName(mResolver, 1, EF_ADN, null);
+        assertThat(validationResult.getName()).isEqualTo("");
+        assertThat(validationResult.getSanitizedName()).isEqualTo("");
+        assertThat(validationResult.getEncodedLength()).isEqualTo(0);
+        assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
+                AdnRecord.getMaxAlphaTagBytes(40));
+    }
+
+    private void setupSimsWithSubscriptionIds(int... subscriptionIds) {
+        when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(subscriptionIds);
+        when(mMockSubscriptionManager.getActiveSubscriptionInfoCount())
+                .thenReturn(subscriptionIds.length);
+        List<SubscriptionInfo> subscriptions = createSubscriptionsWithIds(subscriptionIds);
+        when(mMockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subscriptions);
+        for (SubscriptionInfo info : subscriptions) {
+            when(mMockSubscriptionManager.getActiveSubscriptionInfo(info.getSubscriptionId()))
+                    .thenReturn(info);
+        }
+    }
+
+    public static class FakeIccPhoneBook extends IIccPhoneBook.Default {
+
+        private static final int DEFAULT_RECORD_SIZE = 30;
+        private static final int DEFAULT_RECORDS_COUNT = 100;
+
+        // The key for both maps is the (subscription ID, efid)
+        private Map<Pair<Integer, Integer>, AdnRecord[]> mRecords = new HashMap<>();
+        // The value is the single record size
+        private Map<Pair<Integer, Integer>, Integer> mRecordSizes = new HashMap<>();
+
+        private int mDefaultSubscriptionId = 101;
+
+        private void addRecord(Pair<Integer, Integer> key, AdnRecord record) {
+            // Assume that if records are being added then the test wants it to be a valid
+            // elementary file so set sizes as well.
+            if (!mRecordSizes.containsKey(key)) {
+                setRecordsSize(key.first, key.second,
+                        Math.max(record.getRecId(), DEFAULT_RECORDS_COUNT), DEFAULT_RECORD_SIZE);
+            }
+            mRecords.get(key)[record.getRecId() - 1] = record;
+        }
+
+        public void addRecord(AdnRecord record) {
+            addRecord(Pair.create(mDefaultSubscriptionId, record.getEfid()), record);
+        }
+
+        public void addRecord(int subscriptionId, AdnRecord record) {
+            addRecord(Pair.create(subscriptionId, record.getEfid()), record);
+        }
+
+        public void addRecord(int subscriptionId, int efId, String name, String phoneNumber) {
+            Pair<Integer, Integer> key = Pair.create(subscriptionId, efId);
+            AdnRecord[] records = mRecords.computeIfAbsent(key, unused ->
+                    createEmptyRecords(efId, 100));
+            int recordIndex = -1;
+            for (int i = 0; i < records.length; i++) {
+                if (records[i].isEmpty()) {
+                    recordIndex = i;
+                    break;
+                }
+            }
+            if (recordIndex == -1) {
+                throw new IllegalStateException("");
+            }
+            addRecord(key, new AdnRecord(efId, recordIndex + 1, name, phoneNumber));
+        }
+
+        public void addAdnRecord(int subscriptionId, String name, String phoneNumber) {
+            addRecord(subscriptionId, IccConstants.EF_ADN, name, phoneNumber);
+        }
+
+        public void addAdnRecord(String name, String phoneNumber) {
+            addRecord(mDefaultSubscriptionId, IccConstants.EF_ADN, name, phoneNumber);
+        }
+
+        public List<AdnRecord> getAllValidRecords() {
+            List<AdnRecord> result = new ArrayList<>();
+            for (AdnRecord[] records : mRecords.values()) {
+                for (AdnRecord record : records) {
+                    if (!record.isEmpty()) {
+                        result.add(record);
+                    }
+                }
+            }
+            return result;
+        }
+
+        public void makeAllEfsSupported() {
+            makeAllEfsSupported(mDefaultSubscriptionId);
+        }
+
+        /**
+         * Sets up the fake to return valid records size for all elementary files for the provided
+         * subscription IDs.
+         */
+        public void makeAllEfsSupported(int... subscriptionIds) {
+            for (int subId : subscriptionIds) {
+                makeAllEfsSupported(subId);
+            }
+        }
+
+        /**
+         * Sets up the fake to return valid records size for all elementary files for the provided
+         * subscription IDs.
+         */
+        public void makeAllEfsSupported(int subscriptionId) {
+            setRecordsSize(subscriptionId, IccConstants.EF_ADN, DEFAULT_RECORDS_COUNT,
+                    DEFAULT_RECORD_SIZE);
+            setRecordsSize(subscriptionId, IccConstants.EF_FDN, DEFAULT_RECORDS_COUNT,
+                    DEFAULT_RECORD_SIZE);
+            setRecordsSize(subscriptionId, IccConstants.EF_SDN, DEFAULT_RECORDS_COUNT,
+                    DEFAULT_RECORD_SIZE);
+        }
+
+        public void setRecordsSize(int subscriptionId, int efid, int maxRecordCount,
+                int maxRecordSize) {
+            Pair<Integer, Integer> key = Pair.create(subscriptionId, efid);
+            mRecordSizes.put(key, maxRecordSize);
+            AdnRecord[] records = mRecords.computeIfAbsent(key, unused ->
+                    createEmptyRecords(efid, maxRecordCount));
+            if (records.length < maxRecordCount) {
+                throw new IllegalStateException("Records already initialized with a smaller size");
+            }
+        }
+
+        private AdnRecord[] createEmptyRecords(int efid, int count) {
+            AdnRecord[] records = new AdnRecord[count];
+            for (int i = 0; i < records.length; i++) {
+                if (records[i] == null) {
+                    records[i] = new AdnRecord(efid, i + 1, "", "");
+                }
+            }
+            return records;
+        }
+
+        public void setDefaultSubscriptionId(int defaultSubscriptionId) {
+            mDefaultSubscriptionId = defaultSubscriptionId;
+        }
+
+        public void reset() {
+            mRecords.clear();
+            mRecordSizes.clear();
+        }
+
+        @Override
+        public List<AdnRecord> getAdnRecordsInEf(int efid) {
+            return getAdnRecordsInEfForSubscriber(mDefaultSubscriptionId, efid);
+        }
+
+        @Override
+        public List<AdnRecord> getAdnRecordsInEfForSubscriber(int subId, int efid) {
+            return Arrays.asList(
+                    mRecords.getOrDefault(Pair.create(subId, efid), new AdnRecord[0]));
+        }
+
+        @Override
+        public boolean updateAdnRecordsInEfBySearch(int efid, String oldTag, String oldPhoneNumber,
+                String newTag, String newPhoneNumber, String pin2) {
+            return updateAdnRecordsInEfBySearchForSubscriber(
+                    mDefaultSubscriptionId, efid,
+                    oldTag, oldPhoneNumber, newTag, newPhoneNumber, pin2);
+        }
+
+        @Override
+        public boolean updateAdnRecordsInEfBySearchForSubscriber(int subId, int efid, String oldTag,
+                String oldPhoneNumber, String newTag, String newPhoneNumber, String pin2) {
+            if (!oldTag.isEmpty() || !oldPhoneNumber.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "updateAdnRecordsInEfBySearchForSubscriber only supports insert");
+            }
+            addRecord(subId, efid, newTag, newPhoneNumber);
+            return true;
+        }
+
+        @Override
+        public boolean updateAdnRecordsInEfByIndex(int efid, String newTag, String newPhoneNumber,
+                int index, String pin2) {
+            return updateAdnRecordsInEfByIndexForSubscriber(mDefaultSubscriptionId,
+                    efid, newTag, newPhoneNumber, index, pin2);
+        }
+
+        @Override
+        public boolean updateAdnRecordsInEfByIndexForSubscriber(int subId, int efid, String newTag,
+                String newPhoneNumber, int index, String pin2) {
+            AdnRecord[] records = mRecords.computeIfAbsent(Pair.create(subId, efid), unused ->
+                    createEmptyRecords(efid, 100));
+            records[index - 1] = new AdnRecord(efid, index, newTag, newPhoneNumber);
+            return true;
+        }
+
+        @Override
+        public int[] getAdnRecordsSize(int efid) {
+            return getAdnRecordsSizeForSubscriber(mDefaultSubscriptionId, efid);
+        }
+
+        @Override
+        public int[] getAdnRecordsSizeForSubscriber(int subId, int efid) {
+            Pair<Integer, Integer> key = Pair.create(subId, efid);
+            Integer recordSize = mRecordSizes.get(key);
+            if (recordSize == null) {
+                return new int[]{0, 0, 0};
+            }
+            int count = mRecords.get(key).length;
+            return new int[]{recordSize, recordSize * count, count};
+        }
+    }
+
+    /**
+     * Implementation of SimPhonebookProvider that allows test-doubles to be injected.
+     *
+     * <p>The ProviderTestRule doesn't seem to allow a better way to do this since it just
+     * invokes the constructor.
+     */
+    public static class TestableSimPhonebookProvider extends SimPhonebookProvider {
+
+        public static void setup(
+                ContentResolver resolver,
+                SubscriptionManager subscriptionManager,
+                IIccPhoneBook iccPhoneBook) {
+            setup(resolver, subscriptionManager, iccPhoneBook, uri -> {
+            });
+        }
+
+        public static void setup(
+                ContentResolver resolver,
+                SubscriptionManager subscriptionManager,
+                IIccPhoneBook iccPhoneBook,
+                ContentNotifier notifier) {
+            TestableSimPhonebookProvider provider =
+                    (TestableSimPhonebookProvider) Objects.requireNonNull(
+                            resolver.acquireContentProviderClient(
+                                    SimPhonebookContract.AUTHORITY))
+                            .getLocalContentProvider();
+            InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+                    provider.onCreate(subscriptionManager, () -> iccPhoneBook, notifier));
+        }
+
+        @Override
+        public boolean onCreate() {
+            // We stub super.onCreate because it initializes services which causes an
+            // IllegalArgumentException because of the context used for the test.
+            return true;
+        }
+    }
+}
diff --git a/tests/src/com/android/phone/callcomposer/CallComposerAuthTest.java b/tests/src/com/android/phone/callcomposer/CallComposerAuthTest.java
new file mode 100644
index 0000000..b503790
--- /dev/null
+++ b/tests/src/com/android/phone/callcomposer/CallComposerAuthTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.callcomposer;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.phone.callcomposer.DigestAuthUtils;
+
+import org.junit.Test;
+
+public class CallComposerAuthTest {
+    @Test
+    public void testResponseGeneration() {
+        String username = "test1";
+        String realm = "test@test.com";
+        byte[] password = "12345678".getBytes();
+        String sNonce = "aaaabbbbcccc";
+        String cNonce = "ccccbbbbaaaa";
+        String ncValue = "00000001";
+        String method = "POST";
+        String uri = "/test/test1?a=b";
+        String qop = "auth";
+
+        String response = DigestAuthUtils.computeResponse(sNonce, cNonce, qop, username,
+                realm, password, method, uri);
+        // precomputed response value from a known-good implementation
+        assertEquals("744d63d6fb11aa132dc906ec95306960", response);
+    }
+}
diff --git a/tests/src/com/android/phone/callcomposer/PictureManagerTest.java b/tests/src/com/android/phone/callcomposer/PictureManagerTest.java
new file mode 100644
index 0000000..b52b297
--- /dev/null
+++ b/tests/src/com/android/phone/callcomposer/PictureManagerTest.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 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.callcomposer;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.OutcomeReceiver;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.provider.CallLog;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.InputStream;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class PictureManagerTest {
+    private static final String FAKE_URL_BASE = "https://www.example.com";
+    private static final String FAKE_URL = "https://www.example.com/AAAAA";
+    private static final long TIMEOUT_MILLIS = 1000;
+    private static final Uri FAKE_CALLLOG_URI = Uri.parse("content://asdf");
+
+    @Mock CallComposerPictureManager.CallLogProxy mockCallLogProxy;
+    @Mock CallComposerPictureTransfer mockPictureTransfer;
+    @Mock Context context;
+    @Mock TelephonyManager telephonyManager;
+
+    private boolean originalTestMode = false;
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        originalTestMode = CallComposerPictureManager.sTestMode;
+        // Even though this is a test, we want test mode off so we can actually exercise the logic
+        // in the class.
+        CallComposerPictureManager.sTestMode = false;
+        when(context.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(telephonyManager);
+        when(context.getSystemServiceName(TelephonyManager.class))
+                .thenReturn(Context.TELEPHONY_SERVICE);
+        when(telephonyManager.createForSubscriptionId(anyInt())).thenReturn(telephonyManager);
+        PersistableBundle b = new PersistableBundle();
+        b.putString(CarrierConfigManager.KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING,
+                FAKE_URL_BASE);
+        when(telephonyManager.getCarrierConfig()).thenReturn(b);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        CallComposerPictureManager.sTestMode = originalTestMode;
+        CallComposerPictureManager.clearInstances();
+    }
+
+    @Test
+    public void testPictureUpload() throws Exception {
+        CallComposerPictureManager manager = CallComposerPictureManager.getInstance(context, 0);
+        manager.setCallLogProxy(mockCallLogProxy);
+        ImageData imageData = new ImageData(new byte[] {1,2,3,4},
+                "image/png", null);
+
+        CompletableFuture<UUID> uploadedUuidFuture = new CompletableFuture<>();
+        manager.handleUploadToServer(new CallComposerPictureTransfer.Factory() {
+            @Override
+            public CallComposerPictureTransfer create(Context context, int subscriptionId,
+                    String url, ExecutorService executorService) {
+                return mockPictureTransfer;
+            }
+        }, imageData, (pair) -> uploadedUuidFuture.complete(pair.first));
+
+        // Get the callback for later manipulation
+        ArgumentCaptor<CallComposerPictureTransfer.PictureCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CallComposerPictureTransfer.PictureCallback.class);
+        verify(mockPictureTransfer).setCallback(callbackCaptor.capture());
+
+        // Make sure the upload method is called
+        ArgumentCaptor<GbaCredentialsSupplier> credSupplierCaptor =
+                ArgumentCaptor.forClass(GbaCredentialsSupplier.class);
+        ArgumentCaptor<ImageData> imageDataCaptor =
+                ArgumentCaptor.forClass(ImageData.class);
+        verify(mockPictureTransfer).uploadPicture(imageDataCaptor.capture(),
+                credSupplierCaptor.capture());
+
+        // Make sure the id field on the image data got filled in
+        ImageData sentData = imageDataCaptor.getValue();
+        assertArrayEquals(imageData.getImageBytes(), sentData.getImageBytes());
+        assertNotNull(sentData.getId());
+        String imageId = sentData.getId();
+
+        testGbaCredLookup(credSupplierCaptor.getValue(), false);
+
+        // Trigger upload success, make sure that the internal state is consistent after the upload.
+        callbackCaptor.getValue().onUploadSuccessful(FAKE_URL);
+        UUID id = uploadedUuidFuture.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        assertEquals(imageId, id.toString());
+        assertEquals(FAKE_URL, manager.getServerUrlForImageId(id));
+
+        // Test the call log upload
+        CompletableFuture<Uri> callLogUriFuture = new CompletableFuture<>();
+        manager.storeUploadedPictureToCallLog(id, callLogUriFuture::complete);
+
+        ArgumentCaptor<OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>>
+                callLogCallbackCaptor = ArgumentCaptor.forClass(OutcomeReceiver.class);
+
+        verify(mockCallLogProxy).storeCallComposerPictureAsUser(nullable(Context.class),
+                nullable(UserHandle.class), nullable(InputStream.class), nullable(Executor.class),
+                callLogCallbackCaptor.capture());
+        callLogCallbackCaptor.getValue().onResult(FAKE_CALLLOG_URI);
+        Uri receivedUri = callLogUriFuture.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        assertEquals(FAKE_CALLLOG_URI, receivedUri);
+    }
+
+    @Test
+    public void testPictureUploadWithAuthRefresh() throws Exception {
+        CallComposerPictureManager manager = CallComposerPictureManager.getInstance(context, 0);
+        manager.setCallLogProxy(mockCallLogProxy);
+        ImageData imageData = new ImageData(new byte[] {1,2,3,4},
+                "image/png", null);
+
+        CompletableFuture<UUID> uploadedUuidFuture = new CompletableFuture<>();
+        manager.handleUploadToServer(new CallComposerPictureTransfer.Factory() {
+            @Override
+            public CallComposerPictureTransfer create(Context context, int subscriptionId,
+                    String url, ExecutorService executorService) {
+                return mockPictureTransfer;
+            }
+        }, imageData, (pair) -> uploadedUuidFuture.complete(pair.first));
+
+        // Get the callback for later manipulation
+        ArgumentCaptor<CallComposerPictureTransfer.PictureCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CallComposerPictureTransfer.PictureCallback.class);
+        verify(mockPictureTransfer).setCallback(callbackCaptor.capture());
+
+        // Make sure the upload method is called
+        verify(mockPictureTransfer).uploadPicture(nullable(ImageData.class),
+                nullable(GbaCredentialsSupplier.class));
+
+        // Simulate a auth-needed retry request
+        callbackCaptor.getValue().onRetryNeeded(true, 0);
+        waitForExecutorAction(CallComposerPictureManager.getExecutor(), TIMEOUT_MILLIS);
+
+        // Make sure upload gets called again immediately, and make sure that the new GBA creds
+        // are requested with a force-refresh.
+        ArgumentCaptor<GbaCredentialsSupplier> credSupplierCaptor =
+                ArgumentCaptor.forClass(GbaCredentialsSupplier.class);
+        verify(mockPictureTransfer, times(2)).uploadPicture(nullable(ImageData.class),
+                credSupplierCaptor.capture());
+
+        testGbaCredLookup(credSupplierCaptor.getValue(), true);
+    }
+
+    @Test
+    public void testPictureDownload() throws Exception {
+        ImageData imageData = new ImageData(new byte[] {1,2,3,4},
+                "image/png", null);
+        CallComposerPictureManager manager = CallComposerPictureManager.getInstance(context, 0);
+        manager.setCallLogProxy(mockCallLogProxy);
+
+        CompletableFuture<Uri> callLogUriFuture = new CompletableFuture<>();
+        manager.handleDownloadFromServer(new CallComposerPictureTransfer.Factory() {
+            @Override
+            public CallComposerPictureTransfer create(Context context, int subscriptionId,
+                    String url, ExecutorService executorService) {
+                return mockPictureTransfer;
+            }
+        }, FAKE_URL, (p) -> callLogUriFuture.complete(p.first));
+
+        // Get the callback for later manipulation
+        ArgumentCaptor<CallComposerPictureTransfer.PictureCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CallComposerPictureTransfer.PictureCallback.class);
+        verify(mockPictureTransfer).setCallback(callbackCaptor.capture());
+
+        // Make sure the download method is called
+        ArgumentCaptor<GbaCredentialsSupplier> credSupplierCaptor =
+                ArgumentCaptor.forClass(GbaCredentialsSupplier.class);
+        verify(mockPictureTransfer).downloadPicture(credSupplierCaptor.capture());
+
+        testGbaCredLookup(credSupplierCaptor.getValue(), false);
+
+        // Trigger download success, make sure that the call log is called into next.
+        callbackCaptor.getValue().onDownloadSuccessful(imageData);
+        ArgumentCaptor<OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>>
+                callLogCallbackCaptor = ArgumentCaptor.forClass(OutcomeReceiver.class);
+        verify(mockCallLogProxy).storeCallComposerPictureAsUser(nullable(Context.class),
+                nullable(UserHandle.class), nullable(InputStream.class), nullable(Executor.class),
+                callLogCallbackCaptor.capture());
+
+        callLogCallbackCaptor.getValue().onResult(FAKE_CALLLOG_URI);
+        Uri receivedUri = callLogUriFuture.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        assertEquals(FAKE_CALLLOG_URI, receivedUri);
+    }
+
+    @Test
+    public void testPictureDownloadWithAuthRefresh() throws Exception {
+        CallComposerPictureManager manager = CallComposerPictureManager.getInstance(context, 0);
+        manager.setCallLogProxy(mockCallLogProxy);
+
+        CompletableFuture<Uri> callLogUriFuture = new CompletableFuture<>();
+        manager.handleDownloadFromServer(new CallComposerPictureTransfer.Factory() {
+            @Override
+            public CallComposerPictureTransfer create(Context context, int subscriptionId,
+                    String url, ExecutorService executorService) {
+                return mockPictureTransfer;
+            }
+        }, FAKE_URL, (p) -> callLogUriFuture.complete(p.first));
+
+        // Get the callback for later manipulation
+        ArgumentCaptor<CallComposerPictureTransfer.PictureCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CallComposerPictureTransfer.PictureCallback.class);
+        verify(mockPictureTransfer).setCallback(callbackCaptor.capture());
+
+        // Make sure the download method is called
+        verify(mockPictureTransfer).downloadPicture(nullable(GbaCredentialsSupplier.class));
+
+        // Simulate a auth-needed retry request
+        callbackCaptor.getValue().onRetryNeeded(true, 0);
+        waitForExecutorAction(CallComposerPictureManager.getExecutor(), TIMEOUT_MILLIS);
+
+        // Make sure download gets called again immediately, and make sure that the new GBA creds
+        // are requested with a force-refresh.
+        ArgumentCaptor<GbaCredentialsSupplier> credSupplierCaptor =
+                ArgumentCaptor.forClass(GbaCredentialsSupplier.class);
+        verify(mockPictureTransfer, times(2)).downloadPicture(credSupplierCaptor.capture());
+
+        testGbaCredLookup(credSupplierCaptor.getValue(), true);
+    }
+
+
+    public void testGbaCredLookup(GbaCredentialsSupplier supplier, boolean forceExpected)
+            throws Exception {
+        String fakeRealm = "3gpp-bootstraping@naf1.example.com";
+        byte[] fakeKey = new byte[] {1, 2, 3, 4, 5};
+        String fakeTxId = "89sdfjggf";
+
+        ArgumentCaptor<TelephonyManager.BootstrapAuthenticationCallback> authCallbackCaptor =
+                ArgumentCaptor.forClass(TelephonyManager.BootstrapAuthenticationCallback.class);
+
+        CompletableFuture<GbaCredentials> credsFuture =
+                supplier.getCredentials(fakeRealm, CallComposerPictureManager.getExecutor());
+        verify(telephonyManager).bootstrapAuthenticationRequest(anyInt(), eq(Uri.parse(fakeRealm)),
+                nullable(UaSecurityProtocolIdentifier.class), eq(forceExpected),
+                nullable(Executor.class),
+                authCallbackCaptor.capture());
+        authCallbackCaptor.getValue().onKeysAvailable(fakeKey, fakeTxId);
+        GbaCredentials creds = credsFuture.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        assertEquals(fakeTxId, creds.getTransactionId());
+        assertArrayEquals(fakeKey, creds.getKey());
+
+
+        // Do it again and see if we make another request, then make sure that matches up with what
+        // we expected.
+        CompletableFuture<GbaCredentials> credsFuture1 =
+                supplier.getCredentials(fakeRealm, CallComposerPictureManager.getExecutor());
+        verify(telephonyManager, times(forceExpected ? 2 : 1))
+                .bootstrapAuthenticationRequest(anyInt(), eq(Uri.parse(fakeRealm)),
+                        nullable(UaSecurityProtocolIdentifier.class),
+                        eq(forceExpected),
+                        nullable(Executor.class),
+                        authCallbackCaptor.capture());
+        authCallbackCaptor.getValue().onKeysAvailable(fakeKey, fakeTxId);
+        GbaCredentials creds1 = credsFuture1.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        assertEquals(fakeTxId, creds1.getTransactionId());
+        assertArrayEquals(fakeKey, creds1.getKey());
+    }
+
+    private static boolean waitForExecutorAction(
+            ExecutorService executorService, long timeoutMillis) {
+        CompletableFuture<Void> f = new CompletableFuture<>();
+        executorService.execute(() -> f.complete(null));
+        try {
+            f.get(timeoutMillis, TimeUnit.MILLISECONDS);
+        } catch (TimeoutException e) {
+            return false;
+        } catch (InterruptedException | ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+        return true;
+    }
+}
diff --git a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
index edfc34f..33c8b8a 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
@@ -27,8 +27,6 @@
 import android.os.Looper;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.internal.telephony.PhoneConstants;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -112,12 +110,10 @@
     @Test
     @SmallTest
     public void testMergeMultiPartyCalls() {
-        when(mTestTelephonyConnectionA.mMockRadioConnection.getPhoneType())
-                .thenReturn(PhoneConstants.PHONE_TYPE_IMS);
-        when(mTestTelephonyConnectionB.mMockRadioConnection.getPhoneType())
-                .thenReturn(PhoneConstants.PHONE_TYPE_IMS);
-        when(mTestTelephonyConnectionA.mMockRadioConnection.isMultiparty()).thenReturn(true);
-        when(mTestTelephonyConnectionB.mMockRadioConnection.isMultiparty()).thenReturn(true);
+        mTestTelephonyConnectionA.setIsImsConnection(true);
+        mTestTelephonyConnectionB.setIsImsConnection(true);
+        when(mTestTelephonyConnectionA.mImsPhoneConnection.isMultiparty()).thenReturn(true);
+        when(mTestTelephonyConnectionB.mImsPhoneConnection.isMultiparty()).thenReturn(true);
 
         mControllerTest.add(mTestTelephonyConnectionB);
         mControllerTest.add(mTestTelephonyConnectionA);
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index f13d709..7e6488d 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.services.telephony;
 
+import static junit.framework.Assert.assertTrue;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -573,4 +575,40 @@
         assertEquals(0, imsConference.getNumberOfParticipants());
         verify(mConferenceHost.mMockCall).hangup();
     }
+
+    /**
+     * Verifies that an ImsConference can handle SIP and TEL URIs for both the P-Associated-Uri and
+     * conference event package identities.
+     */
+    @Test
+    public void testIsParticipantHost() {
+        // Simplest case, assume P-Associated-Uri is a tel URI and that the CEP participant is also
+        // a tel URI.
+        assertTrue(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("tel:+8616505551234")},
+                Uri.parse("tel:+8616505551234")));
+
+        // Assume P-Associated-Uri is a tel URI and the CEP participant is a sip URI.
+        assertTrue(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("tel:+8616505551234")},
+                Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")));
+
+        // Assume P-Associated-Uri is a sip URI and the CEP participant is a tel URI.
+        assertTrue(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")},
+                Uri.parse("tel:+8616505551234")));
+
+        // Assume both P-Associated-Uri and the CEP participant are SIP URIs.
+        assertTrue(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")},
+                Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")));
+
+        // Corner cases
+        assertFalse(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("tel:+8616505551234")}, Uri.fromParts("", "", "")));
+        assertFalse(ImsConference.isParticipantHost(new Uri[] {
+                        Uri.parse("tel:+8616505551234")}, null));
+        assertFalse(ImsConference.isParticipantHost(null, null));
+        assertFalse(ImsConference.isParticipantHost(new Uri[0], null));
+    }
 }
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 2060e6f..07fe6a8 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -936,14 +936,14 @@
 
         // Setup test to not support SUPL on the non-DDS subscription
         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 null);
         testPhone.getServiceState().setRoaming(false);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "150");
         delayDialRunnable.run();
 
@@ -1021,14 +1021,14 @@
 
         // Setup test to not support SUPL on the non-DDS subscription
         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 null);
         testPhone.getServiceState().setRoaming(false);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
         delayDialRunnable.run();
 
@@ -1047,14 +1047,14 @@
 
         // If the non-DDS supports SUPL, dont switch data
         doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 null);
         testPhone.getServiceState().setRoaming(false);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
         delayDialRunnable.run();
 
@@ -1073,14 +1073,14 @@
 
         // Setup test to not support SUPL on the non-DDS subscription
         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 null);
         testPhone.getServiceState().setRoaming(true);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
         delayDialRunnable.run();
 
@@ -1107,13 +1107,13 @@
         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
         String[] roamingPlmns = new String[1];
         roamingPlmns[0] = testRoamingOperator;
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 roamingPlmns);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
         delayDialRunnable.run();
 
@@ -1140,13 +1140,13 @@
         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
         String[] roamingPlmns = new String[1];
         roamingPlmns[0] = testRoamingOperator;
-        getTestContext().getCarrierConfig().putStringArray(
+        getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
                 roamingPlmns);
-        getTestContext().getCarrierConfig().putInt(
+        getTestContext().getCarrierConfig(0 /*subId*/).putInt(
                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
-        getTestContext().getCarrierConfig().putString(
+        getTestContext().getCarrierConfig(0 /*subId*/).putString(
                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
         delayDialRunnable.run();
 
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
index 7d15680..5c3c913 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
@@ -1,25 +1,116 @@
 package com.android.services.telephony;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static junit.framework.TestCase.assertFalse;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
 
 import android.os.Bundle;
 import android.telecom.Connection;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import android.telephony.ims.RtpHeaderExtension;
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
+import com.android.phone.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Set;
+
 @RunWith(AndroidJUnit4.class)
 public class TelephonyConnectionTest {
+    @Mock
+    private ImsPhoneConnection mImsPhoneConnection;
+    @Captor
+    private ArgumentCaptor<Set<RtpHeaderExtension>> mRtpHeaderExtensionCaptor;
+
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mImsPhoneConnection.getState()).thenReturn(Call.State.ACTIVE);
+        when(mImsPhoneConnection.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
+    }
+
+    /**
+     * Ensures an Ims connection uses the D2D communicator when it is enabled.
+     */
+    @Test
+    public void testSetupCommunicator() {
+        TestTelephonyConnection c = new TestTelephonyConnection();
+        c.setIsImsConnection(true);
+        // Enable D2D comms.
+        when(c.mMockResources.getBoolean(eq(
+                R.bool.config_use_device_to_device_communication))).thenReturn(true);
+
+        c.setOriginalConnection(mImsPhoneConnection);
+        junit.framework.Assert.assertNotNull(c.getCommunicator());
+    }
+
+    /**
+     * Ensures an Ims connection does not use the D2D communicator when it is disabled.
+     */
+    @Test
+    public void testDoNotSetupCommunicator() {
+        TestTelephonyConnection c = new TestTelephonyConnection();
+        c.setIsImsConnection(true);
+        // Disable D2D comms.
+        when(c.mMockResources.getBoolean(eq(
+                R.bool.config_use_device_to_device_communication))).thenReturn(false);
+
+        c.setOriginalConnection(mImsPhoneConnection);
+        junit.framework.Assert.assertNull(c.getCommunicator());
+    }
 
     @Test
     public void testCodecInIms() {
         TestTelephonyConnection c = new TestTelephonyConnection();
+        c.setIsImsConnection(true);
         c.updateState();
         Bundle extras = c.getExtras();
         int codec = extras.getInt(Connection.EXTRA_AUDIO_CODEC, Connection.AUDIO_CODEC_NONE);
         assertEquals(codec, Connection.AUDIO_CODEC_AMR);
     }
 
+    @Test
+    public void testConferenceNotSupportedForDownGradedVideoCall() {
+        TestTelephonyConnection c = new TestTelephonyConnection();
+        c.setIsImsConnection(true);
+        c.setIsVideoCall(false);
+        c.setWasVideoCall(true);
+        c.setDownGradeVideoCall(true);
+        c.refreshConferenceSupported();
+        assertFalse(c.isConferenceSupported());
+        c.setDownGradeVideoCall(false);
+        c.refreshConferenceSupported();
+        assertTrue(c.isConferenceSupported());
+    }
+
+    /**
+     * Tests to ensure that the presence of an ImsExternalConnection does not cause a crash in
+     * TelephonyConnection due to an illegal cast.
+     */
+    @Test
+    public void testImsExternalConnectionOnRefreshConference() {
+        TestTelephonyConnection c = new TestTelephonyConnection();
+        c.setIsImsConnection(true);
+        c.setIsImsExternalConnection(true);
+        try {
+            c.refreshConferenceSupported();
+        } catch (ClassCastException e) {
+            fail("refreshConferenceSupported threw ClassCastException");
+        }
+    }
 }
diff --git a/tests/src/com/android/services/telephony/TelephonyManagerTest.java b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
new file mode 100644
index 0000000..2202bc7
--- /dev/null
+++ b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
+import android.test.mock.MockContext;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.telephony.ITelephony;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Unit tests for {@link TelephonyManager}. */
+@RunWith(AndroidJUnit4.class)
+public class TelephonyManagerTest {
+    private static final String PKG_NAME = "Unittest.TelephonyManagerTest";
+    private static final String TAG = "TelephonyManagerTest";
+
+    private ITelephony mMockITelephony;
+    private SubscriptionManager mMockSubscriptionManager;
+    private Context mMockContext;
+
+    private TelephonyManager mTelephonyManager;
+
+    private final MockContext mContext =
+            new MockContext() {
+                @Override
+                public String getOpPackageName() {
+                    return PKG_NAME;
+                }
+                @Override
+                public String getAttributionTag() {
+                    return TAG;
+                }
+                @Override
+                public Context getApplicationContext() {
+                    return null;
+                }
+                @Override
+                public Object getSystemService(String name) {
+                    switch (name) {
+                        case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
+                            return mMockSubscriptionManager;
+                        }
+                    }
+                    return null;
+                }
+            };
+
+    @Before
+    public void setUp() throws Exception {
+        mMockITelephony = mock(ITelephony.class);
+        mMockSubscriptionManager = mock(SubscriptionManager.class);
+        mMockContext = mock(Context.class);
+        when(mMockContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
+                .thenReturn(mMockSubscriptionManager);
+
+        mTelephonyManager = new TelephonyManager(mContext);
+        TelephonyManager.setupITelephonyForTest(mMockITelephony);
+        TelephonyManager.enableServiceHandleCaching();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        TelephonyManager.setupITelephonyForTest(null);
+        TelephonyManager.disableServiceHandleCaching();
+    }
+
+    @Test
+    public void testFilterEmergencyNumbersByCategories() throws Exception {
+        Map<Integer, List<EmergencyNumber>> emergencyNumberLists = new HashMap<>();
+        List<EmergencyNumber> emergencyNumberList = new ArrayList<>();
+        EmergencyNumber number_police = new EmergencyNumber(
+                "911",
+                "us",
+                "30",
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+                new ArrayList<String>(),
+                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+        EmergencyNumber number_fire = new EmergencyNumber(
+                "912",
+                "us",
+                "30",
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE,
+                new ArrayList<String>(),
+                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+        emergencyNumberList.add(number_police);
+        emergencyNumberList.add(number_fire);
+        final int test_sub_id = 1;
+        emergencyNumberLists.put(test_sub_id, emergencyNumberList);
+
+        Map<Integer, List<EmergencyNumber>> returnedEmergencyNumberLists =
+                mTelephonyManager.filterEmergencyNumbersByCategories(emergencyNumberLists,
+                        EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+
+        // Verify the returned number list contains only the police number(s)
+        List<EmergencyNumber> returnedEmergencyNumberList = returnedEmergencyNumberLists.get(
+                test_sub_id);
+        for (EmergencyNumber num : returnedEmergencyNumberList) {
+            assertTrue(num.isInEmergencyServiceCategories(
+                    EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE));
+        }
+    }
+
+    @Test
+    public void testGetEmergencyNumberListForCategories() throws Exception {
+        Map<Integer, List<EmergencyNumber>> emergencyNumberLists = new HashMap<>();
+        List<EmergencyNumber> emergencyNumberList = new ArrayList<>();
+        EmergencyNumber number_police = new EmergencyNumber(
+                "911",
+                "us",
+                "30",
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+                new ArrayList<String>(),
+                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+        EmergencyNumber number_fire = new EmergencyNumber(
+                "912",
+                "us",
+                "30",
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE,
+                new ArrayList<String>(),
+                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+        emergencyNumberList.add(number_police);
+        emergencyNumberList.add(number_fire);
+        final int test_sub_id = 1;
+        emergencyNumberLists.put(test_sub_id, emergencyNumberList);
+        when(mMockITelephony.getEmergencyNumberList(eq(PKG_NAME), eq(TAG))).thenReturn(
+                emergencyNumberLists);
+
+        // Call TelephonyManager.getEmergencyNumberList(Category)
+        Map<Integer, List<EmergencyNumber>> returnedEmergencyNumberLists =
+                mTelephonyManager.getEmergencyNumberList(
+                        EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+
+        // Verify the ITelephony service is called
+        verify(mMockITelephony, times(1)).getEmergencyNumberList(eq(PKG_NAME), eq(TAG));
+
+        // Verify the returned number list contains only the police number(s)
+        List<EmergencyNumber> returnedEmergencyNumberList = returnedEmergencyNumberLists.get(
+                test_sub_id);
+        for (EmergencyNumber num : returnedEmergencyNumberList) {
+            assertTrue(num.isInEmergencyServiceCategories(
+                    EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE));
+        }
+    }
+}
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 09cec17..596393c 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -16,25 +16,33 @@
 
 package com.android.services.telephony;
 
+import android.telephony.TelephonyManager;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.VideoProfile;
+import android.telephony.CarrierConfigManager;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
+import com.android.ims.ImsCall;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.imsphone.ImsExternalConnection;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -61,16 +69,44 @@
     Resources mMockResources;
 
     @Mock
+    TelephonyManager mMockTelephonyManager;
+
+    @Mock
     EmergencyNumberTracker mEmergencyNumberTracker;
 
+    @Mock
+    ImsPhoneConnection mImsPhoneConnection;
+
+    @Mock
+    ImsExternalConnection mImsExternalConnection;
+
+    @Mock
+    ImsCall mImsCall;
+
+    @Mock
+    TelecomAccountRegistry mTelecomAccountRegistry;
+
+    @Mock
+    CarrierConfigManager mCarrierConfigManager;
+
+    private boolean mIsImsConnection;
+    private boolean mIsImsExternalConnection;
+    private boolean mIsConferenceSupported = true;
     private Phone mMockPhone;
     private int mNotifyPhoneAccountChangedCount = 0;
     private List<String> mLastConnectionEvents = new ArrayList<>();
     private List<Bundle> mLastConnectionEventExtras = new ArrayList<>();
+    private Object mLock = new Object();
 
     @Override
     public com.android.internal.telephony.Connection getOriginalConnection() {
-        return mMockRadioConnection;
+        if (mIsImsExternalConnection) {
+            return mImsExternalConnection;
+        } else if (mIsImsConnection) {
+            return mImsPhoneConnection;
+        } else {
+            return mMockRadioConnection;
+        }
     }
 
     @Override
@@ -82,16 +118,22 @@
         super(null, null, android.telecom.Call.Details.DIRECTION_INCOMING);
         MockitoAnnotations.initMocks(this);
 
+        mIsImsConnection = false;
+        mIsImsExternalConnection = false;
         mMockPhone = mock(Phone.class);
         mMockContext = mock(Context.class);
+        mMockTelephonyManager = mock(TelephonyManager.class);
         mOriginalConnection = mMockRadioConnection;
         // Set up mMockRadioConnection and mMockPhone to contain an active call
         when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
         when(mOriginalConnection.getState()).thenReturn(Call.State.ACTIVE);
         when(mMockRadioConnection.getAudioCodec()).thenReturn(
                 android.telecom.Connection.AUDIO_CODEC_AMR);
+        when(mImsPhoneConnection.getAudioCodec()).thenReturn(
+                android.telecom.Connection.AUDIO_CODEC_AMR);
         when(mMockRadioConnection.getCall()).thenReturn(mMockCall);
         when(mMockRadioConnection.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
+        when(mImsPhoneConnection.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
         doNothing().when(mMockRadioConnection).addListener(any(Connection.Listener.class));
         doNothing().when(mMockRadioConnection).addPostDialListener(
                 any(Connection.PostDialListener.class));
@@ -101,11 +143,24 @@
         when(mMockPhone.getContext()).thenReturn(mMockContext);
         when(mMockPhone.getCurrentSubscriberUris()).thenReturn(null);
         when(mMockContext.getResources()).thenReturn(mMockResources);
+        when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
+                .thenReturn(mMockTelephonyManager);
         when(mMockResources.getBoolean(anyInt())).thenReturn(false);
         when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
         when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
         when(mMockCall.getState()).thenReturn(Call.State.ACTIVE);
         when(mMockCall.getPhone()).thenReturn(mMockPhone);
+        when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
+        when(mImsPhoneConnection.getImsCall()).thenReturn(mImsCall);
+        when(mTelecomAccountRegistry.isMergeCallSupported(notNull(PhoneAccountHandle.class)))
+                .thenReturn(mIsConferenceSupported);
+        when(mTelecomAccountRegistry.isMergeImsCallSupported(notNull(PhoneAccountHandle.class)))
+                .thenReturn(mIsImsConnection);
+        when(mTelecomAccountRegistry
+                .isVideoConferencingSupported(notNull(PhoneAccountHandle.class))).thenReturn(false);
+        when(mTelecomAccountRegistry
+                .isMergeOfWifiCallsAllowedWhenVoWifiOff(notNull(PhoneAccountHandle.class)))
+                .thenReturn(false);
         try {
             doNothing().when(mMockCall).hangup();
         } catch (CallStateException e) {
@@ -113,11 +168,6 @@
         }
     }
 
-    @Override
-    public boolean isConferenceSupported() {
-        return true;
-    }
-
     public void setMockPhone(Phone newPhone) {
         mMockPhone = newPhone;
     }
@@ -155,6 +205,13 @@
     }
 
     @Override
+    public void refreshConferenceSupported() {
+        if (mIsImsConnection) {
+            super.refreshConferenceSupported();
+        }
+    }
+
+    @Override
     public CharSequence getResourceText(int messageId) {
         return "TEST";
     }
@@ -165,8 +222,36 @@
     }
 
     @Override
-    void refreshConferenceSupported() {
-        // Requires ImsManager dependencies, do not implement during testing.
+    public void setConferenceSupported(boolean conferenceSupported) {
+        mIsConferenceSupported = conferenceSupported;
+    }
+
+    @Override
+    public boolean isConferenceSupported() {
+        return mIsConferenceSupported;
+    }
+
+    @Override
+    public TelecomAccountRegistry getTelecomAccountRegistry(Context context) {
+        return mTelecomAccountRegistry;
+    }
+
+    public void setIsVideoCall(boolean isVideoCall) {
+        if (isVideoCall) {
+            setVideoState(VideoProfile.STATE_TX_ENABLED);
+        } else {
+            setVideoState(VideoProfile.STATE_AUDIO_ONLY);
+        }
+    }
+
+    public void setWasVideoCall(boolean wasVideoCall) {
+        when(mImsCall.wasVideoCall()).thenReturn(wasVideoCall);
+    }
+
+    @Override
+    boolean isWfcEnabled(Phone phone) {
+        // Requires ImsManager dependencies, mock for test.
+        return true;
     }
 
     public int getNotifyPhoneAccountChangedCount() {
@@ -180,4 +265,23 @@
     public List<Bundle> getLastConnectionEventExtras() {
         return mLastConnectionEventExtras;
     }
+
+    public void setIsImsConnection(boolean isImsConnection) {
+        mIsImsConnection = isImsConnection;
+        when(mTelecomAccountRegistry.isMergeImsCallSupported(notNull(PhoneAccountHandle.class)))
+                .thenReturn(isImsConnection && mIsConferenceSupported);
+    }
+
+    public void setIsImsExternalConnection(boolean isExternalConnection) {
+        mIsImsExternalConnection = isExternalConnection;
+    }
+
+    public void setDownGradeVideoCall(boolean downgrade) {
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL,
+                downgrade);
+        when(mMockContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
+                .thenReturn(mCarrierConfigManager);
+        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+    }
 }
diff --git a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
new file mode 100644
index 0000000..4d40702
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class DelegateStateTrackerTest extends TelephonyTestBase {
+    private static final int TEST_SUB_ID = 1;
+
+    @Mock private ISipDelegate mSipDelegate;
+    @Mock private ISipDelegateConnectionStateCallback mAppCallback;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * When an underlying SipDelegate is created, the app should only receive one onCreated callback
+     * independent of how many times sipDelegateConnected is called. Once created, registration
+     * and IMS configuration events should propagate up to the app as well.
+     */
+    @SmallTest
+    @Test
+    public void testDelegateCreated() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+                mSipDelegate);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        stateTracker.sipDelegateConnected(deniedTags);
+        // Calling connected multiple times should not generate multiple onCreated events.
+        stateTracker.sipDelegateConnected(deniedTags);
+        verify(mAppCallback).onCreated(mSipDelegate);
+
+        // Ensure status updates are sent to app as expected.
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .build();
+        SipDelegateImsConfiguration config = new SipDelegateImsConfiguration.Builder(1/*version*/)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+        stateTracker.onImsConfigurationChanged(config);
+        verify(mAppCallback).onFeatureTagStatusChanged(eq(regState),
+                eq(new ArrayList<>(deniedTags)));
+        verify(mAppCallback).onImsConfigurationChanged(config);
+
+        verify(mAppCallback, never()).onDestroyed(anyInt());
+    }
+
+    /**
+     * onDestroyed should be called when sipDelegateDestroyed is called.
+     */
+    @SmallTest
+    @Test
+    public void testDelegateDestroyed() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+                mSipDelegate);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        stateTracker.sipDelegateConnected(deniedTags);
+
+        stateTracker.sipDelegateDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mAppCallback).onDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+    }
+
+    /**
+     * When a SipDelegate is created and then an event occurs that will destroy->create a new
+     * SipDelegate underneath, we need to move the state of the features that are reporting
+     * registered to DEREGISTERING_REASON_FEATURE_TAGS_CHANGING so that the app can close dialogs on
+     * it. Once the new underlying SipDelegate is created, we must verify that the new registration
+     * is propagated up without any overrides.
+     */
+    @SmallTest
+    @Test
+    public void testDelegateChangingRegisteredTagsOverride() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+                mSipDelegate);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        stateTracker.sipDelegateConnected(deniedTags);
+        // SipDelegate created
+        verify(mAppCallback).onCreated(mSipDelegate);
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+        // Simulate underlying SipDelegate switch
+        stateTracker.sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+        // onFeatureTagStatusChanged should now be called with registered features overridden with
+        // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING
+        DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+                .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING)
+                // Already Deregistering/Deregistered tags should not be overridden.
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        // new underlying SipDelegate created
+        stateTracker.sipDelegateConnected(deniedTags);
+        stateTracker.onRegistrationStateChanged(regState);
+
+        // Verify registration state through the process:
+        ArgumentCaptor<DelegateRegistrationState> regCaptor =
+                ArgumentCaptor.forClass(DelegateRegistrationState.class);
+        verify(mAppCallback, times(3)).onFeatureTagStatusChanged(
+                regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+        List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+        // feature tags should first be registered
+        assertEquals(regState, testStates.get(0));
+        // registered feature tags should have moved to deregistering
+        assertEquals(overrideRegState, testStates.get(1));
+        // and then moved back to registered after underlying FT change done.
+        assertEquals(regState, testStates.get(2));
+
+        //onCreate should only have been called once and onDestroy should have never been called.
+        verify(mAppCallback).onCreated(mSipDelegate);
+        verify(mAppCallback, never()).onDestroyed(anyInt());
+    }
+
+    /**
+     * Test the case that when the underlying Denied tags change in the SipDelegate, the change is
+     * properly shown in the registration update event.
+     */
+    @SmallTest
+    @Test
+    public void testDelegateChangingDeniedTagsChanged() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+                mSipDelegate);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        stateTracker.sipDelegateConnected(deniedTags);
+        // SipDelegate created
+        verify(mAppCallback).onCreated(mSipDelegate);
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+        // Simulate underlying SipDelegate switch
+        stateTracker.sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+        // onFeatureTagStatusChanged should now be called with registered features overridden with
+        // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING
+        DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+                .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING)
+                .build();
+        // Verify registration state so far.
+        ArgumentCaptor<DelegateRegistrationState> regCaptor =
+                ArgumentCaptor.forClass(DelegateRegistrationState.class);
+        verify(mAppCallback, times(2)).onFeatureTagStatusChanged(
+                regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+        List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+        assertEquals(2, testStates.size());
+        // feature tags should first be registered
+        assertEquals(regState, testStates.get(0));
+        // registered feature tags should have moved to deregistering
+        assertEquals(overrideRegState, testStates.get(1));
+
+        // new underlying SipDelegate created, but SipDelegate denied one to one chat
+        deniedTags.add(new FeatureTagState(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+        stateTracker.sipDelegateConnected(deniedTags);
+        DelegateRegistrationState fullyDeniedRegState = new DelegateRegistrationState.Builder()
+                .build();
+        // In this special case, it will be the SipDelegateConnectionBase that will trigger
+        // reg state change.
+        stateTracker.onRegistrationStateChanged(fullyDeniedRegState);
+        verify(mAppCallback).onFeatureTagStatusChanged(regCaptor.capture(),
+                eq(new ArrayList<>(deniedTags)));
+        // now all feature tags denied, so we should see only denied tags.
+        assertEquals(fullyDeniedRegState, regCaptor.getValue());
+
+        //onCreate should only have been called once and onDestroy should have never been called.
+        verify(mAppCallback).onCreated(mSipDelegate);
+        verify(mAppCallback, never()).onDestroyed(anyInt());
+    }
+
+    /**
+     * Test that when we move from changing tags state to the delegate being destroyed, we get the
+     * correct onDestroy event sent to the app.
+     */
+    @SmallTest
+    @Test
+    public void testDelegateChangingDeniedTagsChangingToDestroy() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+                mSipDelegate);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        stateTracker.sipDelegateConnected(deniedTags);
+        // SipDelegate created
+        verify(mAppCallback).onCreated(mSipDelegate);
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+        verify(mAppCallback).onFeatureTagStatusChanged(any(),
+                eq(new ArrayList<>(deniedTags)));
+        // Simulate underlying SipDelegate switch
+        stateTracker.sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+        // Destroy
+        stateTracker.sipDelegateDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+        // onFeatureTagStatusChanged should now be called with registered features overridden with
+        // DEREGISTERING_REASON_DESTROY_PENDING
+        DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+                .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING)
+                // Deregistered should stay the same.
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        // Verify registration state through process:
+        ArgumentCaptor<DelegateRegistrationState> regCaptor =
+                ArgumentCaptor.forClass(DelegateRegistrationState.class);
+        verify(mAppCallback, times(2)).onFeatureTagStatusChanged(regCaptor.capture(),
+                eq(new ArrayList<>(deniedTags)));
+        List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+        assertEquals(2, testStates.size());
+        // feature tags should first be registered
+        assertEquals(regState, testStates.get(0));
+        // registered feature tags should have moved to deregistering
+        assertEquals(overrideRegState, testStates.get(1));
+        //onCreate/onDestroy should only be called once.
+        verify(mAppCallback).onCreated(mSipDelegate);
+        verify(mAppCallback).onDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+    }
+
+    private Set<FeatureTagState> getMmTelDeniedTag() {
+        Set<FeatureTagState> deniedTags = new ArraySet<>();
+        deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+        return deniedTags;
+    }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
new file mode 100644
index 0000000..d607f6d
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+/**
+ * Various definitions and utilities related to IMS Signalling.
+ */
+public class ImsSignallingUtils {
+    public static final String MMTEL_TAG =
+            "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"";
+    public static final String ONE_TO_ONE_CHAT_TAG =
+            "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.msg\"";
+    public static final String GROUP_CHAT_TAG =
+            "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.session\"";
+    public static final String FILE_TRANSFER_HTTP_TAG =
+            "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gppapplication.ims.iari.rcs.fthttp\"";
+}
diff --git a/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
new file mode 100644
index 0000000..5e05085
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class MessageTransportStateTrackerTest extends TelephonyTestBase {
+    private static final int TEST_SUB_ID = 1;
+
+    private static final SipMessage TEST_MESSAGE = new SipMessage(
+            "INVITE sip:callee@ex.domain.com SIP/2.0",
+            "Via: SIP/2.0/UDP ex.place.com;branch=z9hG4bK776asdhds",
+            new byte[0]);
+
+    // Use for finer-grained control of when the Executor executes.
+    private static class PendingExecutor implements Executor {
+        private final ArrayList<Runnable> mPendingRunnables = new ArrayList<>();
+
+        @Override
+        public void execute(Runnable command) {
+            mPendingRunnables.add(command);
+        }
+
+        public void executePending() {
+            for (Runnable r : mPendingRunnables) {
+                r.run();
+            }
+            mPendingRunnables.clear();
+        }
+    }
+
+    @Mock private ISipDelegateMessageCallback mDelegateMessageCallback;
+    @Mock private ISipDelegate mISipDelegate;
+    @Mock private Consumer<Boolean> mMockCloseConsumer;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateConnectionSendOutgoingMessage() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+
+        doThrow(new RemoteException()).when(mISipDelegate).sendMessage(any(), anyLong());
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+                eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD));
+
+        tracker.close(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+                eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED));
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateConnectionCloseGracefully() throws Exception {
+        PendingExecutor executor = new PendingExecutor();
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                executor, mDelegateMessageCallback);
+
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        executor.executePending();
+        verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+        verify(mDelegateMessageCallback, never()).onMessageSendFailure(any(), anyInt());
+
+        // Use PendingExecutor a little weird here, we need to queue sendMessage first, even though
+        // closeGracefully will complete partly synchronously to test that the pending message will
+        // return MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION before the scheduled
+        // graceful close operation completes.
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        tracker.closeGracefully(
+                SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+                SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+                mMockCloseConsumer);
+        verify(mMockCloseConsumer, never()).accept(any());
+        // resolve pending close operation
+        executor.executePending();
+        verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+                eq(SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION));
+        // Still should only report one call of sendMessage from before
+        verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+        verify(mMockCloseConsumer).accept(true);
+
+        // ensure that after close operation completes, we get the correct
+        // MESSAGE_FAILURE_REASON_DELEGATE_CLOSED message.
+        tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+        executor.executePending();
+        verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+                eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED));
+        // Still should only report one call of sendMessage from before
+        verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateConnectionNotifyMessageReceived() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getDelegateConnection().notifyMessageReceived("z9hG4bK776asdhds");
+        verify(mISipDelegate).notifyMessageReceived("z9hG4bK776asdhds");
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateConnectionNotifyMessageReceiveError() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getDelegateConnection().notifyMessageReceiveError("z9hG4bK776asdhds",
+                SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+        verify(mISipDelegate).notifyMessageReceiveError("z9hG4bK776asdhds",
+                SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateConnectionCloseDialog() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getDelegateConnection().closeDialog("testCallId");
+        verify(mISipDelegate).closeDialog("testCallId");
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateOnMessageReceived() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+
+        tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+        verify(mDelegateMessageCallback).onMessageReceived(TEST_MESSAGE);
+
+        doThrow(new RemoteException()).when(mDelegateMessageCallback).onMessageReceived(any());
+        tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+        verify(mISipDelegate).notifyMessageReceiveError(any(),
+                eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD));
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateOnMessageReceivedClosedGracefully() throws Exception {
+        PendingExecutor executor = new PendingExecutor();
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                executor, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+
+        tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+        executor.executePending();
+        verify(mDelegateMessageCallback).onMessageReceived(TEST_MESSAGE);
+
+        tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+        tracker.closeGracefully(
+                SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+                SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+                mMockCloseConsumer);
+        executor.executePending();
+        // Incoming SIP message should not be blocked by closeGracefully
+        verify(mDelegateMessageCallback, times(2)).onMessageReceived(TEST_MESSAGE);
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateOnMessageSent() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getMessageCallback().onMessageSent("z9hG4bK776asdhds");
+        verify(mDelegateMessageCallback).onMessageSent("z9hG4bK776asdhds");
+    }
+
+    @SmallTest
+    @Test
+    public void testDelegateonMessageSendFailure() throws Exception {
+        MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+                Runnable::run, mDelegateMessageCallback);
+        tracker.openTransport(mISipDelegate, Collections.emptySet());
+        tracker.getMessageCallback().onMessageSendFailure("z9hG4bK776asdhds",
+                SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+        verify(mDelegateMessageCallback).onMessageSendFailure("z9hG4bK776asdhds",
+                SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+    }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index fbb270d..7e87dc7 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -100,7 +100,8 @@
         verify(mMockFeature).onRcsConnected(mFeatureManager);
 
         // Disconnect
-        mConnectorListener.getValue().connectionUnavailable();
+        mConnectorListener.getValue().connectionUnavailable(
+                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
 
         verify(mFeatureManager).unregisterImsRegistrationCallback(any());
         verify(mMockFeature, times(2)).onRcsDisconnected();
@@ -193,7 +194,8 @@
     public void testFeatureManagerDisconnectedAddFeature() {
         RcsFeatureController controller = createFeatureController();
         // Disconnect the RcsFeatureManager
-        mConnectorListener.getValue().connectionUnavailable();
+        mConnectorListener.getValue().connectionUnavailable(
+                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
 
         verify(mMockFeature).onRcsDisconnected();
@@ -205,7 +207,8 @@
         IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
         IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
         // Disconnect the RcsFeatureManager
-        mConnectorListener.getValue().connectionUnavailable();
+        mConnectorListener.getValue().connectionUnavailable(
+                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
 
         try {
             controller.registerImsRegistrationCallback(0 /*subId*/, null /*callback*/);
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java
new file mode 100644
index 0000000..360fa21
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class SipDelegateBinderConnectionTest extends TelephonyTestBase {
+    private static final int TEST_SUB_ID = 1;
+
+    @Mock private ISipDelegate mMockDelegate;
+    @Mock private ISipTransport mMockTransport;
+    @Mock private IImsRegistration mMockRegistration;
+    @Mock private IBinder mTransportBinder;
+    @Mock private ISipDelegateMessageCallback mMessageCallback;
+    @Mock private DelegateBinderStateManager.StateCallback mMockStateCallback;
+    @Mock private BiConsumer<ISipDelegate, Set<FeatureTagState>> mMockCreatedCallback;
+    @Mock private Consumer<Integer> mMockDestroyedCallback;
+
+    private ArrayList<SipDelegateBinderConnection.StateCallback> mStateCallbackList;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        doReturn(mTransportBinder).when(mMockTransport).asBinder();
+        mStateCallbackList = new ArrayList<>(1);
+        mStateCallbackList.add(mMockStateCallback);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @SmallTest
+    @Test
+    public void testBaseImpl() throws Exception {
+        DelegateBinderStateManager baseConnection = new SipDelegateBinderConnectionStub(
+                getMmTelDeniedTag(), Runnable::run, mStateCallbackList);
+
+        baseConnection.create(null /*message cb*/, mMockCreatedCallback);
+        // Verify the stub simulates onCreated + on registration state callback.
+        verify(mMockCreatedCallback).accept(any(), eq(getMmTelDeniedTag()));
+        verify(mMockStateCallback).onRegistrationStateChanged(
+                new DelegateRegistrationState.Builder().build());
+
+        // Verify onDestroyed is called correctly.
+        baseConnection.destroy(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+                mMockDestroyedCallback);
+        verify(mMockDestroyedCallback).accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+    }
+
+    @SmallTest
+    @Test
+    public void testCreateConnection() throws Exception {
+        DelegateRequest request = getDelegateRequest();
+        ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+                mMockTransport, mMockRegistration, request, deniedTags, Runnable::run,
+                mStateCallbackList);
+        ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+
+        // Send onCreated callback from SipDelegate
+        ArrayList<FeatureTagState> delegateDeniedTags = new ArrayList<>(1);
+        delegateDeniedTags.add(new FeatureTagState(ImsSignallingUtils.GROUP_CHAT_TAG,
+                SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+        assertNotNull(cb);
+        cb.onCreated(mMockDelegate, delegateDeniedTags);
+
+        ArraySet<FeatureTagState> totalDeniedTags = new ArraySet<>(deniedTags);
+        // Add the tags denied by the controller as well.
+        totalDeniedTags.addAll(delegateDeniedTags);
+        // The callback should contain the controller and delegate denied tags in the callback.
+        verify(mMockCreatedCallback).accept(mMockDelegate, totalDeniedTags);
+    }
+
+    @SmallTest
+    @Test
+    public void testCreateConnectionServiceDead() throws Exception {
+        DelegateRequest request = getDelegateRequest();
+        ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+                mMockTransport, mMockRegistration, request, deniedTags, Runnable::run,
+                mStateCallbackList);
+        doThrow(new RemoteException()).when(mMockTransport).createSipDelegate(eq(TEST_SUB_ID),
+                any(), any(), any());
+        ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+        assertNull(cb);
+    }
+
+    @SmallTest
+    @Test
+    public void testDestroyConnection() throws Exception {
+        DelegateRequest request = getDelegateRequest();
+        ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+                mMockTransport, mMockRegistration, request, deniedTags, Runnable::run,
+                mStateCallbackList);
+        ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+        assertNotNull(cb);
+        cb.onCreated(mMockDelegate, null /*denied*/);
+        verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+        // call Destroy on the SipDelegate
+        destroy(connection, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        cb.onDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mMockDestroyedCallback).accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+    }
+
+    @SmallTest
+    @Test
+    public void testDestroyConnectionDead() throws Exception {
+        DelegateRequest request = getDelegateRequest();
+        ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+                mMockTransport, mMockRegistration, request, deniedTags, Runnable::run,
+                mStateCallbackList);
+        ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+        assertNotNull(cb);
+        cb.onCreated(mMockDelegate, null /*denied*/);
+        verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+        // try to destroy when dead and ensure callback is still called.
+        doThrow(new RemoteException()).when(mMockTransport).destroySipDelegate(any(), anyInt());
+        destroy(connection, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mMockDestroyedCallback).accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+    }
+
+    @SmallTest
+    @Test
+    public void testStateCallback() throws Exception {
+        DelegateRequest request = getDelegateRequest();
+        ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+                mMockTransport, mMockRegistration, request, deniedTags, Runnable::run,
+                mStateCallbackList);
+        ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+        assertNotNull(cb);
+        cb.onCreated(mMockDelegate, new ArrayList<>(deniedTags));
+        verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+        SipDelegateImsConfiguration config = new SipDelegateImsConfiguration.Builder(1).build();
+        cb.onImsConfigurationChanged(config);
+        verify(mMockStateCallback).onImsConfigurationChanged(config);
+
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTags(request.getFeatureTags()).build();
+        cb.onFeatureTagRegistrationChanged(regState);
+        verify(mMockStateCallback).onRegistrationStateChanged(regState);
+    }
+
+    private ISipDelegateStateCallback createDelegateCaptureStateCallback(
+            DelegateRequest r, SipDelegateBinderConnection c) throws Exception {
+        boolean isCreating = c.create(mMessageCallback, mMockCreatedCallback);
+        if (!isCreating) return null;
+        ArgumentCaptor<ISipDelegateStateCallback> stateCaptor =
+                ArgumentCaptor.forClass(ISipDelegateStateCallback.class);
+        verify(mMockTransport).createSipDelegate(eq(TEST_SUB_ID), eq(r), stateCaptor.capture(),
+                eq(mMessageCallback));
+        assertNotNull(stateCaptor.getValue());
+        return stateCaptor.getValue();
+    }
+
+    private void destroy(SipDelegateBinderConnection c, int reason) throws Exception {
+        c.destroy(reason, mMockDestroyedCallback);
+        verify(mMockTransport).destroySipDelegate(mMockDelegate, reason);
+    }
+
+    private DelegateRequest getDelegateRequest() {
+        ArraySet<String> featureTags = new ArraySet<>(2);
+        featureTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        featureTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+        return new DelegateRequest(featureTags);
+    }
+
+    private ArraySet<FeatureTagState> getMmTelDeniedTag() {
+        ArraySet<FeatureTagState> deniedTags = new ArraySet<>();
+        deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+        return deniedTags;
+    }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
new file mode 100644
index 0000000..27f896b
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class SipDelegateControllerTest extends TelephonyTestBase {
+    private static final int TEST_SUB_ID = 1;
+
+    @Mock private ISipDelegate mMockSipDelegate;
+    @Mock private MessageTransportStateTracker mMockMessageTracker;
+    @Mock private ISipDelegateMessageCallback mMockMessageCallback;
+    @Mock private DelegateStateTracker mMockDelegateStateTracker;
+    @Mock private DelegateBinderStateManager mMockBinderConnection;
+    @Captor private ArgumentCaptor<BiConsumer<ISipDelegate, Set<FeatureTagState>>> mCreatedCaptor;
+    @Captor private ArgumentCaptor<Consumer<Boolean>> mBooleanConsumerCaptor;
+    @Captor private ArgumentCaptor<Consumer<Integer>> mIntegerConsumerCaptor;
+
+    private ScheduledExecutorService mExecutorService;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        when(mMockMessageTracker.getMessageCallback()).thenReturn(mMockMessageCallback);
+        mExecutorService = new TestExecutorService();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mExecutorService.shutdownNow();
+        super.tearDown();
+    }
+
+    @SmallTest
+    @Test
+    public void testCreateDelegate() throws Exception {
+        DelegateRequest request = getBaseDelegateRequest();
+        SipDelegateController controller = getTestDelegateController(request,
+                Collections.emptySet());
+
+        doReturn(true).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+        CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+                Collections.emptySet() /*denied tags*/);
+        BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+                verifyConnectionCreated(1);
+        assertNotNull(consumer);
+
+        assertFalse(future.isDone());
+        consumer.accept(mMockSipDelegate, Collections.emptySet());
+        assertTrue(future.get());
+        verify(mMockMessageTracker).openTransport(mMockSipDelegate, Collections.emptySet());
+        verify(mMockDelegateStateTracker).sipDelegateConnected(Collections.emptySet());
+    }
+
+    @SmallTest
+    @Test
+    public void testCreateDelegateTransportDied() throws Exception {
+        DelegateRequest request = getBaseDelegateRequest();
+        SipDelegateController controller = getTestDelegateController(request,
+                Collections.emptySet());
+
+        //Create operation fails
+        doReturn(false).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+        CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+                Collections.emptySet() /*denied tags*/);
+
+        assertFalse(future.get());
+    }
+
+    @SmallTest
+    @Test
+    public void testDestroyDelegate() throws Exception {
+        DelegateRequest request = getBaseDelegateRequest();
+        SipDelegateController controller = getTestDelegateController(request,
+                Collections.emptySet());
+        createSipDelegate(request, controller);
+
+        CompletableFuture<Integer> pendingDestroy = controller.destroy(false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        assertFalse(pendingDestroy.isDone());
+        Consumer<Boolean> pendingClosedConsumer = verifyMessageTrackerCloseGracefully();
+        verify(mMockDelegateStateTracker).sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+
+        // verify we do not call destroy on the delegate until the message tracker releases the
+        // transport.
+        verify(mMockBinderConnection, never()).destroy(anyInt(), any());
+        pendingClosedConsumer.accept(true);
+        Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+        pendingDestroyedConsumer.accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mMockDelegateStateTracker).sipDelegateDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        assertTrue(pendingDestroy.isDone());
+        assertEquals(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+                pendingDestroy.get().intValue());
+    }
+
+    @SmallTest
+    @Test
+    public void testDestroyDelegateForce() throws Exception {
+        DelegateRequest request = getBaseDelegateRequest();
+        SipDelegateController controller = getTestDelegateController(request,
+                Collections.emptySet());
+        createSipDelegate(request, controller);
+
+        CompletableFuture<Integer> pendingDestroy = controller.destroy(true /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        assertFalse(pendingDestroy.isDone());
+        // Do not wait for message transport close in this case.
+        verify(mMockMessageTracker).close(
+                SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
+        verify(mMockDelegateStateTracker, never()).sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+
+        //verify destroy is called
+        Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+        pendingDestroyedConsumer.accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mMockDelegateStateTracker).sipDelegateDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        assertTrue(pendingDestroy.isDone());
+        assertEquals(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+                pendingDestroy.get().intValue());
+    }
+
+    @SmallTest
+    @Test
+    public void testChangeSupportedFeatures() throws Exception {
+        DelegateRequest request = getBaseDelegateRequest();
+        SipDelegateController controller = getTestDelegateController(request,
+                Collections.emptySet());
+        createSipDelegate(request, controller);
+
+        Set<String> newFts = getBaseFTSet();
+        newFts.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+        CompletableFuture<Boolean> pendingChange = controller.changeSupportedFeatureTags(
+                newFts, Collections.emptySet());
+        assertFalse(pendingChange.isDone());
+        // message tracker should close gracefully.
+        Consumer<Boolean> pendingClosedConsumer = verifyMessageTrackerCloseGracefully();
+        verify(mMockDelegateStateTracker).sipDelegateChanging(
+                DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+        verify(mMockBinderConnection, never()).destroy(anyInt(), any());
+        pendingClosedConsumer.accept(true);
+        Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+        pendingDestroyedConsumer.accept(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mMockDelegateStateTracker, never()).sipDelegateDestroyed(anyInt());
+
+        // This will cause any exceptions to be printed if something completed exceptionally.
+        assertNull(pendingChange.getNow(null));
+        BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+                verifyConnectionCreated(2);
+        assertNotNull(consumer);
+        consumer.accept(mMockSipDelegate, Collections.emptySet());
+        assertTrue(pendingChange.get());
+
+        verify(mMockMessageTracker, times(2)).openTransport(mMockSipDelegate,
+                Collections.emptySet());
+        verify(mMockDelegateStateTracker, times(2)).sipDelegateConnected(Collections.emptySet());
+    }
+
+    private void createSipDelegate(DelegateRequest request, SipDelegateController controller)
+            throws Exception {
+        doReturn(true).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+        CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+                Collections.emptySet() /*denied tags*/);
+        BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+                verifyConnectionCreated(1);
+        assertNotNull(consumer);
+        consumer.accept(mMockSipDelegate, Collections.emptySet());
+        assertTrue(future.get());
+    }
+
+    private ArraySet<String> getBaseFTSet() {
+        ArraySet<String> request = new ArraySet<>();
+        request.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        return request;
+    }
+
+    private DelegateRequest getBaseDelegateRequest() {
+        return new DelegateRequest(getBaseFTSet());
+    }
+
+    private SipDelegateController getTestDelegateController(DelegateRequest request,
+            Set<FeatureTagState> deniedSet) {
+        return new SipDelegateController(TEST_SUB_ID, request, "", mExecutorService,
+                mMockMessageTracker, mMockDelegateStateTracker,
+                (a, b, deniedFeatureSet, d, e) ->  {
+                    assertEquals(deniedSet, deniedFeatureSet);
+                    return mMockBinderConnection;
+                });
+    }
+
+    private BiConsumer<ISipDelegate, Set<FeatureTagState>> verifyConnectionCreated(int numTimes) {
+        verify(mMockBinderConnection, times(numTimes)).create(eq(mMockMessageCallback),
+                mCreatedCaptor.capture());
+        return mCreatedCaptor.getValue();
+    }
+
+    private Consumer<Boolean> verifyMessageTrackerCloseGracefully() {
+        verify(mMockMessageTracker).closeGracefully(anyInt(), anyInt(),
+                mBooleanConsumerCaptor.capture());
+        return mBooleanConsumerCaptor.getValue();
+    }
+    private Consumer<Integer> verifyBinderConnectionDestroy() {
+        verify(mMockBinderConnection).destroy(anyInt(), mIntegerConsumerCaptor.capture());
+        return mIntegerConsumerCaptor.getValue();
+    }
+
+}
diff --git a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
new file mode 100644
index 0000000..fa27775
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
@@ -0,0 +1,913 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.role.RoleManager;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+import com.android.ims.RcsFeatureManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@RunWith(AndroidJUnit4.class)
+public class SipTransportControllerTest extends TelephonyTestBase {
+    private static final int TEST_SUB_ID = 1;
+    private static final String TEST_PACKAGE_NAME = "com.test_pkg";
+    private static final String TEST_PACKAGE_NAME_2 = "com.test_pkg2";
+    private static final int TIMEOUT_MS = 200;
+    private static final int THROTTLE_MS = 50;
+
+    private class SipDelegateControllerContainer {
+        public final int subId;
+        public final String packageName;
+        public final DelegateRequest delegateRequest;
+        public final SipDelegateController delegateController;
+        public final ISipDelegate mMockDelegate;
+        public final IBinder mMockDelegateBinder;
+
+        SipDelegateControllerContainer(int id, String name, DelegateRequest request) {
+            delegateController = mock(SipDelegateController.class);
+            mMockDelegate = mock(ISipDelegate.class);
+            mMockDelegateBinder = mock(IBinder.class);
+            doReturn(mMockDelegateBinder).when(mMockDelegate).asBinder();
+            doReturn(name).when(delegateController).getPackageName();
+            doReturn(request).when(delegateController).getInitialRequest();
+            doReturn(mMockDelegate).when(delegateController).getSipDelegateInterface();
+            subId = id;
+            packageName = name;
+            delegateRequest = request;
+        }
+    }
+
+    @Mock private RcsFeatureManager mRcsManager;
+    @Mock private ISipTransport mSipTransport;
+    @Mock private IImsRegistration mImsRegistration;
+    @Mock private ISipDelegateConnectionStateCallback mMockStateCallback;
+    @Mock private ISipDelegateMessageCallback mMockMessageCallback;
+    @Mock private SipTransportController.SipDelegateControllerFactory
+            mMockDelegateControllerFactory;
+    @Mock private SipTransportController.RoleManagerAdapter mMockRoleManager;
+
+    private ScheduledExecutorService mExecutorService = null;
+    private final ArrayList<SipDelegateControllerContainer> mMockControllers = new ArrayList<>();
+    private final ArrayList<String> mSmsPackageName = new ArrayList<>(1);
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        doReturn(mSmsPackageName).when(mMockRoleManager).getRoleHolders(RoleManager.ROLE_SMS);
+        doReturn(mImsRegistration).when(mRcsManager).getImsRegistration();
+        mSmsPackageName.add(TEST_PACKAGE_NAME);
+        doAnswer(invocation -> {
+            Integer subId = invocation.getArgument(0);
+            String packageName = invocation.getArgument(2);
+            DelegateRequest request = invocation.getArgument(1);
+            SipDelegateController c = getMockDelegateController(subId, packageName, request);
+            assertNotNull("create called with no corresponding controller set up", c);
+            return c;
+        }).when(mMockDelegateControllerFactory).create(anyInt(), any(), anyString(), any(), any(),
+                any(), any(), any());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        boolean isShutdown = mExecutorService == null || mExecutorService.isShutdown();
+        if (!isShutdown) {
+            mExecutorService.shutdownNow();
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedRcsNotConnected() {
+        SipTransportController controller = createController(new TestExecutorService());
+        try {
+            controller.isSupported(TEST_SUB_ID);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedInvalidSubId() {
+        SipTransportController controller = createController(new TestExecutorService());
+        try {
+            controller.isSupported(TEST_SUB_ID + 1);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedSubIdChanged() {
+        SipTransportController controller = createController(new TestExecutorService());
+        controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+        try {
+            controller.isSupported(TEST_SUB_ID);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedSipTransportAvailableRcsConnected() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        try {
+            assertTrue(controller.isSupported(TEST_SUB_ID));
+        } catch (ImsException e) {
+            fail();
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedSipTransportNotAvailableRcsDisconnected() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        controller.onRcsDisconnected();
+        try {
+            controller.isSupported(TEST_SUB_ID);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedSipTransportNotAvailableRcsConnected() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doReturn(null).when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        try {
+            assertFalse(controller.isSupported(TEST_SUB_ID));
+        } catch (ImsException e) {
+            fail();
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void isSupportedImsServiceNotAvailableRcsConnected() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE))
+                .when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        try {
+            controller.isSupported(TEST_SUB_ID);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void createImsServiceAvailableSubIdIncorrect() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        try {
+            controller.createSipDelegate(TEST_SUB_ID + 1,
+                    new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+                    mMockStateCallback, mMockMessageCallback);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void createImsServiceDoesntSupportTransport() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doReturn(null).when(mRcsManager).getSipTransport();
+        controller.onRcsConnected(mRcsManager);
+        try {
+            controller.createSipDelegate(TEST_SUB_ID,
+                    new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+                    mMockStateCallback, mMockMessageCallback);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void createImsServiceNotAvailable() throws Exception {
+        SipTransportController controller = createController(new TestExecutorService());
+        doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE))
+                .when(mRcsManager).getSipTransport();
+        // No RCS connected message
+        try {
+            controller.createSipDelegate(TEST_SUB_ID,
+                    new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+                    mMockStateCallback, mMockMessageCallback);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+        }
+    }
+
+    @SmallTest
+    @Test
+    public void basicCreate() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        DelegateRequest r = getBaseDelegateRequest();
+
+        SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME, r);
+        createDelegateAndVerify(controller, c, r, r.getFeatureTags(), Collections.emptySet(),
+                TEST_PACKAGE_NAME);
+        verifyDelegateRegistrationChangedEvent(1 /*times*/, 0 /*waitMs*/);
+        triggerFullNetworkRegistrationAndVerify(controller, c);
+    }
+
+    @SmallTest
+    @Test
+    public void basicCreateDestroy() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        DelegateRequest r = getBaseDelegateRequest();
+        SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME, r);
+        createDelegateAndVerify(controller, c, r, r.getFeatureTags(), Collections.emptySet(),
+                TEST_PACKAGE_NAME);
+        verifyDelegateRegistrationChangedEvent(1, 0 /*throttle*/);
+
+        destroyDelegateAndVerify(controller, c, false,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verifyDelegateRegistrationChangedEvent(2 /*times*/, 0 /*waitMs*/);
+        triggerFullNetworkRegistrationAndVerifyNever(controller, c);
+    }
+
+    @SmallTest
+    @Test
+    public void testCreateButNotInRole() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        DelegateRequest r = getBaseDelegateRequest();
+        Set<FeatureTagState> getDeniedTags = getDeniedTagsForReason(r.getFeatureTags(),
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+
+        // Try to create a SipDelegate for a package that is not the default sms role.
+        SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME_2, r);
+        createDelegateAndVerify(controller, c, r, Collections.emptySet(), getDeniedTags,
+                TEST_PACKAGE_NAME_2);
+    }
+
+    @SmallTest
+    @Test
+    public void createTwoAndDenyOverlappingTags() throws Exception {
+        SipTransportController controller = setupLiveTransportController(0 /*reeval*/,
+                THROTTLE_MS);
+
+        // First delegate requests RCS message + File transfer
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+        // there is a delay in the indication to update reg, so it should not happen yet.
+        verifyNoDelegateRegistrationChangedEvent();
+
+        // First delegate requests RCS message + Group RCS message. For this delegate, single RCS
+        // message should be denied.
+        ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+        DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+        Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig(
+                secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
+                firstDelegate);
+        SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                secondDelegateRequest);
+        createDelegateAndVerify(controller, c2, secondDelegateRequest, grantedAndDenied.first,
+                grantedAndDenied.second, TEST_PACKAGE_NAME, 1);
+        // a reg changed event should happen after wait.
+        verifyDelegateRegistrationChangedEvent(1, 2 * THROTTLE_MS);
+    }
+
+    @SmallTest
+    @Test
+    public void createTwoAndTriggerRoleChange() throws Exception {
+        SipTransportController controller = setupLiveTransportController(0 /*reeval*/, THROTTLE_MS);
+
+        DelegateRequest firstDelegateRequest = getBaseDelegateRequest();
+        Set<FeatureTagState> firstDeniedTags = getDeniedTagsForReason(
+                firstDelegateRequest.getFeatureTags(),
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest,
+                firstDelegateRequest.getFeatureTags(), Collections.emptySet(), TEST_PACKAGE_NAME);
+        verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS);
+
+        DelegateRequest secondDelegateRequest = getBaseDelegateRequest();
+        Set<FeatureTagState> secondDeniedTags = getDeniedTagsForReason(
+                secondDelegateRequest.getFeatureTags(),
+                SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+        // Try to create a SipDelegate for a package that is not the default sms role.
+        SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME_2,
+                secondDelegateRequest);
+        createDelegateAndVerify(controller, c2, secondDelegateRequest, Collections.emptySet(),
+                secondDeniedTags, TEST_PACKAGE_NAME_2, 1);
+
+        // now swap the SMS role.
+        CompletableFuture<Boolean> pendingC1Change = setChangeSupportedFeatureTagsFuture(c1,
+                Collections.emptySet(), firstDeniedTags);
+        CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture(c2,
+                secondDelegateRequest.getFeatureTags(), Collections.emptySet());
+        setSmsRoleAndEvaluate(controller, TEST_PACKAGE_NAME_2);
+        // swapping roles should trigger a deregistration event on the ImsService side.
+        verifyDelegateDeregistrationEvent();
+        // there should also not be any new registration changed events
+        verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS);
+        // trigger completion stage to run
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(c1).changeSupportedFeatureTags(Collections.emptySet(), firstDeniedTags);
+        // we should not get a change for c2 until pendingC1Change completes.
+        verify(c2, never()).changeSupportedFeatureTags(secondDelegateRequest.getFeatureTags(),
+                Collections.emptySet());
+        // ensure we are not blocking executor here
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        completePendingChange(pendingC1Change, true);
+        // trigger completion stage to run
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(c2).changeSupportedFeatureTags(secondDelegateRequest.getFeatureTags(),
+                Collections.emptySet());
+        // ensure we are not blocking executor here
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        completePendingChange(pendingC2Change, true);
+        // verify we now get a second registration changed event
+        verifyDelegateRegistrationChangedEvent(2 /*times*/, THROTTLE_MS);
+    }
+
+    @SmallTest
+    @Test
+    public void createTwoAndDestroyOlder() throws Exception {
+        SipTransportController controller = setupLiveTransportController(0 /*reeval*/, THROTTLE_MS);
+
+        // First delegate requests RCS message + File transfer
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+        verifyNoDelegateRegistrationChangedEvent();
+
+        // First delegate requests RCS message + Group RCS message. For this delegate, single RCS
+        // message should be denied.
+        ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+        DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+        Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig(
+                secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
+                firstDelegate);
+        SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                secondDelegateRequest);
+        createDelegateAndVerify(controller, c2, secondDelegateRequest, grantedAndDenied.first,
+                grantedAndDenied.second, TEST_PACKAGE_NAME, 1);
+        verifyNoDelegateRegistrationChangedEvent();
+
+        // Destroy the firstDelegate, which should now cause all previously denied tags to be
+        // granted to the new delegate.
+        CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture(c2,
+                secondDelegate, Collections.emptySet());
+        destroyDelegateAndVerify(controller, c1, false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        // wait for create to be processed.
+        assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+        verify(c2).changeSupportedFeatureTags(secondDelegate, Collections.emptySet());
+        completePendingChange(pendingC2Change, true);
+
+        verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS);
+    }
+
+    @SmallTest
+    @Test
+    public void testThrottling() throws Exception {
+        SipTransportController controller = setupLiveTransportController(THROTTLE_MS, THROTTLE_MS);
+
+        // First delegate requests RCS message + File transfer
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1,
+                firstDelegateRequest, firstDelegate, Collections.emptySet(), TEST_PACKAGE_NAME);
+
+        // Request RCS message + group RCS Message. For this delegate, single RCS message should be
+        // denied.
+        ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+        DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+        Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC2 =
+                getAllowedAndDeniedTagsForConfig(secondDelegateRequest,
+                        SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate);
+        SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                secondDelegateRequest);
+        CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2,
+                secondDelegateRequest, grantedAndDeniedC2.first, grantedAndDeniedC2.second,
+                TEST_PACKAGE_NAME);
+
+        // Request group RCS message + file transfer. All should be denied at first
+        ArraySet<String> thirdDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        thirdDelegate.remove(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        DelegateRequest thirdDelegateRequest = new DelegateRequest(thirdDelegate);
+        Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC3 =
+                getAllowedAndDeniedTagsForConfig(thirdDelegateRequest,
+                        SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate,
+                        grantedAndDeniedC2.first);
+        SipDelegateController c3 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                thirdDelegateRequest);
+        CompletableFuture<Boolean> pendingC3Change = createDelegate(controller, c3,
+                thirdDelegateRequest, grantedAndDeniedC3.first, grantedAndDeniedC3.second,
+                TEST_PACKAGE_NAME);
+
+        verifyNoDelegateRegistrationChangedEvent();
+        assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+        verifyDelegateChanged(c1, pendingC1Change, firstDelegate, Collections.emptySet(), 0);
+        verifyDelegateChanged(c2, pendingC2Change, grantedAndDeniedC2.first,
+                grantedAndDeniedC2.second, 0);
+        verifyDelegateChanged(c3, pendingC3Change, grantedAndDeniedC3.first,
+                grantedAndDeniedC3.second, 0);
+        verifyDelegateRegistrationChangedEvent(1, 2 * THROTTLE_MS);
+
+        // Destroy the first and second controller in quick succession, this should only generate
+        // one reevaluate for the third controller.
+        CompletableFuture<Boolean> pendingChangeC3 = setChangeSupportedFeatureTagsFuture(
+                c3, thirdDelegate, Collections.emptySet());
+        CompletableFuture<Integer> pendingDestroyC1 = destroyDelegate(controller, c1,
+                false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        CompletableFuture<Integer> pendingDestroyC2 = destroyDelegate(controller, c2,
+                false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+        verifyDestroyDelegate(controller, c1, pendingDestroyC1, false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verifyDestroyDelegate(controller, c2, pendingDestroyC2, false /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+        // All requested features should now be granted
+        completePendingChange(pendingChangeC3, true);
+        verify(c3).changeSupportedFeatureTags(thirdDelegate, Collections.emptySet());
+        // In total reeval should have only been called twice.
+        verify(c3, times(2)).changeSupportedFeatureTags(any(), any());
+        verifyDelegateRegistrationChangedEvent(2 /*times*/, 2 * THROTTLE_MS);
+    }
+
+    @SmallTest
+    @Test
+    public void testSubIdChangeDestroyTriggered() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+        verifyDelegateRegistrationChangedEvent(1 /*times*/, 0 /*waitMs*/);
+
+        CompletableFuture<Integer> pendingDestroy =  setDestroyFuture(c1, true,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        verifyDelegateRegistrationChangedEvent(2 /*times*/, 0 /*waitMs*/);
+    }
+
+    @SmallTest
+    @Test
+    public void testRcsManagerGoneDestroyTriggered() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+
+        CompletableFuture<Integer> pendingDestroy =  setDestroyFuture(c1, true,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+        controller.onRcsDisconnected();
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+        verifyDelegateRegistrationChangedEvent(1, 0 /*waitMs*/);
+    }
+
+    @SmallTest
+    @Test
+    public void testDestroyTriggered() throws Exception {
+        SipTransportController controller = setupLiveTransportController();
+
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+
+        CompletableFuture<Integer> pendingDestroy =  setDestroyFuture(c1, true,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        controller.onDestroy();
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verifyDelegateDeregistrationEvent();
+        // verify change was called.
+        verify(c1).destroy(true /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        // ensure thread is not blocked while waiting for pending complete.
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        completePendingDestroy(pendingDestroy,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+    }
+
+    @SmallTest
+    @Test
+    public void testTimingSubIdChangedAndCreateNewSubId() throws Exception {
+        SipTransportController controller = setupLiveTransportController(THROTTLE_MS, 0);
+
+        ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+        DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+        SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+                firstDelegateRequest);
+        CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1,
+                firstDelegateRequest, firstDelegate, Collections.emptySet(), TEST_PACKAGE_NAME);
+        assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+        verifyDelegateChanged(c1, pendingC1Change, firstDelegate, Collections.emptySet(), 0);
+
+
+        CompletableFuture<Integer> pendingDestroy =  setDestroyFuture(c1, true,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        // triggers reeval now.
+        controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+
+        // mock a second delegate with the new subId associated with the slot.
+        ArraySet<String> secondDelegate = new ArraySet<>();
+        secondDelegate.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        secondDelegate.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+        DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+        SipDelegateController c2 = injectMockDelegateController(TEST_SUB_ID + 1,
+                TEST_PACKAGE_NAME, secondDelegateRequest);
+        CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2,
+                TEST_SUB_ID + 1, secondDelegateRequest, secondDelegate,
+                Collections.emptySet(), TEST_PACKAGE_NAME);
+        assertTrue(scheduleDelayedWait(THROTTLE_MS));
+
+        //trigger destroyed event
+        verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+        assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+        verifyDelegateChanged(c2, pendingC2Change, secondDelegate, Collections.emptySet(), 0);
+    }
+
+    @SafeVarargs
+    private final Pair<Set<String>, Set<FeatureTagState>> getAllowedAndDeniedTagsForConfig(
+            DelegateRequest r, int denyReason, Set<String>... previousRequestedTagSets) {
+        ArraySet<String> rejectedTags = new ArraySet<>(r.getFeatureTags());
+        ArraySet<String> grantedTags = new ArraySet<>(r.getFeatureTags());
+        Set<String> previousRequestedTags = new ArraySet<>();
+        for (Set<String> s : previousRequestedTagSets) {
+            previousRequestedTags.addAll(s);
+        }
+        rejectedTags.retainAll(previousRequestedTags);
+        grantedTags.removeAll(previousRequestedTags);
+        Set<FeatureTagState> deniedTags = getDeniedTagsForReason(rejectedTags, denyReason);
+        return new Pair<>(grantedTags, deniedTags);
+    }
+
+    private void completePendingChange(CompletableFuture<Boolean> change, boolean result) {
+        mExecutorService.execute(() -> change.complete(result));
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+    }
+
+    private void completePendingDestroy(CompletableFuture<Integer> destroy, int result) {
+        mExecutorService.execute(() -> destroy.complete(result));
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+    }
+
+    private SipTransportController setupLiveTransportController() throws Exception {
+        return setupLiveTransportController(0 /*throttleMs*/, 0 /*regDelayMs*/);
+    }
+
+    private SipTransportController setupLiveTransportController(int throttleMs, int regDelayMs)
+            throws Exception {
+        mExecutorService = Executors.newSingleThreadScheduledExecutor();
+        SipTransportController controller = createControllerAndThrottle(mExecutorService,
+                throttleMs, regDelayMs);
+        doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+        controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID);
+        controller.onRcsConnected(mRcsManager);
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        return controller;
+    }
+
+    private void createDelegateAndVerify(SipTransportController controller,
+            SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+            Set<FeatureTagState> deniedTags, String packageName,
+            int numPreviousChanges) throws ImsException {
+
+        CompletableFuture<Boolean> pendingChange = createDelegate(controller, delegateController, r,
+                allowedTags, deniedTags, packageName);
+        verifyDelegateChanged(delegateController, pendingChange, allowedTags, deniedTags,
+                numPreviousChanges);
+    }
+
+    private void createDelegateAndVerify(SipTransportController controller,
+            SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+            Set<FeatureTagState> deniedTags, String packageName) throws ImsException {
+        createDelegateAndVerify(controller, delegateController, r, allowedTags, deniedTags,
+                packageName, 0);
+    }
+
+    private CompletableFuture<Boolean> createDelegate(SipTransportController controller,
+            SipDelegateController delegateController, int subId, DelegateRequest r,
+            Set<String> allowedTags, Set<FeatureTagState> deniedTags, String packageName) {
+        CompletableFuture<Boolean> pendingChange = setChangeSupportedFeatureTagsFuture(
+                delegateController, allowedTags, deniedTags);
+        try {
+            controller.createSipDelegate(subId, r, packageName, mMockStateCallback,
+                    mMockMessageCallback);
+        } catch (ImsException e) {
+            fail("ImsException thrown:" + e);
+        }
+        // move to internal & schedule eval
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        // reeval
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        return pendingChange;
+    }
+
+    private CompletableFuture<Boolean> createDelegate(SipTransportController controller,
+            SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+            Set<FeatureTagState> deniedTags, String packageName) throws ImsException {
+        return createDelegate(controller, delegateController, TEST_SUB_ID, r, allowedTags,
+                deniedTags, packageName);
+    }
+
+    private void verifyDelegateChanged(SipDelegateController delegateController,
+            CompletableFuture<Boolean> pendingChange, Set<String> allowedTags,
+            Set<FeatureTagState> deniedTags, int numPreviousChangeStages) {
+        // empty the queue of pending changeSupportedFeatureTags before running the one we are
+        // interested in, since the reevaluate waits for one stage to complete before moving to the
+        // next.
+        for (int i = 0; i < numPreviousChangeStages + 1; i++) {
+            assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+        }
+        // verify change was called.
+        verify(delegateController).changeSupportedFeatureTags(allowedTags, deniedTags);
+        // ensure thread is not blocked while waiting for pending complete.
+        assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+        completePendingChange(pendingChange, true);
+        // process pending change.
+        assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+    }
+
+    private void destroyDelegateAndVerify(SipTransportController controller,
+            SipDelegateController delegateController, boolean force, int reason) {
+        CompletableFuture<Integer> pendingDestroy =  destroyDelegate(controller, delegateController,
+                force, reason);
+        verifyDestroyDelegate(controller, delegateController, pendingDestroy, force, reason);
+    }
+
+    private CompletableFuture<Integer> destroyDelegate(SipTransportController controller,
+            SipDelegateController delegateController, boolean force, int reason) {
+        CompletableFuture<Integer> pendingDestroy =  setDestroyFuture(delegateController, force,
+                reason);
+        controller.destroySipDelegate(TEST_SUB_ID, delegateController.getSipDelegateInterface(),
+                reason);
+        // move to internal & schedule eval
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        // reeval
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        return pendingDestroy;
+    }
+
+    private void verifyDestroyDelegate(SipTransportController controller,
+            SipDelegateController delegateController, CompletableFuture<Integer> pendingDestroy,
+            boolean force, int reason) {
+        // verify destroy was called.
+        verify(delegateController).destroy(force, reason);
+        // ensure thread is not blocked while waiting for pending complete.
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        completePendingDestroy(pendingDestroy, reason);
+    }
+
+    private void triggerFullNetworkRegistrationAndVerify(SipTransportController controller,
+            SipDelegateController delegateController) {
+        controller.triggerFullNetworkRegistration(TEST_SUB_ID,
+                delegateController.getSipDelegateInterface(), 403, "forbidden");
+        // move to internal & trigger event
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(delegateController).triggerFullNetworkRegistration(403, "forbidden");
+    }
+
+    private void triggerFullNetworkRegistrationAndVerifyNever(SipTransportController controller,
+            SipDelegateController delegateController) {
+        controller.triggerFullNetworkRegistration(TEST_SUB_ID,
+                delegateController.getSipDelegateInterface(), 403, "forbidden");
+        // move to internal & potentially trigger event
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(delegateController, never()).triggerFullNetworkRegistration(anyInt(), anyString());
+    }
+
+    private DelegateRequest getBaseDelegateRequest() {
+        Set<String> featureTags = new ArraySet<>();
+        featureTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        featureTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+        featureTags.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+        return new DelegateRequest(featureTags);
+    }
+
+    private Set<FeatureTagState> getBaseDeniedSet() {
+        Set<FeatureTagState> deniedTags = new ArraySet<>();
+        deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+                SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+        return deniedTags;
+    }
+
+    private Set<FeatureTagState> getDeniedTagsForReason(Set<String> deniedTags, int reason) {
+        return deniedTags.stream().map(t -> new FeatureTagState(t, reason))
+                .collect(Collectors.toSet());
+    }
+
+    private SipDelegateController injectMockDelegateController(String packageName,
+            DelegateRequest r) {
+        return injectMockDelegateController(TEST_SUB_ID, packageName, r);
+    }
+
+    private SipDelegateController injectMockDelegateController(int subId, String packageName,
+            DelegateRequest r) {
+        SipDelegateControllerContainer c = new SipDelegateControllerContainer(subId,
+                packageName, r);
+        mMockControllers.add(c);
+        return c.delegateController;
+    }
+
+    private SipDelegateController getMockDelegateController(int subId, String packageName,
+            DelegateRequest r) {
+        return mMockControllers.stream()
+                .filter(c -> c.subId == subId && c.packageName.equals(packageName)
+                        && c.delegateRequest.equals(r))
+                .map(c -> c.delegateController).findFirst().orElse(null);
+    }
+
+    private CompletableFuture<Boolean> setChangeSupportedFeatureTagsFuture(SipDelegateController c,
+            Set<String> supportedSet, Set<FeatureTagState> deniedSet) {
+        CompletableFuture<Boolean> result = new CompletableFuture<>();
+        doReturn(result).when(c).changeSupportedFeatureTags(eq(supportedSet), eq(deniedSet));
+        return result;
+    }
+
+    private CompletableFuture<Integer> setDestroyFuture(SipDelegateController c, boolean force,
+            int destroyReason) {
+        CompletableFuture<Integer> result = new CompletableFuture<>();
+        doReturn(result).when(c).destroy(force, destroyReason);
+        return result;
+    }
+
+    private void setSmsRoleAndEvaluate(SipTransportController c, String packageName) {
+        verify(mMockRoleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any());
+        mSmsPackageName.clear();
+        mSmsPackageName.add(packageName);
+        c.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.SYSTEM);
+        // finish internal throttled re-evaluate
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+    }
+
+    private void verifyNoDelegateRegistrationChangedEvent() throws Exception {
+        // event is scheduled and then executed.
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(mImsRegistration, never()).triggerUpdateSipDelegateRegistration();
+    }
+
+    private void verifyDelegateRegistrationChangedEvent(int times, int waitMs)
+            throws Exception {
+        // event is scheduled and then executed.
+        assertTrue(scheduleDelayedWait(waitMs));
+        waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+        verify(mImsRegistration, times(times)).triggerUpdateSipDelegateRegistration();
+    }
+
+
+    private void verifyDelegateDeregistrationEvent() throws Exception {
+        verify(mImsRegistration).triggerSipDelegateDeregistration();
+    }
+
+    private SipTransportController createController(ScheduledExecutorService e) {
+        return createControllerAndThrottle(e, 0 /*throttleMs*/, 0 /*regDelayMs*/);
+    }
+
+    private SipTransportController createControllerAndThrottle(ScheduledExecutorService e,
+            int throttleMs, int regDelayMs) {
+        return new SipTransportController(mContext, 0 /*slotId*/, TEST_SUB_ID,
+                mMockDelegateControllerFactory, mMockRoleManager,
+                // Remove delays for testing.
+                new SipTransportController.TimerAdapter() {
+                    @Override
+                    public int getReevaluateThrottleTimerMilliseconds() {
+                        return throttleMs;
+                    }
+
+                    @Override
+                    public int getUpdateRegistrationDelayMilliseconds() {
+                        return regDelayMs;
+                    }
+                }, e);
+    }
+
+    private boolean scheduleDelayedWait(long timeMs) {
+        CountDownLatch l = new CountDownLatch(1);
+        mExecutorService.schedule(l::countDown, timeMs, TimeUnit.MILLISECONDS);
+        while (l.getCount() > 0) {
+            try {
+                return l.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                // try again
+            }
+        }
+        return true;
+    }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index cfb68b7..c367af3 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -50,8 +50,11 @@
 
     @Captor ArgumentCaptor<BroadcastReceiver> mReceiverCaptor;
     @Mock TelephonyRcsService.FeatureFactory mFeatureFactory;
-    @Mock UserCapabilityExchangeImpl mMockUceSlot0;
-    @Mock UserCapabilityExchangeImpl mMockUceSlot1;
+    @Mock TelephonyRcsService.ResourceProxy mResourceProxy;
+    @Mock UceControllerManager mMockUceSlot0;
+    @Mock UceControllerManager mMockUceSlot1;
+    @Mock SipTransportController mMockSipTransportSlot0;
+    @Mock SipTransportController mMockSipTransportSlot1;
     @Mock RcsFeatureController.RegistrationHelperFactory mRegistrationFactory;
     @Mock RcsFeatureController.FeatureConnectorFactory<RcsFeatureManager> mFeatureConnectorFactory;
     @Mock FeatureConnector<RcsFeatureManager> mFeatureConnector;
@@ -68,10 +71,15 @@
         mFeatureControllerSlot1 = createFeatureController(1 /*slotId*/);
         doReturn(mFeatureControllerSlot0).when(mFeatureFactory).createController(any(), eq(0));
         doReturn(mFeatureControllerSlot1).when(mFeatureFactory).createController(any(), eq(1));
-        doReturn(mMockUceSlot0).when(mFeatureFactory).createUserCapabilityExchange(any(), eq(0),
+        doReturn(mMockUceSlot0).when(mFeatureFactory).createUceControllerManager(any(), eq(0),
                 anyInt());
-        doReturn(mMockUceSlot1).when(mFeatureFactory).createUserCapabilityExchange(any(), eq(1),
+        doReturn(mMockUceSlot1).when(mFeatureFactory).createUceControllerManager(any(), eq(1),
                 anyInt());
+        doReturn(mMockSipTransportSlot0).when(mFeatureFactory).createSipTransportController(any(),
+                eq(0), anyInt());
+        doReturn(mMockSipTransportSlot1).when(mFeatureFactory).createSipTransportController(any(),
+                eq(1), anyInt());
+        doReturn(true).when(mResourceProxy).getDeviceUceEnabled(any());
         //set up default slot-> sub ID mappings.
         setSlotToSubIdMapping(0 /*slotId*/, 1/*subId*/);
         setSlotToSubIdMapping(1 /*slotId*/, 2/*subId*/);
@@ -83,18 +91,21 @@
     }
 
     @Test
-    public void testUserCapabilityExchangePresenceConnected() {
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+    public void testUceControllerPresenceConnected() {
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
         createRcsService(1 /*numSlots*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
     }
 
     @Test
-    public void testUserCapabilityExchangeOptionsConnected() {
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, true /*isEnabled*/);
+    public void testUceControllerOptionsConnected() {
+        setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL,
+                true /*isEnabled*/);
         createRcsService(1 /*numSlots*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
     }
 
@@ -103,18 +114,67 @@
         createRcsService(1 /*numSlots*/);
         // No carrier config set for UCE.
         verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, never()).connect();
     }
 
     @Test
+    public void testSipTransportConnected() {
+        createRcsService(1 /*numSlots*/);
+        verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot0, never()).connect();
+
+
+        // Send carrier config update for each slot.
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+                true /*isEnabled*/);
+        sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+        verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot0).connect();
+        verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+    }
+
+    @Test
+    public void testSipTransportConnectedOneSlot() {
+        createRcsService(2 /*numSlots*/);
+        verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot0, never()).connect();
+        verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot1,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot1, never()).connect();
+
+
+        // Send carrier config update for slot 0 only
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+                true /*isEnabled*/);
+        setCarrierConfig(2 /*subId*/,
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+                false /*isEnabled*/);
+        sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+        sendCarrierConfigChanged(1 /*slotId*/, 2 /*subId*/);
+        verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot1, never()).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot0).connect();
+        verify(mFeatureControllerSlot1, never()).connect();
+        verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+        verify(mFeatureControllerSlot1, never()).updateAssociatedSubscription(1);
+    }
+
+    @Test
     public void testNoFeaturesEnabledCarrierConfigChanged() {
         createRcsService(1 /*numSlots*/);
         // No carrier config set for UCE.
 
         sendCarrierConfigChanged(0, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
         verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, never()).connect();
         verify(mFeatureControllerSlot0, never()).updateAssociatedSubscription(anyInt());
     }
@@ -122,27 +182,32 @@
 
     @Test
     public void testSlotUpdates() {
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
+        setCarrierConfig(2 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
         TelephonyRcsService service = createRcsService(1 /*numSlots*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
 
         // there should be no changes if the new num slots = old num
         service.updateFeatureControllerSize(1 /*newNumSlots*/);
         verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, times(1)).connect();
 
         // Add a new slot.
         verify(mFeatureControllerSlot1, never()).addFeature(mMockUceSlot1,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot1, never()).connect();
         service.updateFeatureControllerSize(2 /*newNumSlots*/);
         // This shouldn't have changed for slot 0.
         verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, times(1)).connect();
-        verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class);
         verify(mFeatureControllerSlot1, times(1)).connect();
 
         // Remove a slot.
@@ -151,10 +216,10 @@
         service.updateFeatureControllerSize(1 /*newNumSlots*/);
         // addFeature/connect shouldn't have been called again
         verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, times(1)).connect();
         verify(mFeatureControllerSlot1, times(1)).addFeature(mMockUceSlot1,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot1, times(1)).connect();
         // Verify destroy is only called for slot 1.
         verify(mFeatureControllerSlot0, never()).destroy();
@@ -163,10 +228,15 @@
 
     @Test
     public void testCarrierConfigUpdate() {
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
+        setCarrierConfig(2 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
         createRcsService(2 /*numSlots*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
-        verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
+        verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
         verify(mFeatureControllerSlot1).connect();
 
@@ -182,16 +252,40 @@
 
     @Test
     public void testCarrierConfigUpdateUceToNoUce() {
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
         createRcsService(1 /*numSlots*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
 
 
         // Send carrier config update for each slot.
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false /*isEnabled*/);
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                false /*isEnabled*/);
         sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
-        verify(mFeatureControllerSlot0).removeFeature(UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).removeFeature(UceControllerManager.class);
+        verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+    }
+
+    @Test
+    public void testCarrierConfigUpdateTransportToNoTransport() {
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+                true /*isEnabled*/);
+        createRcsService(1 /*numSlots*/);
+        verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+                SipTransportController.class);
+        verify(mFeatureControllerSlot0).connect();
+
+
+        // Send carrier config update for each slot.
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+                false /*isEnabled*/);
+        sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+        verify(mFeatureControllerSlot0).removeFeature(SipTransportController.class);
         verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
     }
 
@@ -199,14 +293,16 @@
     public void testCarrierConfigUpdateNoUceToUce() {
         createRcsService(1 /*numSlots*/);
         verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
-                UserCapabilityExchangeImpl.class);
+                UceControllerManager.class);
         verify(mFeatureControllerSlot0, never()).connect();
 
 
         // Send carrier config update for each slot.
-        setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+        setCarrierConfig(1 /*subId*/,
+                CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL,
+                true /*isEnabled*/);
         sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
-        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+        verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
         verify(mFeatureControllerSlot0).connect();
         verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
     }
@@ -218,8 +314,8 @@
         mReceiverCaptor.getValue().onReceive(mContext, intent);
     }
 
-    private void setCarrierConfig(String key, boolean value) {
-        PersistableBundle bundle = mContext.getCarrierConfig();
+    private void setCarrierConfig(int subId, String key, boolean value) {
+        PersistableBundle bundle = mContext.getCarrierConfig(subId);
         bundle.putBoolean(key, value);
     }
 
@@ -231,7 +327,7 @@
     }
 
     private TelephonyRcsService createRcsService(int numSlots) {
-        TelephonyRcsService service = new TelephonyRcsService(mContext, numSlots);
+        TelephonyRcsService service = new TelephonyRcsService(mContext, numSlots, mResourceProxy);
         service.setFeatureFactory(mFeatureFactory);
         service.initialize();
         verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
diff --git a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
new file mode 100644
index 0000000..4148d13
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.net.Uri;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+import com.android.ims.RcsFeatureManager;
+import com.android.ims.rcs.uce.UceController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+@RunWith(AndroidJUnit4.class)
+public class UceControllerManagerTest extends TelephonyTestBase {
+
+    @Mock private UceController mUceController;
+    @Mock private RcsFeatureManager mRcsFeatureManager;
+
+    private final ExecutorService mExecutorService = new TestExecutorService();
+
+    private int mSlotId = 1;
+    private int mSubId = 1;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        doReturn(mSubId).when(mUceController).getSubId();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @Test
+    public void testRcsConnected() throws Exception {
+        UceControllerManager controllerManager = getUceControllerManager();
+
+        controllerManager.onRcsConnected(mRcsFeatureManager);
+
+        verify(mUceController).onRcsConnected(mRcsFeatureManager);
+    }
+
+    @Test
+    public void testRcsDisconnected() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+
+        uceCtrlManager.onRcsDisconnected();
+
+        verify(mUceController).onRcsDisconnected();
+    }
+
+    @Test
+    public void testDestroy() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+
+        uceCtrlManager.onDestroy();
+
+        verify(mUceController).onDestroy();
+    }
+
+    @Test
+    public void testSubscriptionUpdated() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+
+        uceCtrlManager.onAssociatedSubscriptionUpdated(mSubId);
+
+        verify(mUceController).onDestroy();
+    }
+
+    @Test
+    public void testRequestCapabilitiesWithRcsUnavailable() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(true).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsDisconnected();
+
+        try {
+            List<Uri> contacts = Arrays.asList(Uri.fromParts("sip", "00000", null));
+            IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+            uceCtrlManager.requestCapabilities(contacts, callback);
+
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testRequestCapabilitiesWithRcsConnected() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(false).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+        try {
+            List<Uri> contacts = Arrays.asList(Uri.fromParts("sip", "00000", null));
+            IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+            uceCtrlManager.requestCapabilities(contacts, callback);
+
+            verify(mUceController).requestCapabilities(contacts, callback);
+        } catch (ImsException e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void testRequestNetworkAvailability() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(false).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+        Uri contact = Uri.fromParts("sip", "00000", null);
+        IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+        uceCtrlManager.requestNetworkAvailability(contact, callback);
+
+        verify(mUceController).requestAvailability(contact, callback);
+    }
+
+    @Test
+    public void testRequestNetworkAvailabilityWithRcsUnavailable() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(true).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsDisconnected();
+
+        try {
+            Uri contact = Uri.fromParts("sip", "00000", null);
+            IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+            uceCtrlManager.requestNetworkAvailability(contact, callback);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testGetPublishState() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(false).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+        uceCtrlManager.getUcePublishState();
+
+        verify(mUceController).getUcePublishState();
+    }
+
+    @Test
+    public void testGetPublishStateWithRcsUnavailable() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(true).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsDisconnected();
+
+        try {
+            uceCtrlManager.getUcePublishState();
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testRegisterPublishStateCallback() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+
+        uceCtrlManager.registerPublishStateCallback(callback);
+
+        verify(mUceController).registerPublishStateCallback(callback);
+    }
+
+    @Test
+    public void testRegisterPublishStateCallbackWithRcsUnavailable() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        doReturn(true).when(mUceController).isUnavailable();
+        uceCtrlManager.onRcsDisconnected();
+
+        try {
+            IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+            uceCtrlManager.registerPublishStateCallback(callback);
+            fail();
+        } catch (ImsException e) {
+            assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testUnregisterPublishStateCallback() throws Exception {
+        UceControllerManager uceCtrlManager = getUceControllerManager();
+        IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+
+        uceCtrlManager.unregisterPublishStateCallback(callback);
+
+        verify(mUceController).unregisterPublishStateCallback(callback);
+    }
+
+    private UceControllerManager getUceControllerManager() {
+        UceControllerManager manager = new UceControllerManager(mContext, mSlotId, mSubId,
+                mExecutorService);
+        manager.setUceController(mUceController);
+        return manager;
+    }
+}