Merge "Call mLoaded.set(false) for fileupdate default case"
diff --git a/Android.bp b/Android.bp
index 8cf8d0d..693da7c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -36,39 +36,22 @@
     path: "src/java",
 }
 
-java_library {
-    name: "telephony-common",
+filegroup {
+    name: "jarjar-rules-shared",
+    srcs: ["jarjar-rules-shared.txt"],
+}
+
+android_app {
+    name: "telephony-resources",
     installable: true,
 
-    aidl: {
-        local_include_dirs: ["src/java"],
-    },
-    srcs: [
-        ":opt-telephony-common-srcs",
-        "src/java/**/I*.aidl",
-        "src/java/**/*.logtags",
+    resource_dirs: [
+        "res",
     ],
 
-    jarjar_rules: ":framework-jarjar-rules",
-
-    libs: [
-        "android.hardware.radio-V1.0-java",
-        "android.hardware.radio-V1.1-java",
-        "android.hardware.radio-V1.2-java",
-        "android.hardware.radio-V1.3-java",
-        "android.hardware.radio-V1.4-java",
-        "voip-common",
-        "ims-common",
-        "services",
-    ],
-    static_libs: [
-        "android.hardware.radio.config-V1.0-java-shallow",
-        "android.hardware.radio.config-V1.1-java-shallow",
-        "android.hardware.radio.config-V1.2-java-shallow",
-        "android.hardware.radio.deprecated-V1.0-java-shallow",
-        "telephony-protos",
-        "ecc-protos-lite",
-    ],
+    platform_apis: true,
+    manifest: "AndroidManifest_Resources.xml",
+    export_package_resources: true,
 
     product_variables: {
         pdk: {
@@ -78,3 +61,52 @@
     },
 }
 
+java_library {
+    name: "telephony-common",
+    installable: true,
+
+    aidl: {
+        local_include_dirs: ["src/java"],
+    },
+    srcs: [
+        ":opt-telephony-common-srcs",
+        ":framework-telephony-stack-shared-srcs",
+        "src/java/**/I*.aidl",
+        "src/java/**/*.logtags",
+    ],
+
+    jarjar_rules: ":jarjar-rules-shared",
+
+    libs: [
+        "android.hardware.radio-V1.0-java",
+        "android.hardware.radio-V1.1-java",
+        "android.hardware.radio-V1.2-java",
+        "android.hardware.radio-V1.3-java",
+        "android.hardware.radio-V1.4-java",
+        "android.hardware.radio-V1.5-java",
+        "voip-common",
+        "ims-common",
+        "services",
+        "unsupportedappusage",
+        "telephony-resources",
+    ],
+    required: ["telephony-resources"],
+    static_libs: [
+        "android.hardware.radio.config-V1.0-java-shallow",
+        "android.hardware.radio.config-V1.1-java-shallow",
+        "android.hardware.radio.config-V1.2-java-shallow",
+        "android.hardware.radio.config-V1.3-java-shallow",
+        "android.hardware.radio.deprecated-V1.0-java-shallow",
+        "ecc-protos-lite",
+        "libphonenumber-nogeocoder",
+        "PlatformProperties",
+        "telephony-protos",
+    ],
+
+    product_variables: {
+        pdk: {
+            // enable this build only when platform library is available
+            enabled: false,
+        },
+    },
+}
diff --git a/AndroidManifest_Resources.xml b/AndroidManifest_Resources.xml
new file mode 100644
index 0000000..7afba27
--- /dev/null
+++ b/AndroidManifest_Resources.xml
@@ -0,0 +1,8 @@
+<!-- Manifest for telephony resources APK -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.telephony.resources">
+    <application
+        android:directBootAware="true"
+        android:hasCode="false">
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/OWNERS b/OWNERS
index 8f494b2..0f8fc34 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,4 +11,5 @@
 refuhoo@google.com
 paulye@google.com
 nazaninb@google.com
-sarahchin@google.com
\ No newline at end of file
+sarahchin@google.com
+dbright@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..e75dcb0
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "TeleServiceTests",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/jarjar-rules-shared.txt b/jarjar-rules-shared.txt
new file mode 100644
index 0000000..aa887da
--- /dev/null
+++ b/jarjar-rules-shared.txt
@@ -0,0 +1,19 @@
+rule android.os.RegistrantList* com.android.internal.telephony.RegistrantList@1
+rule android.os.Registrant* com.android.internal.telephony.Registrant@1
+rule android.hidl.** android.internal.hidl.@1
+rule android.sysprop.** android.internal.telephony.sysprop.@1
+rule android.util.LocalLog* com.android.internal.telephony.LocalLog@1
+rule android.util.TimeUtils* com.android.internal.telephony.TimeUtils@1
+rule com.android.internal.os.SomeArgs* com.android.internal.telephony.SomeArgs@1
+rule com.android.internal.util.AsyncChannel* com.android.internal.telephony.AsyncChannel@1
+rule com.android.internal.util.AsyncService* com.android.internal.telephony.AsyncService@1
+rule com.android.internal.util.BitwiseInputStream* com.android.internal.telephony.BitwiseInputStream@1
+rule com.android.internal.util.FastXmlSerializer* com.android.internal.telephony.FastXmlSerializer@1
+rule com.android.internal.util.HexDump* com.android.internal.telephony.HexDump@1
+rule com.android.internal.util.IState* com.android.internal.telephony.IState@1
+rule com.android.internal.util.IndentingPrintWriter* com.android.internal.telephony.IndentingPrintWriter@1
+rule com.android.internal.util.Preconditions* com.android.internal.telephony.Preconditions@1
+rule com.android.internal.util.State* com.android.internal.telephony.State@1
+rule com.android.internal.util.StateMachine* com.android.internal.telephony.StateMachine@1
+rule com.android.internal.util.UserIcons* com.android.internal.telephony.UserIcons@1
+rule com.google.i18n.phonenumbers.** com.android.internal.telephony.phonenumbers.@1
diff --git a/proto/Android.bp b/proto/Android.bp
index 166be3d..d7e379f 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -22,8 +22,8 @@
         ],
     },
     srcs: ["src/**/*.proto"],
-    sdk_version: "core_platform",
+    sdk_version: "system_current",
     jarjar_rules: "jarjar-rules.txt",
     // Pin java_version until jarjar is certified to support later versions. http://b/72703434
     java_version: "1.8",
-}
\ No newline at end of file
+}
diff --git a/proto/src/carrierId.proto b/proto/src/carrierId.proto
deleted file mode 100644
index 0f5eba8..0000000
--- a/proto/src/carrierId.proto
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Copyright (C) 2017 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.
-//
-
-syntax = "proto2";
-
-package carrierIdentification;
-
-option java_package = "com.android.internal.telephony";
-option java_outer_classname = "CarrierIdProto";
-
-// A complete list of carriers
-message CarrierList {
-  // A collection of carriers. one entry for one carrier.
-  repeated CarrierId carrier_id = 1;
-  // Version number of current carrier list
-  optional int32 version = 2;
-};
-
-// CarrierId is the unique representation of a carrier in CID table.
-message CarrierId {
-  // [Optional] A unique canonical number designated to a carrier.
-  optional int32 canonical_id = 1;
-
-  // [Optional] A user-friendly carrier name (not localized).
-  optional string carrier_name = 2;
-
-  // [Optional] Carrier attributes to match a carrier. At least one value is required.
-  repeated CarrierAttribute carrier_attribute = 3;
-
-  // [Optional] A unique canonical number to represent its parent carrier. The parent-child
-  // relationship can be used to differentiate a single carrier by different networks,
-  // by prepaid v.s. postpaid  or even by 4G v.s. 3G plan.
-  optional int32 parent_canonical_id = 4;
-};
-
-// Attributes used to match a carrier.
-// For each field within this message:
-//   - if not set, the attribute is ignored;
-//   - if set, the device must have one of the specified values to match.
-// Match is based on AND between any field that is set and OR for values within a repeated field.
-message CarrierAttribute {
-  // [Optional] The MCC and MNC that map to this carrier. At least one value is required.
-  repeated string mccmnc_tuple = 1;
-
-  // [Optional] Prefix of IMSI (International Mobile Subscriber Identity) in
-  // decimal format. Some digits can be replaced with "x" symbols matching any digit.
-  // Sample values: 20404794, 21670xx2xxx.
-  repeated string imsi_prefix_xpattern = 2;
-
-  // [Optional] The Service Provider Name. Read from subscription EF_SPN.
-  // Sample values: C Spire, LeclercMobile
-  repeated string spn = 3;
-
-  // [Optional] PLMN network name. Read from subscription EF_PNN.
-  // Sample values:
-  repeated string plmn = 4;
-
-  // [Optional] Group Identifier Level1 for a GSM phone. Read from subscription EF_GID1.
-  // Sample values: 6D, BAE0000000000000
-  repeated string gid1 = 5;
-
-  // [Optional] Group Identifier Level2 for a GSM phone. Read from subscription EF_GID2.
-  // Sample values: 6D, BAE0000000000000
-  repeated string gid2 = 6;
-
-  // [Optional] The Access Point Name, corresponding to "apn" field returned by
-  // "content://telephony/carriers/preferapn" on device.
-  // Sample values: fast.t-mobile.com, internet
-  repeated string preferred_apn = 7;
-
-  // [Optional] Prefix of Integrated Circuit Card Identifier. Read from subscription EF_ICCID.
-  // Sample values: 894430, 894410
-  repeated string iccid_prefix = 8;
-
-  // [Optional] Carrier Privilege Access Rule in hex string.
-  // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88
-  repeated string privilege_access_rule = 9;
-};
-
diff --git a/proto/src/telephony.proto b/proto/src/telephony.proto
index ec2acf4..020aba6 100644
--- a/proto/src/telephony.proto
+++ b/proto/src/telephony.proto
@@ -262,6 +262,46 @@
     ROAMING_TYPE_INTERNATIONAL = 3;
   }
 
+  // Frequency range
+  enum FrequencyRange {
+    // Unknown. The default value.
+    FREQUENCY_RANGE_UNKNOWN = 0;
+
+    // Frequency range is below 1GHz.
+    FREQUENCY_RANGE_LOW = 1;
+
+    // Frequency range is between 1GHz and 3GHz.
+    FREQUENCY_RANGE_MID = 2;
+
+    // Frequency range is between 3GHz and 6GHz.
+    FREQUENCY_RANGE_HIGH = 3;
+
+    // Frequency range is above 6GHz (millimeter wave frequency).
+    FREQUENCY_RANGE_MMWAVE = 4;
+  }
+
+  // NR (5G) state
+  enum NrState {
+    // The device isn't camped on an LTE cell
+    // or the LTE cell doesn't support EN-DC.
+    NR_STATE_NONE = 0;
+
+    // The device is camped on an LTE cell that supports EN-DC
+    // but either DCNR is restricted
+    // or NR is not supported by the selected PLMN.
+    NR_STATE_RESTRICTED = 1;
+
+    // The device is camped on an LTE cell that supports EN-DC
+    // and both DCNR is not restricted and NR is supported
+    // by the selected PLMN.
+    NR_STATE_NOT_RESTRICTED = 2;
+
+    // The device is camped on an LTE cell that supports EN-DC
+    // and connected to at least one 5G cell
+    // as a secondary serving cell.
+    NR_STATE_CONNECTED = 3;
+  }
+
   // Current registered operator
   optional TelephonyOperator voice_operator = 1;
 
@@ -282,6 +322,12 @@
 
   // Current Channel Number
   optional int32 channel_number = 7;
+
+  // Current NR frequency range
+  optional FrequencyRange nr_frequency_range = 8;
+
+  // Current NR state
+  optional NrState nr_state = 9;
 }
 
 // Radio access families
@@ -720,7 +766,7 @@
     // along with the event if it is available
     MODEM_RESTART = 11;
 
-    // System time overwritten by NITZ (Network time)
+    // A system time update suggestion was made from a received NITZ (Network time) signal
     NITZ_TIME = 12;
 
     // Carrier Identification Matching Event
@@ -749,6 +795,12 @@
 
     // Emergency Number update event (Device HAL >= 1.4).
     EMERGENCY_NUMBER_REPORT = 21;
+
+    // Network capabilities change event.
+    NETWORK_CAPABILITIES_CHANGED = 22;
+
+    // Signal strength
+    SIGNAL_STRENGTH = 23;
   }
 
   enum ApnType {
@@ -1651,6 +1703,11 @@
     optional string preferApn = 12;
   }
 
+  message NetworkCapabilitiesInfo {
+    // Is network unmetered
+    optional bool is_network_unmetered = 1;
+  }
+
   // Time when event happened on device, in milliseconds since epoch
   optional int64 timestamp_millis = 1;
 
@@ -1693,7 +1750,7 @@
   // Modem restart event
   optional ModemRestart modem_restart = 14;
 
-  // NITZ time in milliseconds
+  // NITZ time in milliseconds (see TelephonyEvent.Type.NITZ_TIME)
   optional int64 nitz_timestamp_millis = 15;
 
   // Carrier id matching event
@@ -1723,6 +1780,19 @@
 
   // Updated Emergency Call info.
   optional EmergencyNumberInfo updated_emergency_number = 25;
+
+  // NetworkCapabilities changed info.
+  optional NetworkCapabilitiesInfo network_capabilities = 26;
+
+  // Signal strength
+  optional int32 signal_strength = 27;
+
+  // Indicate the version of emergency number database in Android platform
+  optional int32 emergency_number_database_version = 28;
+  // [
+  //  (datapol.semantic_type) = ST_SOFTWARE_ID,
+  //  (datapol.qualifier) = { is_public: true }
+  //]
 }
 
 message ActiveSubscriptionInfo {
@@ -2032,6 +2102,13 @@
 
       // Indicate the emergency call information dialed from the CS call
       optional EmergencyNumberInfo emergency_number_info = 8;
+
+      // Indicate the version of emergency number database in Android platform
+      optional int32 emergency_number_database_version = 9;
+      // [
+      //  (datapol.semantic_type) = ST_SOFTWARE_ID,
+      //  (datapol.qualifier) = { is_public: true }
+      //]
     }
 
     // Single Radio Voice Call Continuity(SRVCC) progress state
@@ -2128,6 +2205,18 @@
 
       // the codec type of an ongoing call
       optional AudioCodec codec_type = 11;
+
+      // true if no incoming RTP is received for a continuous duration of 4 seconds
+      optional bool rtp_inactivity_detected = 12;
+
+      // true if only silence RTP packets are received for 20 seconds immediately
+      // after call is connected
+      optional bool rx_silence_detected = 13;
+
+      // true if only silence RTP packets are sent for 20 seconds immediately
+      // after call is connected
+      optional bool tx_silence_detected = 14;
+
     }
 
     message CallQualitySummary {
@@ -2258,6 +2347,13 @@
 
     // Emergency call info
     optional EmergencyNumberInfo ims_emergency_number_info = 27;
+
+    // Indicate the version of emergency number database in Android platform
+    optional int32 emergency_number_database_version = 28;
+    // [
+    //  (datapol.semantic_type) = ST_SOFTWARE_ID,
+    //  (datapol.qualifier) = { is_public: true }
+    //]
   }
 
   // Time when call has started, in minutes since epoch,
diff --git a/res/values/config.xml b/res/values/config.xml
new file mode 100644
index 0000000..5ea773e
--- /dev/null
+++ b/res/values/config.xml
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds.  Do not translate.
+
+     NOTE: The naming convention is "config_camelCaseValue". Some legacy
+     entries do not follow the convention, but all new entries should. -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- The RadioAccessFamilies supported by the device.
+         Empty is viewed as "all".  Only used on devices which
+         don't support RIL_REQUEST_GET_RADIO_CAPABILITY
+         format is UMTS|LTE|... -->
+    <string translatable="false" name="config_radio_access_family"></string>
+
+    <!-- MMS user agent string -->
+    <string name="config_mms_user_agent" translatable="false"></string>
+
+    <!-- MMS user agent prolfile url -->
+    <string name="config_mms_user_agent_profile_url" translatable="false"></string>
+
+    <!-- Config determines whether to update phone object when voice registration
+         state changes. Voice radio tech change will always trigger an update of
+         phone object irrespective of this config -->
+    <bool name="config_switch_phone_on_voice_reg_state_change">true</bool>
+
+    <!-- Boolean indicating if restoring network selection should be skipped -->
+    <!-- The restoring is handled by modem if it is true-->
+    <bool translatable="false" name="skip_restoring_network_selection">false</bool>
+
+    <!-- An array of CDMA roaming indicators which means international roaming -->
+    <integer-array translatable="false" name="config_cdma_international_roaming_indicators" />
+
+    <!-- Configure mobile network MTU. The standard default is set here but each carrier
+         may have a specific value set in an overlay config.xml file. -->
+    <integer name="config_mobile_mtu">1500</integer>
+
+    <!-- Configure mobile tcp buffer sizes in the form:
+         rat-name:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max
+         If no value is found for the rat-name in use, the system default will be applied.
+    -->
+    <string-array name="config_mobile_tcp_buffers">
+    </string-array>
+
+    <!-- flag to indicate if EF LI/EF PL should be used for system language -->
+    <bool name="config_use_sim_language_file">false</bool>
+
+    <!-- List of countries in which we display 'No service' on status bar
+         instead of 'Emergency calls only' when SIM is unready. -->
+    <string-array translatable="false" name="config_display_no_service_when_sim_unready">
+        <item>"DE"</item>
+        <item>"GB"</item>
+        <item>"JP"</item>
+    </string-array>
+
+    <!-- Flag indicating whether the surface flinger is inefficient
+         at performing a blur.  Used by parts of the UI to turn off
+         the blur effect where it isn't worth the performance hit.
+         As of Honeycomb, blurring is not supported anymore. -->
+    <bool name="config_sf_slowBlur">true</bool>
+
+    <!-- set to false if we need to show user confirmation
+         when alpha identifier is not provided by the UICC -->
+    <bool name="config_stkNoAlphaUsrCnf">true</bool>
+
+    <!-- Number of physical SIM slots on the device. This includes both eSIM and pSIM slots, and
+         is not necessarily the same as the number of phones/logical modems supported by the device.
+         For example, a multi-sim device can have 2 phones/logical modems, but 3 physical slots,
+         or a single SIM device can have 1 phones/logical modems, but 2 physical slots (one eSIM
+         and one pSIM) -->
+    <integer name="config_num_physical_slots">1</integer>
+
+    <!-- Is the device capable of hot swapping an UICC Card -->
+    <bool name="config_hotswapCapable">false</bool>
+
+    <!-- An array of device capabilities defined by GSMA SGP.22 v2.0.
+         The first item is the capability name that the device supports. The second item is the
+         major version. The minor and revision versions are default to 0s.
+         The device capabilities and their definition in the spec are:
+             gsm : gsmSupportedRelease
+             utran : utranSupportedRelease
+             cdma1x : cdma2000onexSupportedRelease
+             hrpd : cdma2000hrpdSupportedRelease
+             ehrpd : cdma2000ehrpdSupportedRelease
+             eutran : eutranSupportedRelease
+             nfc : contactlessSupportedRelease
+             crl : rspCrlSupportedVersion
+    -->
+    <string-array translatable="false" name="config_telephonyEuiccDeviceCapabilities">
+        <!-- Example:
+        <item>"gsm,11"</item>
+        <item>"utran,11"</item>
+        <item>"cdma1x,1"</item>
+        <item>"hrpd,3"</item>
+        <item>"ehrpd,12"</item>
+        <item>"eutran,11"</item>
+        <item>"nfc,1"</item>
+        <item>"crl,1"</item>
+        -->
+    </string-array>
+
+    <!-- If this value is true, duplicate Source/Destination port fields
+         in WDP header of some carriers OMADM wap push are supported.
+         ex: MSGTYPE-TotalSegments-CurrentSegment
+             -SourcePortDestPort-SourcePortDestPort-OMADM PDU
+         If false, not supported. -->
+    <bool name="config_duplicate_port_omadm_wappush">false</bool>
+
+    <!-- Cellular network service package name to bind to by default. -->
+    <string name="config_wwan_network_service_package" translatable="false">com.android.phone</string>
+
+    <!-- Cellular network service class name to bind to by default.-->
+    <string name="config_wwan_network_service_class" translatable="false"></string>
+
+    <!-- IWLAN network service package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wlan_network_service_package" translatable="false"></string>
+
+    <!-- IWLAN network service class name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wlan_network_service_class" translatable="false"></string>
+
+    <!-- Telephony qualified networks service package name to bind to by default. -->
+    <string name="config_qualified_networks_service_package" translatable="false"></string>
+
+    <!-- Telephony qualified networks service class name to bind to by default. -->
+    <string name="config_qualified_networks_service_class" translatable="false"></string>
+
+    <!-- Cellular data service package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wwan_data_service_package" translatable="false">com.android.phone</string>
+
+    <!-- IWLAN data service package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wlan_data_service_package" translatable="false"></string>
+
+    <!-- Cellular data service class name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wwan_data_service_class" translatable="false"></string>
+
+    <!-- IWLAN data service class name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wlan_data_service_class" translatable="false"></string>
+
+    <!-- Boolean indicating if RADIO POWER OFF is required on receiving SIM REFRESH with RESET.
+         This will be handled by modem if it is false. -->
+    <bool name="config_requireRadioPowerOffOnSimRefreshReset">false</bool>
+
+    <!-- Flag specifying whether the device will use the "allow_hold_in_ims_call" carrier config
+         option.  When false, the device will support holding of IMS calls, regardless of the
+         carrier config setting. -->
+    <bool name="config_device_respects_hold_carrier_config">true</bool>
+
+    <!-- Whether to use voip audio mode for ims call -->
+    <bool name="config_use_voip_mode_for_ims">false</bool>
+
+    <!-- Enables built-in SIP phone capability -->
+    <bool name="config_built_in_sip_phone">true</bool>
+
+    <!-- Flag indicating apps will skip sending hold request before merge. In this case
+        IMS service implementation will do both.i.e.hold followed by merge. -->
+    <bool name="skipHoldBeforeMerge">true</bool>
+
+    <!-- Flag specifying whether VoLTE is available on device -->
+    <bool name="config_device_volte_available">false</bool>
+
+    <!-- Flag specifying whether VT is available on device -->
+    <bool name="config_device_vt_available">false</bool>
+
+    <!-- Flag specifying whether WFC over IMS is available on device -->
+    <bool name="config_device_wfc_ims_available">false</bool>
+
+    <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
+    <bool name="config_dynamic_bind_ims">false</bool>
+
+    <!-- ImsService package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_ims_package"/>
+
+    <!-- Whether cbrs is supported on the device or not -->
+    <bool name="config_cbrs_supported" translatable="false">false</bool>
+
+    <!-- Enables SIP on WIFI only -->
+    <bool name="config_sip_wifi_only">false</bool>
+
+    <!-- Name of the dialog that is used to install the carrier app when the SIM is inserted -->
+    <string name="config_carrierAppInstallDialogComponent" translatable="false"
+            >com.android.simappdialog/com.android.simappdialog.InstallCarrierAppActivity</string>
+
+    <!-- The default mobile provisioning apn. Empty by default, maybe overridden by
+         an mcc/mnc specific config.xml -->
+    <string name="mobile_provisioning_apn" translatable="false"></string>
+
+    <!-- Number of retries Cell Data should attempt for a given error code before
+         restarting the modem.
+         Error codes not listed will not lead to modem restarts.
+         Array of "code#,retry#"  -->
+    <string-array name="config_cell_retries_per_error_code">
+    </string-array>
+
+    <bool name="config_auto_attach_data_on_creation">true</bool>
+
+    <!-- Set to true if after a provisioning apn the radio should be restarted -->
+    <bool name="config_restartRadioAfterProvisioning">false</bool>
+
+    <!-- When true, indicates that the vendor's IMS implementation requires a workaround when
+         sending a request to enable or disable the camera while the video session is also
+         paused. -->
+    <bool name="config_useVideoPauseWorkaround">false</bool>
+
+    <!-- Use ERI text for network name on CDMA LTE -->
+    <bool name="config_LTE_eri_for_network_name">true</bool>
+
+    <!-- Flag indicating if the user is notified when the mobile network access is restricted -->
+    <bool name="config_user_notification_of_restrictied_mobile_access">true</bool>
+
+    <!-- Component name of the ICC hotswap prompt for restart dialog -->
+    <string name="config_iccHotswapPromptForRestartDialogComponent" translatable="false">@null</string>
+
+    <!-- call barring MMI code from TS 22.030 Annex B -->
+    <string-array translatable="false" name="config_callBarringMMI">
+        <item>33</item>
+        <item>331</item>
+        <item>332</item>
+        <item>35</item>
+        <item>351</item>
+        <item>330</item>
+        <item>333</item>
+        <item>353</item>
+    </string-array>
+
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+    <string-array name="config_twoDigitNumberPattern" translatable="false">
+    </string-array>
+
+    <!-- A array of regex to treat a SMS as VVM SMS if the message body matches.
+         Each item represents an entry, which consists of two parts:
+         a comma (,) separated list of MCCMNC the regex applies to, followed by a semicolon (;), and
+         then the regex itself. -->
+    <string-array name="config_vvmSmsFilterRegexes" translatable="false">
+        <!-- Verizon requires any SMS that starts with //VZWVVM to be treated as a VVM SMS-->
+        <item>310004,310010,310012,310013,310590,310890,310910,311110,311270,311271,311272,311273,311274,311275,311276,311277,311278,311279,311280,311281,311282,311283,311284,311285,311286,311287,311288,311289,311390,311480,311481,311482,311483,311484,311485,311486,311487,311488,311489;^//VZWVVM.*</item>
+    </string-array>
+
+    <!-- default telephony hardware configuration for this platform.
+    -->
+    <!-- this string array should be overridden by the device to present a list
+         telephony hardware resource.  this is used by the telephony device controller
+         (TDC) to offer the basic capabilities of the hardware to the telephony
+         framework
+    -->
+    <!-- an array of "[hardware type],[hardware-uuid],[state],[[hardware-type specific]]"
+         with, [[hardware-type specific]] in:
+            - "[[ril-model],[rat],[max-active-voice],[max-active-data],[max-active-standby]]"
+              for 'modem' hardware
+            - "[[associated-modem-uuid]]"
+              for 'sim' hardware.
+         refer to HardwareConfig in com.android.internal.telephony for specific details/values
+         those elements can carry.
+    -->
+    <string-array translatable="false" name="config_telephonyHardware">
+        <!-- modem -->
+        <item>0,modem,0,0,0,1,1,1</item>
+        <!-- sim -->
+        <item>1,sim,0,modem</item>
+    </string-array>
+
+    <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] -->
+    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastservice
+    </string>
+
+    <!-- For some operators, PDU has garbages. To fix it, need to use valid index -->
+    <integer name="config_valid_wappush_index">-1</integer>
+
+    <!-- Set to true if we need to not prefer an APN.
+         This is being added to enable a simple scenario of pre-paid
+         provisioning on some carriers, working around a bug (7305641)
+         where if the preferred is used we don't try the others. -->
+    <bool name="config_dontPreferApn">false</bool>
+
+</resources>
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
new file mode 100644
index 0000000..1bbad36
--- /dev/null
+++ b/res/values/overlayable.xml
@@ -0,0 +1,78 @@
+<?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.
+-->
+
+<!-- The collection of resources for theming the appearance of a device -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <overlayable name="TelephonyCustomization">
+
+        <!-- START VENDOR CUSTOMIZATION -->
+        <policy type="product|system|vendor">
+            <item type="string" name="config_mms_user_agent"/>
+            <item type="string" name="config_mms_user_agent_profile_url"/>
+            <item type="bool" name="config_switch_phone_on_voice_reg_state_change"/>
+            <item type="bool" name="skip_restoring_network_selection"/>
+            <item type="bool" name="config_hotswapCapable"/>
+            <item type="array" name="config_cdma_international_roaming_indicators"/>
+            <item type="integer" name="config_mobile_mtu"/>
+            <item type="array" name="config_mobile_tcp_buffers"/>
+            <item type="bool" name="config_use_sim_language_file"/>
+            <item type="bool" name="config_requireRadioPowerOffOnSimRefreshReset"/>
+            <item type="bool" name="config_device_respects_hold_carrier_config"/>
+            <item type="array" name="config_display_no_service_when_sim_unready"/>
+            <item type="array" name="config_telephonyEuiccDeviceCapabilities"/>
+            <item type="integer" name="config_num_physical_slots"/>
+            <item type="bool" name="config_duplicate_port_omadm_wappush"/>
+            <item type="string" name="config_wwan_network_service_package"/>
+            <item type="string" name="config_wwan_network_service_class"/>
+            <item type="string" name="config_wlan_network_service_package"/>
+            <item type="string" name="config_wlan_network_service_class"/>
+            <item type="string" name="config_qualified_networks_service_package"/>
+            <item type="string" name="config_qualified_networks_service_class"/>
+            <item type="string" name="config_wwan_data_service_package"/>
+            <item type="string" name="config_wwan_data_service_class"/>
+            <item type="string" name="config_wlan_data_service_package"/>
+            <item type="string" name="config_wlan_data_service_class"/>
+            <item type="bool" name="config_use_voip_mode_for_ims"/>
+            <item type="bool" name="config_built_in_sip_phone"/>
+            <item type="bool" name="skipHoldBeforeMerge"/>
+            <item type="bool" name="config_device_volte_available"/>
+            <item type="bool" name="config_device_vt_available"/>
+            <item type="bool" name="config_device_wfc_ims_available"/>
+            <item type="bool" name="config_dynamic_bind_ims"/>
+            <item type="string" name="config_ims_package"/>
+            <item type="string" name="config_carrierAppInstallDialogComponent"/>
+            <item type="bool" name="config_cbrs_supported"/>
+            <item type="bool" name="config_sip_wifi_only"/>
+            <item type="string" name="mobile_provisioning_apn"/>
+            <item type="array" name="config_cell_retries_per_error_code"/>
+            <item type="bool" name="config_auto_attach_data_on_creation"/>
+            <item type="bool" name="config_restartRadioAfterProvisioning"/>
+            <item type="bool" name="config_useVideoPauseWorkaround"/>
+            <item type="bool" name="config_LTE_eri_for_network_name"/>
+            <item type="bool" name="config_user_notification_of_restrictied_mobile_access"/>
+            <item type="string" name="config_iccHotswapPromptForRestartDialogComponent"/>
+            <item type="array" name="config_callBarringMMI"/>
+            <item type="array" name="config_twoDigitNumberPattern"/>
+            <item type="array" name="config_vvmSmsFilterRegexes"/>
+            <item type="array" name="config_telephonyHardware"/>
+            <item type="string" name="cellbroadcast_default_package"/>
+            <item type="integer" name="config_valid_wappush_index"/>
+            <item type="bool" name="config_dontPreferApn"/>
+          </policy>
+        <!-- END VENDOR CUSTOMIZATION -->
+
+    </overlayable>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..5cf34ec
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Do Not Translate: Alternate eri.xml -->
+    <string name="alternate_eri_file">/data/eri.xml</string>
+
+    <!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale. The wifi regulatory domain is extracted from the locale information. This is used at startup to set system defaults by checking the system property ro.carrier for the carrier-id and searching through this array -->
+    <!-- An Array of [[Carrier-ID]                     -->
+    <!--              [default-locale]]                -->
+    <string-array name="carrier_properties" translatable="false">
+    </string-array>
+
+    <!-- For GsmMmiCode.java --> <skip />
+    <!-- Displayed when the user dialed an MMI code whose function
+         could not be performed. This will be displayed in a toast. -->
+    <string name="mmiError">Connection problem or invalid MMI code.</string>
+    <!-- Displayed when the user dialed an MMI code whose function
+         could not be performed because FDN is enabled. This will be displayed in a toast. -->
+    <string name="mmiFdnError">Operation is restricted to fixed dialing numbers only.</string>
+    <!-- Displayed when a carrier does not support call forwarding queries when roaming. -->
+    <string name="mmiErrorWhileRoaming">Can not change call forwarding settings from your phone while you are roaming.</string>
+
+    <!-- What the UI should display for "voice mail" unless overridden by the SIM-->
+    <string name="defaultVoiceMailAlphaTag">Voicemail</string>
+
+    <!-- Displayed when a phone feature such as call barring was activated. -->
+    <string name="serviceEnabled">Service was enabled.</string>
+    <!-- Displayed in front of the list of a set of service classes
+         (voice, data, fax, etc.) that were enabled. -->
+    <string name="serviceEnabledFor">Service was enabled for:</string>
+    <!-- Displayed when a phone feature such as call forwarding was deactivated. -->
+    <string name="serviceDisabled">Service has been disabled.</string>
+    <!-- Displayed when a phone property such as a SIM password was registered. -->
+    <string name="serviceRegistered">Registration was successful.</string>
+    <!-- Displayed when a phone property such as a SIM password was erased. -->
+    <string name="serviceErased">Erasure was successful.</string>
+    <!-- Displayed when a SIM password was entered incorrectly. -->
+    <string name="passwordIncorrect">Incorrect password.</string>
+    <!-- Displayed when a phone feature triggered by an MMI code is complete. -->
+    <string name="mmiComplete">MMI complete.</string>
+    <!-- Displayed when a SIM PIN password is entered incorrectly. -->
+    <string name="badPin">The old PIN you typed isn\'t correct.</string>
+    <!-- Displayed when a SIM PUK password is entered incorrectly. -->
+    <string name="badPuk">The PUK you typed isn\'t correct.</string>
+    <!-- Displayed when SIM PIN passwords are entered inconsistently. -->
+    <string name="mismatchPin">The PINs you typed don\'t match.</string>
+    <!-- Displayed when a SIM PIN password is too long or too short. -->
+    <string name="invalidPin">Type a PIN that is 4 to 8 numbers.</string>
+    <!-- Displayed when a SIM PUK password is too short. -->
+    <string name="invalidPuk">Type a PUK that is 8 numbers or longer.</string>
+    <!-- Displayed to prompt the user to type the PUK password to unlock
+         the SIM card. -->
+    <string name="needPuk">Your SIM card is PUK-locked. Type the PUK code to unlock it.</string>
+    <string name="needPuk2">Type PUK2 to unblock SIM card.</string>
+    <!-- Displayed when user attempts to change SIM PIN1 without enabling PIN1. -->
+    <string name="enablePin">Unsuccessful, enable SIM/RUIM Lock.</string>
+    <!-- Displayed when a SIM PIN/PUK is entered incorrectly. -->
+    <plurals name="pinpuk_attempts">
+        <item quantity="one">You have <xliff:g id="number">%d</xliff:g> remaining attempt before SIM is locked.</item>
+        <item quantity="other">You have <xliff:g id="number">%d</xliff:g> remaining attempts before SIM is locked.</item>
+    </plurals>
+    <!-- Title for the dialog used to display the user's IMEI number [CHAR LIMIT=10] -->
+    <string name="imei">IMEI</string>
+
+    <!-- Title for the dialog used to display the user's MEID number on CDMA network
+         [CHAR LIMIT=10] -->
+    <string name="meid">MEID</string>
+
+    <!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
+    <string name="ClipMmi">Incoming Caller ID</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
+    <string name="ClirMmi">Outgoing Caller ID</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID. -->
+    <string name="ColpMmi">Connected Line ID</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID restriction. -->
+    <string name="ColrMmi">Connected Line ID Restriction</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling call forwarding. -->
+    <string name="CfMmi">Call forwarding</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling call waiting. -->
+    <string name="CwMmi">Call waiting</string>
+    <!-- Displayed as the title for a success/failure report enabling/disabling call barring. -->
+    <string name="BaMmi">Call barring</string>
+    <!-- Displayed as the title for a success/failure report changing the SIM password. -->
+    <string name="PwdMmi">Password change</string>
+    <!-- Displayed as the title for a success/failure report changing the SIM PIN. -->
+    <string name="PinMmi">PIN change</string>
+    <string name="CnipMmi">Calling number present</string>
+    <string name="CnirMmi">Calling number restricted</string>
+    <string name="ThreeWCMmi">Three way calling</string>
+    <string name="RuacMmi">Rejection of undesired annoying calls</string>
+    <string name="CndMmi">Calling number delivery</string>
+    <string name="DndMmi">Do not disturb</string>
+
+    <!-- Displayed to confirm to the user that caller ID will be restricted on the next call as usual. -->
+    <string name="CLIRDefaultOnNextCallOn">Caller ID defaults to restricted. Next call: Restricted</string>
+    <!-- Displayed to confirm to the user that caller ID will be not restricted on the next call even though it usually is. -->
+    <string name="CLIRDefaultOnNextCallOff">Caller ID defaults to restricted. Next call: Not restricted</string>
+    <!-- Displayed to confirm to the user that caller ID will not be restricted on the next call but usually is. -->
+    <string name="CLIRDefaultOffNextCallOn">Caller ID defaults to not restricted. Next call: Restricted</string>
+    <!-- Displayed to confirm to the user that caller ID will not be restricted on the next call or in general. -->
+    <string name="CLIRDefaultOffNextCallOff">Caller ID defaults to not restricted. Next call: Not restricted</string>
+
+
+    <!-- Displayed to tell the user that caller ID is not provisioned for their SIM. -->
+    <string name="serviceNotProvisioned">Service not provisioned.</string>
+    <!-- Displayed to tell the user that they cannot change the caller ID setting. -->
+    <string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
+
+    <!-- Notification title to tell the user that data service is blocked by access control. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="RestrictedOnDataTitle">No mobile data service</string>
+    <!-- Notification title to tell the user that emergency calling is blocked by access control. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
+    <!-- Notification title to tell the user that normal service is blocked by access control. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="RestrictedOnNormalTitle">No voice service</string>
+    <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
+
+    <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
+
+    <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control when multiple SIMs are active. [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="RestrictedStateContentMsimTemplate">Temporarily turned off by your carrier for SIM <xliff:g id="simNumber" example="1">%d</xliff:g></string>
+
+    <!-- Displayed to tell the user that they should switch their network preference. -->
+    <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach mobile network</string>
+    <!-- Displayed to tell the user that they should switch their network preference. -->
+    <string name="NetworkPreferenceSwitchSummary">Try changing preferred network. Tap to change.</string>
+    <!-- Displayed to tell the user that emergency calls might not be available. -->
+    <string name="EmergencyCallWarningTitle">Emergency calling unavailable</string>
+    <!-- Displayed to tell the user that emergency calls might not be available. -->
+    <string name="EmergencyCallWarningSummary">Can\u2019t make emergency calls over Wi\u2011Fi</string>
+
+    <!-- Telephony notification channel name for a channel containing network alert notifications. -->
+    <string name="notification_channel_network_alert">Alerts</string>
+    <!-- Telephony notification channel name for a channel containing call forwarding notifications. -->
+    <string name="notification_channel_call_forward">Call forwarding</string>
+    <!-- Telephony notification channel name for a channel containing emergency callback mode notifications. -->
+    <string name="notification_channel_emergency_callback">Emergency callback mode</string>
+    <!-- Telephony notification channel name for a channel containing mobile data status notifications. -->
+    <string name="notification_channel_mobile_data_status">Mobile data status</string>
+    <!-- Telephony notification channel name for a channel containing sms notifications. -->
+    <string name="notification_channel_sms">SMS messages</string>
+    <!-- Telephony notification channel name for a channel containing voice mail notifications. -->
+    <string name="notification_channel_voice_mail">Voicemail messages</string>
+    <!-- Telephony notification channel name for a channel containing wifi calling status notifications. -->
+    <string name="notification_channel_wfc">Wi-Fi calling</string>
+    <!-- Telephony notification channel name for a channel containing SIM notifications -->
+    <string name="notification_channel_sim">SIM status</string>
+    <!-- Telephony notification channel name for a channel containing high priority SIM notifications -->
+    <string name="notification_channel_sim_high_prio">High priority SIM status</string>
+
+    <!-- Displayed to tell the user that peer changed TTY mode -->
+    <string name="peerTtyModeFull">Peer requested TTY Mode FULL</string>
+    <string name="peerTtyModeHco">Peer requested TTY Mode HCO</string>
+    <string name="peerTtyModeVco">Peer requested TTY Mode VCO</string>
+    <string name="peerTtyModeOff">Peer requested TTY Mode OFF</string>
+
+    <!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip />
+    <!-- Example: Service was enabled for: Voice, Data -->
+    <string name="serviceClassVoice">Voice</string>
+    <!-- Example: Service was enabled for: Voice, Data -->
+    <string name="serviceClassData">Data</string>
+    <!-- Example: Service was enabled for: Voice, FAX -->
+    <string name="serviceClassFAX">FAX</string>
+    <!-- Example: Service was enabled for: Voice, SMS -->
+    <string name="serviceClassSMS">SMS</string>
+    <!-- Meaning: asynchronous data.  Example: Service was enabled for: Voice, Async -->
+    <string name="serviceClassDataAsync">Async</string>
+    <!-- Meaning: synchronous data.  Example: Service was enabled for: Voice, Async -->
+    <string name="serviceClassDataSync">Sync</string>
+    <!-- Meaning: packet data.  Example: Service was enabled for: Voice, Packet -->
+    <string name="serviceClassPacket">Packet</string>
+    <!-- Meaning: unknown.  Example: Service was enabled for: Voice, PAD -->
+    <string name="serviceClassPAD">PAD</string>
+
+    <!-- CDMA Roaming Indicator Strings (non ERI)--> <skip />
+    <!-- Default roaming indicator text -->
+    <string name="roamingText0">Roaming Indicator On</string>
+    <string name="roamingText1">Roaming Indicator Off</string>
+    <string name="roamingText2">Roaming Indicator Flashing</string>
+    <string name="roamingText3">Out of Neighborhood</string>
+    <string name="roamingText4">Out of Building</string>
+    <string name="roamingText5">Roaming - Preferred System</string>
+    <string name="roamingText6">Roaming - Available System</string>
+    <string name="roamingText7">Roaming - Alliance Partner</string>
+    <string name="roamingText8">Roaming - Premium Partner</string>
+    <string name="roamingText9">Roaming - Full Service Functionality</string>
+    <string name="roamingText10">Roaming - Partial Service Functionality</string>
+    <string name="roamingText11">Roaming Banner On</string>
+    <string name="roamingText12">Roaming Banner Off</string>
+    <string name="roamingTextSearching">Searching for Service</string>
+
+    <!-- Displayed when WFC registration fails -->
+    <string name="wfcRegErrorTitle">Couldn\u2019t set up Wi\u2011Fi calling</string>
+    <!-- WFC Operator Error Messages showed as alerts -->
+    <string-array name="wfcOperatorErrorAlertMessages">
+        <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g>)</item>
+    </string-array>
+    <!-- WFC Operator Error Messages showed as notifications -->
+    <string-array name="wfcOperatorErrorNotificationMessages">
+        <item>Issue registering Wi\u2011Fi calling with your carrier: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g></item>
+    </string-array>
+    <!-- Template for showing mobile network operator name while WFC is active -->
+    <string-array name="wfcSpnFormats" translatable="false">
+        <item>@string/wfcSpnFormat_spn</item>
+        <item>@string/wfcSpnFormat_spn_wifi_calling</item>
+        <item>@string/wfcSpnFormat_wlan_call</item>
+        <item>@string/wfcSpnFormat_spn_wlan_call</item>
+        <item>@string/wfcSpnFormat_spn_wifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
+        <item>@string/wfcSpnFormat_spn_vowifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling</item>
+        <item>@string/wfcSpnFormat_wifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling_wo_hyphen</item>
+        <item>@string/wfcSpnFormat_vowifi</item>
+        <item>@string/wfcSpnFormat_spn_wifi_calling_vo_hyphen</item>
+    </string-array>
+
+    <!-- Ims supported call barring MMI code -->
+    <string-array translatable="false" name="config_callBarringMMI_for_ims">
+        <item>33</item>
+        <item>331</item>
+        <item>332</item>
+        <item>35</item>
+        <item>351</item>
+        <item>330</item>
+        <item>333</item>
+        <item>353</item>
+      </string-array>
+
+    <!-- Spn during Wi-Fi Calling: "<operator>" -->
+    <string name="wfcSpnFormat_spn"><xliff:g id="spn" example="Operator">%s</xliff:g></string>
+    <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi Calling" -->
+    <string name="wfcSpnFormat_spn_wifi_calling"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "<operator> WiFi Calling" -->
+    <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen"><xliff:g id="spn" example="Operator">%s</xliff:g> WiFi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "WLAN Call" -->
+    <string name="wfcSpnFormat_wlan_call">WLAN Call</string>
+    <!-- Spn during Wi-Fi Calling: "<operator> WLAN Call" -->
+    <string name="wfcSpnFormat_spn_wlan_call"><xliff:g id="spn" example="Operator">%s</xliff:g> WLAN Call</string>
+    <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi" -->
+    <string name="wfcSpnFormat_spn_wifi"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi</string>
+    <!-- Spn during Wi-Fi Calling: "WiFi Calling | <operator>" -->
+    <string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
+    <!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
+    <string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi Calling" -->
+    <string name="wfcSpnFormat_wifi_calling">Wi-Fi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi" -->
+    <string name="wfcSpnFormat_wifi">Wi-Fi</string>
+    <!-- Spn during Wi-Fi Calling: "WiFi Calling" (without hyphen) -->
+    <string name="wfcSpnFormat_wifi_calling_wo_hyphen">WiFi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "VoWifi" -->
+    <string name="wfcSpnFormat_vowifi">VoWifi</string>
+
+    <!--
+        {0} is one of "bearerServiceCode*"
+        {1} is dialing number
+        {2} is time in seconds
+
+        cfTemplateRegistered and cfTemplateRegisteredTime mean that a phone number
+        has been set but forwarding is not on.
+    --> <skip />
+    <!-- Displayed when the call forwarding query was not able to be forwarded. -->
+    <string name="cfTemplateNotForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: Not forwarded</string>
+    <!-- Displayed when the call forwarding query was forwarded. -->
+    <string name="cfTemplateForwarded"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g></string>
+    <!-- Displayed when the call forwarding query will be forwarded after some time. -->
+    <string name="cfTemplateForwardedTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: <xliff:g id="dialing_number">{1}</xliff:g> after <xliff:g id="time_delay">{2}</xliff:g> seconds</string>
+    <!-- Displayed when the call forwarding query was set but forwarding is not enabled. -->
+    <string name="cfTemplateRegistered"><xliff:g id="bearer_service_code">{0}</xliff:g>: Not forwarded</string>
+    <!-- Displayed when the call forwarding query was set but forwarding is not enabled. -->
+    <string name="cfTemplateRegisteredTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: Not forwarded</string>
+
+    <!-- SMS per-application rate control Dialog --> <skip />
+    <!-- SMS_DIALOG: An SMS dialog is shown if an application tries to send too many SMSes.  This is the title of that dialog. -->
+    <string name="sms_control_title">Sending SMS messages</string>
+    <!-- See SMS_DIALOG.  This is the message shown in that dialog. [CHAR LIMIT=NONE] -->
+    <string name="sms_control_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?</string>
+    <!-- See SMS_DIALOG.  This is a button choice to allow sending the SMSes. [CHAR LIMIT=30] -->
+    <string name="sms_control_yes">Allow</string>
+    <!-- See SMS_DIALOG.  This is a button choice to disallow sending the SMSes. [CHAR LIMIT=30] -->
+    <string name="sms_control_no">Deny</string>
+
+    <!-- SMS short code verification dialog. --> <skip />
+    <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
+    <string name="sms_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>.</string>
+    <!-- Message details for the SMS short code confirmation dialog (possible premium short code). [CHAR LIMIT=NONE] -->
+    <string name="sms_short_code_details">This <b>may cause charges</b> on your mobile account.</string>
+    <!-- Message details for the SMS short code confirmation dialog (premium short code). [CHAR LIMIT=NONE] -->
+    <string name="sms_premium_short_code_details"><b>This will cause charges on your mobile account.</b></string>
+    <!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_allow">Send</string>
+    <!-- Text of the cancel button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_deny">Cancel</string>
+    <!-- Text of the checkbox for the SMS short code confirmation dialog to remember the user's choice. [CHAR LIMIT=40] -->
+    <string name="sms_short_code_remember_choice">Remember my choice</string>
+    <!-- Text shown when remember checkbox is checked to inform the user how they may undo the setting. [CHAR LIMIT=40] -->
+    <string name="sms_short_code_remember_undo_instruction">You can change this later in Settings\u00A0>\u00A0Apps"</string>
+
+    <!-- Text of the approval button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_always_allow">Always Allow</string>
+    <!-- Text of the cancel button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_never_allow">Never Allow</string>
+
+    <!-- SIM swap and device reboot Dialog --> <skip />
+    <!-- See SIM_REMOVED_DIALOG.  This is the title of that dialog. -->
+    <string name="sim_removed_title">SIM card removed</string>
+    <!-- See SIM_REMOVED_DIALOG.  This is the message of that dialog. -->
+    <string name="sim_removed_message">The mobile network will be unavailable until you restart with a valid SIM card inserted.</string>
+    <!-- See SIM_REMOVED_DIALOG.  This is the button of that dialog. -->
+    <string name="sim_done_button">Done</string>
+    <!-- See SIM_ADDED_DIALOG.  This is the title of that dialog. -->
+    <string name="sim_added_title">SIM card added</string>
+    <!-- See SIM_ADDED_DIALOG.  This is the message of that dialog. -->
+    <string name="sim_added_message">Restart your device to access the mobile network.</string>
+    <!-- See SIM_ADDED_DIALOG.  This is the button of that dialog. -->
+    <string name="sim_restart_button">Restart</string>
+    <!-- See Carrier_App_Dialog. This is the message of that dialog. -->
+    <string name="install_carrier_app_notification_title">Activate mobile service</string>
+    <!-- Notification message that shows when the user inserts a SIM card that requires a carrier app download, but the app name is unknown -->
+    <string name="install_carrier_app_notification_text">Download the carrier app to activate your new SIM</string>
+    <!-- Notification message that shows when the user inserts a SIM card that requires a carrier app download.  App name is known -->
+    <string name="install_carrier_app_notification_text_app_name">Download the <xliff:g id="app_name">%1$s</xliff:g> app to activate your new SIM</string>
+
+    <!-- See Carrier_App_Notification. This is the button of that dialog. -->
+    <string name="install_carrier_app_notification_button">Download app</string>
+    <!-- See carrier_app_notification. This is the headline. -->
+    <string name="carrier_app_notification_title">New SIM inserted</string>
+    <string name="carrier_app_notification_text">Tap to set it up</string>
+
+    <!-- STK sending DTMF, SMS, USSD, SS -->
+    <string name="sending">Sending\u2026</string>
+
+    <!-- STK launch Browser -->
+    <string name="launchBrowserDefault">Launch Browser?</string>
+
+    <!-- STK setup Call -->
+    <string name="SetupCallDefault">Accept call?</string>
+
+    <!-- Displayed when the USSD/SS request is modified by STK CC to a
+    different request. This will be displayed in a toast. -->
+    <string name="stk_cc_ussd_to_dial">USSD request changed to regular call</string>
+    <string name="stk_cc_ussd_to_ss">USSD request changed to SS request</string>
+    <string name="stk_cc_ussd_to_ussd">Changed to new USSD request</string>
+    <string name="stk_cc_ussd_to_dial_video">USSD request changed to video call</string>
+    <string name="stk_cc_ss_to_dial">SS request changed to regular call</string>
+    <string name="stk_cc_ss_to_dial_video">SS request changed to video call</string>
+    <string name="stk_cc_ss_to_ussd">SS request changed to USSD request</string>
+    <string name="stk_cc_ss_to_ss">Changed to new SS request</string>
+
+    <!-- Notification title shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
+    <string name="new_sms_notification_title">You have new messages</string>
+    <!-- Notification content shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
+    <string name="new_sms_notification_content">Open SMS app to view</string>
+
+    <!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
+    <string name="conference_call">Conference Call</string>
+
+    <!-- Title of notification when UE fails CS registration with MM reject cause code from network. -->
+    <string name="mmcc_authentication_reject">SIM not allowed for voice</string>
+    <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned for voice</string>
+    <string name="mmcc_illegal_ms">SIM not allowed for voice</string>
+    <string name="mmcc_illegal_me">Phone not allowed for voice</string>
+
+    <!-- Title of notification when UE fails to register network with MM reject cause code when multiple SIMs are active. -->
+    <string name="mmcc_authentication_reject_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
+    <string name="mmcc_imsi_unknown_in_hlr_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not provisioned</string>
+    <string name="mmcc_illegal_ms_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
+    <string name="mmcc_illegal_me_msim_template">SIM <xliff:g id="simNumber" example="1">%d</xliff:g> not allowed</string>
+
+    <!-- Shown in the lock screen when there is emergency calls only mode. -->
+    <string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
+
+    <!-- On the keyguard screen, it shows the carrier the phone is connected to.  This is displayed if the phone is not connected to a carrier.-->
+    <string name="lockscreen_carrier_default">No service</string>
+
+    <!-- Status message for a remote route attempting to connect -->
+    <string name="media_route_status_connecting">Connecting...</string>
+
+    <!-- WFC, summary for Disabled -->
+    <string name="wifi_calling_off_summary">Off</string>
+    <!-- WFC, summary for Wi-Fi Preferred -->
+    <string name="wfc_mode_wifi_preferred_summary">Call over Wi-Fi</string>
+    <!-- WFC, summary for Mobile data Preferred -->
+    <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string>
+    <!-- WFC, summary for Wi-Fi Only -->
+    <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string>
+
+    <!-- Sequence of characters used to separate message strings in keyguard. Typically just em-dash
+         with spaces on either side. [CHAR LIMIT=3] -->
+    <string name="kg_text_message_separator" product="default">" \u2014 "</string>
+
+</resources>
diff --git a/src/java/com/android/internal/telephony/AppSmsManager.java b/src/java/com/android/internal/telephony/AppSmsManager.java
index 30de674..f473c9a 100644
--- a/src/java/com/android/internal/telephony/AppSmsManager.java
+++ b/src/java/com/android/internal/telephony/AppSmsManager.java
@@ -20,16 +20,10 @@
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
-import android.app.role.IRoleManager;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.IFinancialSmsCallback;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
@@ -147,24 +141,6 @@
     }
 
     /**
-     * Get filtered SMS messages for financial app.
-     */
-    public void getSmsMessagesForFinancialApp(
-            String callingPkg, Bundle params, final IFinancialSmsCallback callback) {
-        try {
-            IRoleManager roleManager = IRoleManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
-            roleManager.getSmsMessagesForFinancialApp(callingPkg, params, callback);
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "Receive RemoteException.");
-            // do nothing
-        } catch (ServiceNotFoundException e) {
-            Log.e(LOG_TAG, "Service not found.");
-            // do nothing
-        }
-    }
-
-    /**
      * Handle an incoming SMS_DELIVER_ACTION intent if it is an app-only SMS.
      */
     public boolean handleSmsReceivedIntent(Intent intent) {
diff --git a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
index 820a052..34fae4a 100644
--- a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
+++ b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
@@ -19,12 +19,12 @@
 import android.content.Context;
 import android.os.AsyncTask;
 import android.provider.BlockedNumberContract;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * An {@link AsyncTask} that notifies the Blocked number provider that emergency services were
- * contacted. See {@link BlockedNumberContract.SystemContract#notifyEmergencyContact(Context)}
- * for details.
+ * contacted.
  * {@hide}
  */
 public class AsyncEmergencyContactNotifier extends AsyncTask<Void, Void, Void> {
@@ -39,10 +39,27 @@
     @Override
     protected Void doInBackground(Void... params) {
         try {
-            BlockedNumberContract.SystemContract.notifyEmergencyContact(mContext);
+            notifyEmergencyContact(mContext);
         } catch (Exception e) {
             Rlog.e(TAG, "Exception notifying emergency contact: " + e);
         }
         return null;
     }
+
+    /**
+     * Notifies the provider that emergency services were contacted by the user.
+     */
+    private void notifyEmergencyContact(Context context) {
+        try {
+            Rlog.i("notifyEmergencyContact; caller=%s", context.getOpPackageName());
+            context.getContentResolver().call(
+                    BlockedNumberContract.AUTHORITY_URI,
+                    BlockedNumberContract.METHOD_NOTIFY_EMERGENCY_CONTACT,
+                    null, null);
+        } catch (NullPointerException | IllegalArgumentException ex) {
+            // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+            // either of these happen.
+            Rlog.w(null, "notifyEmergencyContact: provider not ready.");
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index f0c6262..b7eeaf4 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -17,7 +17,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
@@ -101,6 +101,7 @@
     protected RegistrantList mPhysicalChannelConfigurationRegistrants = new RegistrantList();
     protected RegistrantList mLceInfoRegistrants = new RegistrantList();
     protected RegistrantList mEmergencyNumberListRegistrants = new RegistrantList();
+    protected RegistrantList mUiccApplicationsEnablementRegistrants = new RegistrantList();
 
     @UnsupportedAppUsage
     protected Registrant mGsmSmsRegistrant;
@@ -140,6 +141,7 @@
     protected Registrant mCatCcAlphaRegistrant;
     @UnsupportedAppUsage
     protected Registrant mSsRegistrant;
+    protected Registrant mRegistrationFailedRegistrant;
 
     // Preferred network type received from PhoneFactory.
     // This is used when establishing a connection to the
@@ -559,6 +561,16 @@
     }
 
     @Override
+    public void setOnRegistrationFailed(Handler h, int what, Object obj) {
+        mRegistrationFailedRegistrant = new Registrant(h, what, obj);
+    }
+
+    @Override
+    public void unSetOnRegistrationFailed(Handler h) {
+        mRegistrationFailedRegistrant.clear();
+    }
+
+    @Override
     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj) {
         mVoicePrivacyOnRegistrants.addUnique(h, what, obj);
     }
@@ -754,7 +766,6 @@
 
     @Override
     public void registerForNetworkScanResult(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
         mRilNetworkScanResultRegistrants.addUnique(h, what, obj);
     }
 
@@ -953,7 +964,7 @@
 
     @Override
     public void registerForModemReset(Handler h, int what, Object obj) {
-        mModemResetRegistrants.add(new Registrant(h, what, obj));
+        mModemResetRegistrants.addUnique(h, what, obj);
     }
 
     @Override
@@ -963,7 +974,7 @@
 
     @Override
     public void registerForPcoData(Handler h, int what, Object obj) {
-        mPcoDataRegistrants.add(new Registrant(h, what, obj));
+        mPcoDataRegistrants.addUnique(h, what, obj);
     }
 
     @Override
@@ -973,7 +984,7 @@
 
     @Override
     public void registerForCarrierInfoForImsiEncryption(Handler h, int what, Object obj) {
-        mCarrierInfoForImsiEncryptionRegistrants.add(new Registrant(h, what, obj));
+        mCarrierInfoForImsiEncryptionRegistrants.addUnique(h, what, obj);
     }
 
     @Override
@@ -983,8 +994,6 @@
 
     @Override
     public void registerForNattKeepaliveStatus(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-
         synchronized (mStateMonitor) {
             mNattKeepaliveStatusRegistrants.addUnique(h, what, obj);
         }
@@ -996,4 +1005,26 @@
             mNattKeepaliveStatusRegistrants.remove(h);
         }
     }
+
+    /**
+     * Registers the handler for RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED events.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    @Override
+    public void registerUiccApplicationEnablementChanged(Handler h, int what, Object obj) {
+        mUiccApplicationsEnablementRegistrants.addUnique(h, what, obj);
+    }
+
+    /**
+     * Unregisters the handler for RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED events.
+     *
+     * @param h Handler for notification message.
+     */
+    @Override
+    public void unregisterUiccApplicationEnablementChanged(Handler h) {
+        mUiccApplicationsEnablementRegistrants.remove(h);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/BlockChecker.java b/src/java/com/android/internal/telephony/BlockChecker.java
index 1a63db6..f6b6356 100644
--- a/src/java/com/android/internal/telephony/BlockChecker.java
+++ b/src/java/com/android/internal/telephony/BlockChecker.java
@@ -3,7 +3,8 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.BlockedNumberContract;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * {@hide} Checks for blocked phone numbers against {@link BlockedNumberContract}
@@ -67,19 +68,76 @@
         long startTimeNano = System.nanoTime();
 
         try {
-            blockStatus = BlockedNumberContract.SystemContract.shouldSystemBlockNumber(
-                    context, phoneNumber, extras);
+            blockStatus = shouldSystemBlockNumber(context, phoneNumber, extras);
             if (blockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED) {
                 Rlog.d(TAG, phoneNumber + " is blocked.");
             }
         } catch (Exception e) {
             Rlog.e(TAG, "Exception checking for blocked number: " + e);
         }
-
         int durationMillis = (int) ((System.nanoTime() - startTimeNano) / 1000000);
         if (durationMillis > 500 || VDBG) {
             Rlog.d(TAG, "Blocked number lookup took: " + durationMillis + " ms.");
         }
         return blockStatus;
     }
+
+    /**
+     * Returns {@code true} if {@code phoneNumber} is blocked taking
+     * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services
+     * have not been contacted recently and enhanced call blocking not been enabled, this
+     * method is equivalent to {@link #isBlocked(Context, String)}.
+     *
+     * @param context the context of the caller.
+     * @param phoneNumber the number to check.
+     * @param extras the extra attribute of the number.
+     * @return result code indicating if the number should be blocked, and if so why.
+     *         Valid values are: {@link #STATUS_NOT_BLOCKED}, {@link #STATUS_BLOCKED_IN_LIST},
+     *         {@link #STATUS_BLOCKED_NOT_IN_CONTACTS}, {@link #STATUS_BLOCKED_PAYPHONE},
+     *         {@link #STATUS_BLOCKED_RESTRICTED}, {@link #STATUS_BLOCKED_UNKNOWN_NUMBER}.
+     */
+    private static int shouldSystemBlockNumber(Context context, String phoneNumber,
+                                              Bundle extras) {
+        try {
+            String caller = context.getOpPackageName();
+            final Bundle res = context.getContentResolver().call(
+                    BlockedNumberContract.AUTHORITY_URI,
+                    BlockedNumberContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER,
+                    phoneNumber, extras);
+            int blockResult = res != null ? res.getInt(BlockedNumberContract.RES_BLOCK_STATUS,
+                    BlockedNumberContract.STATUS_NOT_BLOCKED) :
+                    BlockedNumberContract.STATUS_NOT_BLOCKED;
+            Rlog.d(TAG, "shouldSystemBlockNumber: number=" + Rlog.pii(TAG, phoneNumber)
+                    + "caller=" + caller + "result=" + blockStatusToString(blockResult));
+            return blockResult;
+        } catch (NullPointerException | IllegalArgumentException ex) {
+            // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
+            // either of these happen.
+            Rlog.w(null, "shouldSystemBlockNumber: provider not ready.");
+            return BlockedNumberContract.STATUS_NOT_BLOCKED;
+        }
+    }
+
+    /**
+     * Converts a block status constant to a string equivalent for logging.
+     * @hide
+     */
+    private static String blockStatusToString(int blockStatus) {
+        switch (blockStatus) {
+            case BlockedNumberContract.STATUS_NOT_BLOCKED:
+                return "not blocked";
+            case BlockedNumberContract.STATUS_BLOCKED_IN_LIST:
+                return "blocked - in list";
+            case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED:
+                return "blocked - restricted";
+            case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER:
+                return "blocked - unknown";
+            case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE:
+                return "blocked - payphone";
+            case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS:
+                return "blocked - not in contacts";
+        }
+        return "unknown";
+    }
+
 }
diff --git a/src/java/com/android/internal/telephony/BtSmsInterfaceManager.java b/src/java/com/android/internal/telephony/BtSmsInterfaceManager.java
index 67e07bc..ea6a6ec 100644
--- a/src/java/com/android/internal/telephony/BtSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/BtSmsInterfaceManager.java
@@ -17,12 +17,11 @@
 
 package com.android.internal.telephony;
 
-import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothMapClient;
 import android.bluetooth.BluetoothProfile;
+import android.content.Context;
 import android.net.Uri;
 import android.telecom.PhoneAccount;
 import android.telephony.SmsManager;
@@ -40,7 +39,7 @@
     /**
      * Sends text through connected Bluetooth device
      */
-    public void sendText(String destAddr, String text, PendingIntent sentIntent,
+    public void sendText(Context context, String destAddr, String text, PendingIntent sentIntent,
             PendingIntent deliveryIntent, SubscriptionInfo info) {
         BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
         if (btAdapter == null) {
@@ -54,7 +53,7 @@
             sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_INVALID_BLUETOOTH_ADDRESS);
             return;
         }
-        btAdapter.getProfileProxy(ActivityThread.currentApplication().getApplicationContext(),
+        btAdapter.getProfileProxy(context.getApplicationContext(),
                 new MapMessageSender(destAddr, text, device, sentIntent, deliveryIntent),
                 BluetoothProfile.MAP_CLIENT);
     }
@@ -99,14 +98,19 @@
             if (profile != BluetoothProfile.MAP_CLIENT) {
                 return;
             }
-            BluetoothMapClient mapProfile = (BluetoothMapClient) proxy;
+            // Comment out the method for mainline (b/143848423). The profile is not for a phone,
+            // so it will not be enabled.
+/*            BluetoothMapClient mapProfile = (BluetoothMapClient) proxy;
             if (mMessage != null) {
                 Log.d(LOG_TAG, "Sending message thru bluetooth");
                 mapProfile.sendMessage(mDevice, mDestAddr, mMessage, mSentIntent, mDeliveryIntent);
                 mMessage = null;
             }
             BluetoothAdapter.getDefaultAdapter()
-                    .closeProfileProxy(BluetoothProfile.MAP_CLIENT, mapProfile);
+                    .closeProfileProxy(BluetoothProfile.MAP_CLIENT, mapProfile);*/
+            if (mMessage != null) {
+                throw new RuntimeException("Can't send message through BluetoothMapClient");
+            }
         }
 
         @Override
diff --git a/src/java/com/android/internal/telephony/Call.java b/src/java/com/android/internal/telephony/Call.java
index a9d1bd5..d3cb584 100644
--- a/src/java/com/android/internal/telephony/Call.java
+++ b/src/java/com/android/internal/telephony/Call.java
@@ -16,13 +16,13 @@
 
 package com.android.internal.telephony;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import android.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+import android.compat.annotation.UnsupportedAppUsage;
 
 import com.android.ims.internal.ConferenceParticipant;
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * {@hide}
@@ -110,6 +110,8 @@
     @UnsupportedAppUsage
     public abstract void hangup() throws CallStateException;
 
+    public abstract void hangup(@android.telecom.Call.RejectReason int rejectReason)
+            throws CallStateException;
 
     /**
      * hasConnection
diff --git a/src/java/com/android/internal/telephony/CallFailCause.java b/src/java/com/android/internal/telephony/CallFailCause.java
index 6e4e01c..6a36197 100644
--- a/src/java/com/android/internal/telephony/CallFailCause.java
+++ b/src/java/com/android/internal/telephony/CallFailCause.java
@@ -149,9 +149,43 @@
     int DIAL_MODIFIED_TO_SS   = 245;
     int DIAL_MODIFIED_TO_DIAL = 246;
 
+    // The call cannot be established because RADIO is OFF
+    int RADIO_OFF = 247;
+
+    // The call cannot be established because of no valid SIM
+    int NO_VALID_SIM = 249;
+
+    // The call is dropped or failed internally by modem
+    int RADIO_INTERNAL_ERROR = 250;
+
+    // Call failed because of UE timer expired while waiting for a response from network
+    int NETWORK_RESP_TIMEOUT = 251;
+
+    // Call failed because of a network reject
+    int NETWORK_REJECT                                   = 252;
+    // Call failed because of radio access failure. ex. RACH failure
+    int RADIO_ACCESS_FAILURE                             = 253;
+    // Call failed/dropped because of a Radio Link Failure (RLF).
+    int RADIO_LINK_FAILURE                               = 254;
+    // Call failed/dropped because of radio link lost
+    int RADIO_LINK_LOST                                  = 255;
+    // Call failed because of a radio uplink issue
+    int RADIO_UPLINK_FAILURE                             = 256;
+    // Call failed because of a RRC (Radio Resource Control) connection setup failure
+    int RADIO_SETUP_FAILURE                              = 257;
+    // Call failed/dropped because of RRC (Radio Resource Control) connection release from NW
+    int RADIO_RELEASE_NORMAL                             = 258;
+    /**
+     * Call failed/dropped because of RRC (Radio Resource Control) abnormally released by
+     * modem/network.
+     */
+    int RADIO_RELEASE_ABNORMAL                           = 259;
     //Access class blocked - TS 31.121 5.2.1
     int ACCESS_CLASS_BLOCKED = 260;
 
+    /** Call failed/dropped because of a network detach. */
+    int NETWORK_DETACH                                   = 261;
+
     //Emergency Redial
     int EMERGENCY_TEMP_FAILURE = 325;
     int EMERGENCY_PERM_FAILURE = 326;
@@ -171,6 +205,260 @@
     // Access Blocked by CDMA Network.
     int CDMA_ACCESS_BLOCKED            = 1009;
 
+    /** Mapped from ImsReasonInfo */
+    // The passed argument is an invalid
+    int LOCAL_ILLEGAL_ARGUMENT                           = 1200;
+    // The operation is invoked in invalid call state
+    int LOCAL_ILLEGAL_STATE                              = 1201;
+    // IMS service internal error
+    int LOCAL_INTERNAL_ERROR                             = 1202;
+    // IMS service goes down (service connection is lost)
+    int LOCAL_IMS_SERVICE_DOWN                           = 1203;
+    // No pending incoming call exists
+    int LOCAL_NO_PENDING_CALL                            = 1204;
+    // Service unavailable; by power off
+    int LOCAL_POWER_OFF                                  = 1205;
+    // Service unavailable; by low battery
+    int LOCAL_LOW_BATTERY                                = 1206;
+    // Service unavailable; by out of service (data service state)
+    int LOCAL_NETWORK_NO_SERVICE                         = 1207;
+
+    /* Service unavailable; by no LTE coverage
+     * (VoLTE is not supported even though IMS is registered)
+     */
+    int LOCAL_NETWORK_NO_LTE_COVERAGE                    = 1208;
+    // Service unavailable; by located in roaming area
+    int LOCAL_NETWORK_ROAMING                            = 1209;
+    // Service unavailable; by IP changed
+    int LOCAL_NETWORK_IP_CHANGED                         = 1210;
+    // Service unavailable; other
+    int LOCAL_SERVICE_UNAVAILABLE                        = 1211;
+    // Service unavailable; IMS connection is lost (IMS is not registered)
+    int LOCAL_NOT_REGISTERED                             = 1212;
+    // Max call exceeded
+    int LOCAL_MAX_CALL_EXCEEDED                          = 1213;
+    // Call decline
+    int LOCAL_CALL_DECLINE                               = 1214;
+    // SRVCC is in progress
+    int LOCAL_CALL_VCC_ON_PROGRESSING                    = 1215;
+    // Resource reservation is failed (QoS precondition)
+    int LOCAL_CALL_RESOURCE_RESERVATION_FAILED           = 1216;
+    /** Retry CS call; VoLTE service can't be provided by the network or remote end
+     *  Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
+     */
+    int LOCAL_CALL_CS_RETRY_REQUIRED                     = 1217;
+    // Retry VoLTE call; VoLTE service can't be provided by the network temporarily
+    int LOCAL_CALL_VOLTE_RETRY_REQUIRED                  = 1218;
+    // IMS call is already terminated (in TERMINATED state)
+    int LOCAL_CALL_TERMINATED                            = 1219;
+    // Handover not feasible
+    int LOCAL_HO_NOT_FEASIBLE                            = 1220;
+
+    // 1xx waiting timer is expired after sending INVITE request (MO only)
+    int TIMEOUT_1XX_WAITING                              = 1221;
+    /** User no answer during call setup operation (MO/MT)
+     *  MO : 200 OK to INVITE request is not received,
+     *  MT : No action from user after alerting the call
+     */
+    int TIMEOUT_NO_ANSWER                                = 1222;
+    /** User no answer during call update operation (MO/MT)
+     *  MO : 200 OK to re-INVITE request is not received,
+     *  MT : No action from user after alerting the call
+     */
+    int TIMEOUT_NO_ANSWER_CALL_UPDATE                    = 1223;
+
+    /**
+     * STATUSCODE (SIP response code) (IMS -> Telephony)
+     */
+    // SIP request is redirected
+    int SIP_REDIRECTED                                   = 1300;
+    /** 4xx responses */
+    // 400 : Bad Request
+    int SIP_BAD_REQUEST                                  = 1310;
+    // 403 : Forbidden
+    int SIP_FORBIDDEN                                    = 1311;
+    // 404 : Not Found
+    int SIP_NOT_FOUND                                    = 1312;
+    /** 415 : Unsupported Media Type
+     *  416 : Unsupported URI Scheme
+     *  420 : Bad Extension
+     */
+    int SIP_NOT_SUPPORTED                                = 1313;
+    // 408 : Request Timeout
+    int SIP_REQUEST_TIMEOUT                              = 1314;
+    // 480 : Temporarily Unavailable
+    int SIP_TEMPRARILY_UNAVAILABLE                       = 1315;
+    // 484 : Address Incomplete
+    int SIP_BAD_ADDRESS                                  = 1316;
+    /** 486 : Busy Here
+     *  600 : Busy Everywhere
+     */
+    int SIP_BUSY                                         = 1317;
+    // 487 : Request Terminated
+    int SIP_REQUEST_CANCELLED                            = 1318;
+    /** 406 : Not Acceptable
+     *  488 : Not Acceptable Here
+     *  606 : Not Acceptable
+     */
+    int SIP_NOT_ACCEPTABLE                               = 1319;
+    /** 410 : Gone
+     *  604 : Does Not Exist Anywhere
+     */
+    int SIP_NOT_REACHABLE                                = 1320;
+    // Others
+    int SIP_CLIENT_ERROR                                 = 1321;
+    // 481 : Transaction Does Not Exist
+    int SIP_TRANSACTION_DOES_NOT_EXIST                   = 1322;
+    /** 5xx responses
+     *  501 : Server Internal Error
+     */
+    int SIP_SERVER_INTERNAL_ERROR                        = 1330;
+    // 503 : Service Unavailable
+    int SIP_SERVICE_UNAVAILABLE                          = 1331;
+    // 504 : Server Time-out
+    int SIP_SERVER_TIMEOUT                               = 1332;
+    // Other
+    int SIP_SERVER_ERROR                                 = 1333;
+    /** 6xx responses
+     *  603 : Decline
+     */
+    int SIP_USER_REJECTED                                = 1340;
+    // Others
+    int SIP_GLOBAL_ERROR                                 = 1341;
+    // Emergency failure
+    int IMS_EMERGENCY_TEMP_FAILURE                       = 1342;
+    int IMS_EMERGENCY_PERM_FAILURE                       = 1343;
+    // Media resource initialization failed
+    int MEDIA_INIT_FAILED                                = 1400;
+    // RTP timeout (no audio / video traffic in the session)
+    int MEDIA_NO_DATA                                    = 1401;
+    // Media is not supported; so dropped the call
+    int MEDIA_NOT_ACCEPTABLE                             = 1402;
+    // Unknown media related errors
+    int MEDIA_UNSPECIFIED                                = 1403;
+    // User triggers the call end
+    int USER_TERMINATED                                  = 1500;
+    // No action while an incoming call is ringing
+    int USER_NOANSWER                                    = 1501;
+    // User ignores an incoming call
+    int USER_IGNORE                                      = 1502;
+    // User declines an incoming call
+    int USER_DECLINE                                     = 1503;
+    // Device declines/ends a call due to low battery
+    int LOW_BATTERY                                      = 1504;
+    // Device declines call due to blacklisted call ID
+    int BLACKLISTED_CALL_ID                              = 1505;
+    // The call is terminated by the network or remote user
+    int USER_TERMINATED_BY_REMOTE                        = 1510;
+
+    /**
+     * UT
+     */
+    int UT_NOT_SUPPORTED                                 = 1800;
+    int UT_SERVICE_UNAVAILABLE                           = 1801;
+    int UT_OPERATION_NOT_ALLOWED                         = 1802;
+    int UT_NETWORK_ERROR                                 = 1803;
+    int UT_CB_PASSWORD_MISMATCH                          = 1804;
+
+    /**
+     * ECBM
+     */
+    int ECBM_NOT_SUPPORTED                               = 1900;
+
+    /**
+     * Fail code used to indicate that Multi-endpoint is not supported by the Ims framework.
+     */
+    int MULTIENDPOINT_NOT_SUPPORTED                      = 1901;
+
+    /**
+     * CALL DROP error codes (Call could drop because of many reasons like Network not available,
+     *  handover, failed, etc)
+     */
+
+    /**
+     * CALL DROP error code for the case when a device is ePDG capable and when the user is on an
+     * active wifi call and at the edge of coverage and there is no qualified LTE network available
+     * to handover the call to. We get a handover NOT_TRIGERRED message from the modem. This error
+     * code is received as part of the handover message.
+     */
+    int CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE               = 2000;
+
+    // MT call has ended due to a release from the network because the call was answered elsewhere
+    int ANSWERED_ELSEWHERE                               = 2100;
+
+    // For MultiEndpoint - Call Pull request has failed
+    int CALL_PULL_OUT_OF_SYNC                            = 2101;
+
+    // For MultiEndpoint - Call has been pulled from primary to secondary
+    int CALL_PULLED                                      = 2102;
+
+    /**
+     * Supplementary services (HOLD/RESUME) failure error codes.
+     * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+     */
+    int SUPP_SVC_FAILED                                  = 2300;
+    int SUPP_SVC_CANCELLED                               = 2301;
+    int SUPP_SVC_REINVITE_COLLISION                      = 2302;
+
+    //DPD Procedure received no response or send failed
+    int IWLAN_DPD_FAILURE                                = 2400;
+
+    // Establishment of the ePDG Tunnel Failed
+    int EPDG_TUNNEL_ESTABLISH_FAILURE                    = 2500;
+
+    // Re-keying of the ePDG Tunnel Failed; may not always result in teardown
+    int EPDG_TUNNEL_REKEY_FAILURE                        = 2501;
+
+    // Connection to the packet gateway is lost
+    int EPDG_TUNNEL_LOST_CONNECTION                      = 2502;
+
+    /**
+     * The maximum number of calls allowed has been reached.  Used in a multi-endpoint scenario
+     * where the number of calls across all connected devices has reached the maximum.
+     */
+    int MAXIMUM_NUMBER_OF_CALLS_REACHED                  = 2503;
+
+    /**
+     * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
+     * declined the call.  Used in a multi-endpoint scenario where a remote device declined an
+     * incoming call.
+     */
+    int REMOTE_CALL_DECLINE                              = 2504;
+
+    /**
+     * Indicates the call was disconnected due to the user reaching their data limit.
+     */
+    int DATA_LIMIT_REACHED                               = 2505;
+
+    /**
+     * Indicates the call was disconnected due to the user disabling cellular data.
+     */
+    int DATA_DISABLED                                    = 2506;
+
+    /**
+     * Indicates a call was disconnected due to loss of wifi signal.
+     */
+    int WIFI_LOST                                        = 2507;
+
+
+    /* OEM specific error codes. To be used by OEMs when they don't want to
+       reveal error code which would be replaced by ERROR_UNSPECIFIED */
+    int OEM_CAUSE_1                                      = 0xf001;
+    int OEM_CAUSE_2                                      = 0xf002;
+    int OEM_CAUSE_3                                      = 0xf003;
+    int OEM_CAUSE_4                                      = 0xf004;
+    int OEM_CAUSE_5                                      = 0xf005;
+    int OEM_CAUSE_6                                      = 0xf006;
+    int OEM_CAUSE_7                                      = 0xf007;
+    int OEM_CAUSE_8                                      = 0xf008;
+    int OEM_CAUSE_9                                      = 0xf009;
+    int OEM_CAUSE_10                                     = 0xf00a;
+    int OEM_CAUSE_11                                     = 0xf00b;
+    int OEM_CAUSE_12                                     = 0xf00c;
+    int OEM_CAUSE_13                                     = 0xf00d;
+    int OEM_CAUSE_14                                     = 0xf00e;
+    int OEM_CAUSE_15                                     = 0xf00f;
+
     int ERROR_UNSPECIFIED = 0xffff;
 
 }
diff --git a/src/java/com/android/internal/telephony/CallForwardInfo.java b/src/java/com/android/internal/telephony/CallForwardInfo.java
index 7d4f587..2a8319b 100644
--- a/src/java/com/android/internal/telephony/CallForwardInfo.java
+++ b/src/java/com/android/internal/telephony/CallForwardInfo.java
@@ -16,8 +16,9 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+import android.compat.annotation.UnsupportedAppUsage;
+
+import com.android.telephony.Rlog;
 
 /**
  * See also RIL_CallForwardInfo in include/telephony/ril.h
diff --git a/src/java/com/android/internal/telephony/CallManager.java b/src/java/com/android/internal/telephony/CallManager.java
index 5112376..151a4bf 100644
--- a/src/java/com/android/internal/telephony/CallManager.java
+++ b/src/java/com/android/internal/telephony/CallManager.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
@@ -25,19 +25,16 @@
 import android.os.RegistrantList;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.sip.SipPhone;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 
-
-
 /**
  * @hide
  *
diff --git a/src/java/com/android/internal/telephony/CallStateException.java b/src/java/com/android/internal/telephony/CallStateException.java
index 1356a2b..3fdc444 100644
--- a/src/java/com/android/internal/telephony/CallStateException.java
+++ b/src/java/com/android/internal/telephony/CallStateException.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/CallTracker.java b/src/java/com/android/internal/telephony/CallTracker.java
index f24b3c8..9e81bcc 100644
--- a/src/java/com/android/internal/telephony/CallTracker.java
+++ b/src/java/com/android/internal/telephony/CallTracker.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
diff --git a/src/java/com/android/internal/telephony/CarrierActionAgent.java b/src/java/com/android/internal/telephony/CarrierActionAgent.java
index c01c9d4..a87925d 100644
--- a/src/java/com/android/internal/telephony/CarrierActionAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierActionAgent.java
@@ -27,13 +27,13 @@
 import android.os.RegistrantList;
 import android.provider.Settings;
 import android.provider.Telephony;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.util.LocalLog;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -89,7 +89,7 @@
             final String action = intent.getAction();
             final String iccState = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
             if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)){
-                if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
+                if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                     // ignore rebroadcast since carrier apps are direct boot aware.
                     return;
                 }
@@ -227,7 +227,7 @@
         carrierActionSetRadioEnabled(true);
         // notify configured carrier apps for reset
         mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(
-                new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET));
+                new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_RESET));
     }
 
     private RegistrantList getRegistrantsFromAction(int action) {
diff --git a/src/java/com/android/internal/telephony/CarrierInfoManager.java b/src/java/com/android/internal/telephony/CarrierInfoManager.java
index f645746..a125fdf 100644
--- a/src/java/com/android/internal/telephony/CarrierInfoManager.java
+++ b/src/java/com/android/internal/telephony/CarrierInfoManager.java
@@ -57,18 +57,16 @@
      *         used for encryption.
      */
     public static ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType,
-                                                                     Context context) {
+                                                                     Context context,
+                                                                     String operatorNumeric) {
         String mcc = "";
         String mnc = "";
-        final TelephonyManager telephonyManager =
-                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        String simOperator = telephonyManager.getSimOperator();
-        if (!TextUtils.isEmpty(simOperator)) {
-            mcc = simOperator.substring(0, 3);
-            mnc = simOperator.substring(3);
+        if (!TextUtils.isEmpty(operatorNumeric)) {
+            mcc = operatorNumeric.substring(0, 3);
+            mnc = operatorNumeric.substring(3);
             Log.i(LOG_TAG, "using values for mnc, mcc: " + mnc + "," + mcc);
         } else {
-            Log.e(LOG_TAG, "Invalid networkOperator: " + simOperator);
+            Log.e(LOG_TAG, "Invalid networkOperator: " + operatorNumeric);
             return null;
         }
         Cursor findCursor = null;
diff --git a/src/java/com/android/internal/telephony/CarrierResolver.java b/src/java/com/android/internal/telephony/CarrierResolver.java
index 959522f..ea31a4b 100644
--- a/src/java/com/android/internal/telephony/CarrierResolver.java
+++ b/src/java/com/android/internal/telephony/CarrierResolver.java
@@ -29,7 +29,6 @@
 import android.provider.Telephony;
 import android.service.carrier.CarrierIdentifier;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -41,6 +40,7 @@
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 0393ffa..0b9cae1 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -34,6 +34,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.carrier.CarrierService;
+import android.telephony.PackageChangeReceiver;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -41,9 +42,8 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.content.PackageMonitor;
-
 import com.android.internal.telephony.util.TelephonyUtils;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
@@ -67,7 +67,10 @@
     public SparseArray<AppBinding> mBindings = new SparseArray();
     @VisibleForTesting
     public SparseArray<String> mLastSimState = new SparseArray<>();
-    private final PackageMonitor mPackageMonitor = new CarrierServicePackageMonitor();
+    private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
+
+    // whether we have successfully bound to the service
+    private boolean mServiceBound = false;
 
     private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
         @Override
@@ -86,12 +89,14 @@
     };
 
     private static final int EVENT_REBIND = 0;
-    private static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;
+    @VisibleForTesting
+    public static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;
     @VisibleForTesting
     public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 2;
 
     @UnsupportedAppUsage
-    private Handler mHandler = new Handler() {
+    @VisibleForTesting
+    public Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             int phoneId;
@@ -124,14 +129,20 @@
 
         updateBindingsAndSimStates();
 
-        PhoneConfigurationManager.getInstance().registerForMultiSimConfigChange(
+        PhoneConfigurationManager.registerForMultiSimConfigChange(
                 mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
 
         mPackageMonitor.register(
-                context, mHandler.getLooper(), UserHandle.ALL, false /* externalStorage */);
-        mContext.registerReceiverAsUser(mUserUnlockedReceiver, UserHandle.SYSTEM,
+                context, mHandler.getLooper(), UserHandle.ALL);
+        try {
+            Context contextAsUser = mContext.createPackageContextAsUser(mContext.getPackageName(),
+                0, UserHandle.SYSTEM);
+            contextAsUser.registerReceiver(mUserUnlockedReceiver,
                 new IntentFilter(Intent.ACTION_USER_UNLOCKED), null /* broadcastPermission */,
                 mHandler);
+        } catch (PackageManager.NameNotFoundException e) {
+            loge("Package name not found: " + e.getMessage());
+        }
     }
 
     // Create or dispose mBindings and mLastSimState objects.
@@ -266,9 +277,12 @@
 
             String error;
             try {
-                if (mContext.bindServiceAsUser(carrierService, connection,
-                        Context.BIND_AUTO_CREATE |  Context.BIND_FOREGROUND_SERVICE,
-                        mHandler, Process.myUserHandle())) {
+                if (mContext.createContextAsUser(Process.myUserHandle(), 0)
+                        .bindService(carrierService,
+                                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                                (r) -> mHandler.post(r),
+                                connection)) {
+                    mServiceBound = true;
                     return;
                 }
 
@@ -323,8 +337,13 @@
             carrierServiceClass = null;
 
             // Actually unbind
-            log("Unbinding from carrier app");
-            mContext.unbindService(connection);
+            if (mServiceBound) {
+                log("Unbinding from carrier app");
+                mServiceBound = false;
+                mContext.unbindService(connection);
+            } else {
+                log("Not bound, skipping unbindService call");
+            }
             connection = null;
             mUnbindScheduledUptimeMillis = -1;
         }
@@ -362,24 +381,36 @@
         }
 
         @Override
+        public void onBindingDied(ComponentName name) {
+            log("Binding from carrier app died: " + name.flattenToString());
+            connected = false;
+        }
+
+        @Override
+        public void onNullBinding(ComponentName name) {
+            log("Null binding from carrier app: " + name.flattenToString());
+            connected = false;
+        }
+
+        @Override
         public String toString() {
             return "CarrierServiceConnection[connected=" + connected + "]";
         }
     }
 
-    private class CarrierServicePackageMonitor extends PackageMonitor {
+    private class CarrierServicePackageMonitor extends PackageChangeReceiver {
         @Override
-        public void onPackageAdded(String packageName, int reason) {
+        public void onPackageAdded(String packageName) {
             evaluateBinding(packageName, true /* forceUnbind */);
         }
 
         @Override
-        public void onPackageRemoved(String packageName, int reason) {
+        public void onPackageRemoved(String packageName) {
             evaluateBinding(packageName, true /* forceUnbind */);
         }
 
         @Override
-        public void onPackageUpdateFinished(String packageName, int uid) {
+        public void onPackageUpdateFinished(String packageName) {
             evaluateBinding(packageName, true /* forceUnbind */);
         }
 
@@ -389,13 +420,12 @@
         }
 
         @Override
-        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+        public void onHandleForceStop(String[] packages, boolean doit) {
             if (doit) {
                 for (String packageName : packages) {
                     evaluateBinding(packageName, true /* forceUnbind */);
                 }
             }
-            return super.onHandleForceStop(intent, packages, uid, doit);
         }
 
         private void evaluateBinding(String carrierPackageName, boolean forceUnbind) {
@@ -424,6 +454,8 @@
         Log.d(LOG_TAG, message);
     }
 
+    private static void loge(String message) { Log.e(LOG_TAG, message); }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("CarrierServiceBindHelper:");
         for (int i = 0; i < mBindings.size(); i++) {
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index e112068..112daf5 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -30,19 +30,17 @@
 import android.os.PersistableBundle;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.NotificationChannelController;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.Map;
 
-
-
 /**
  * This contains Carrier specific logic based on the states/events
  * managed in ServiceStateTracker.
@@ -166,15 +164,8 @@
         if (mSST.mSS == null) {
             return true; //something has gone wrong, return true and not show the notification.
         }
-        return (mSST.mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
-                || mSST.mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE);
-    }
-
-    private boolean isPhoneVoiceRegistered() {
-        if (mSST.mSS == null) {
-            return true; //something has gone wrong, return true and not show the notification.
-        }
-        return (mSST.mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
+        return (mSST.mSS.getState() == ServiceState.STATE_IN_SERVICE
+                || mSST.mSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE);
     }
 
     private boolean isPhoneRegisteredForWifiCalling() {
@@ -456,8 +447,8 @@
     }
 
     /**
-     * Class that defines the emergency notification, which is shown when the user is out of cell
-     * connectivity, but has wifi enabled.
+     * Class that defines the emergency notification, which is shown when Wi-Fi Calling is
+     * available.
      */
     public class EmergencyNetworkNotification implements NotificationType {
 
@@ -502,10 +493,9 @@
          */
         public boolean sendMessage() {
             Rlog.i(LOG_TAG, "EmergencyNetworkNotification: sendMessage() w/values: "
-                    + "," + isPhoneVoiceRegistered() + "," + mDelay + ","
-                    + isPhoneRegisteredForWifiCalling() + "," + mSST.isRadioOn());
-            if (mDelay == UNINITIALIZED_DELAY_VALUE || isPhoneVoiceRegistered()
-                    || !isPhoneRegisteredForWifiCalling()) {
+                    + "," + mDelay + "," + isPhoneRegisteredForWifiCalling() + ","
+                    + mSST.isRadioOn());
+            if (mDelay == UNINITIALIZED_DELAY_VALUE || !isPhoneRegisteredForWifiCalling()) {
                 return false;
             }
             return true;
@@ -525,6 +515,7 @@
                     .setContentTitle(title)
                     .setStyle(new Notification.BigTextStyle().bigText(details))
                     .setContentText(details)
+                    .setFlag(Notification.FLAG_NO_CLEAR, true)
                     .setChannelId(NotificationChannelController.CHANNEL_ID_WFC);
         }
     }
diff --git a/src/java/com/android/internal/telephony/CarrierServicesSmsFilter.java b/src/java/com/android/internal/telephony/CarrierServicesSmsFilter.java
index 24e5059..cabb009 100644
--- a/src/java/com/android/internal/telephony/CarrierServicesSmsFilter.java
+++ b/src/java/com/android/internal/telephony/CarrierServicesSmsFilter.java
@@ -27,12 +27,12 @@
 import android.service.carrier.CarrierMessagingServiceWrapper;
 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper;
 import android.service.carrier.MessagePdu;
-import android.telephony.Rlog;
 import android.util.LocalLog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.uicc.UiccCard;
 import com.android.internal.telephony.uicc.UiccController;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/src/java/com/android/internal/telephony/CarrierSignalAgent.java b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
index ad753db..8a728ad 100644
--- a/src/java/com/android/internal/telephony/CarrierSignalAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
@@ -15,6 +15,9 @@
  */
 package com.android.internal.telephony;
 
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
+
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -30,14 +33,15 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
 
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -47,9 +51,6 @@
 import java.util.Map;
 import java.util.Set;
 
-import static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
-import static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
-
 /**
  * This class act as an CarrierSignalling Agent.
  * it load registered carrier signalling receivers from carrier config, cache the result to avoid
@@ -98,11 +99,11 @@
      * This is a list of supported signals from CarrierSignalAgent
      */
     private final Set<String> mCarrierSignalList = new HashSet<>(Arrays.asList(
-            TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE,
-            TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED,
-            TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
-            TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET,
-            TelephonyIntents.ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE));
+            TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE,
+            TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED,
+            TelephonyManager.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
+            TelephonyManager.ACTION_CARRIER_SIGNAL_RESET,
+            TelephonyManager.ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE));
 
     private final LocalLog mErrorLocalLog = new LocalLog(20);
 
@@ -148,10 +149,10 @@
                             // an optimization to avoid signaling on every default network switch.
                             if (!mDefaultNetworkAvail) {
                                 if (DBG) log("Default network available: " + network);
-                                Intent intent = new Intent(TelephonyIntents
+                                Intent intent = new Intent(TelephonyManager
                                         .ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE);
                                 intent.putExtra(
-                                        TelephonyIntents.EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, true);
+                                        TelephonyManager.EXTRA_DEFAULT_NETWORK_AVAILABLE, true);
                                 notifyCarrierSignalReceivers(intent);
                                 mDefaultNetworkAvail = true;
                             }
@@ -159,10 +160,10 @@
                         @Override
                         public void onLost(Network network) {
                             if (DBG) log("Default network lost: " + network);
-                            Intent intent = new Intent(TelephonyIntents
+                            Intent intent = new Intent(TelephonyManager
                                     .ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE);
                             intent.putExtra(
-                                    TelephonyIntents.EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, false);
+                                    TelephonyManager.EXTRA_DEFAULT_NETWORK_AVAILABLE, false);
                             notifyCarrierSignalReceivers(intent);
                             mDefaultNetworkAvail = false;
                         }
diff --git a/src/java/com/android/internal/telephony/CarrierSmsUtils.java b/src/java/com/android/internal/telephony/CarrierSmsUtils.java
index a64aea7..f78d147 100644
--- a/src/java/com/android/internal/telephony/CarrierSmsUtils.java
+++ b/src/java/com/android/internal/telephony/CarrierSmsUtils.java
@@ -24,7 +24,8 @@
 import android.os.Binder;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.util.List;
 
diff --git a/src/java/com/android/internal/telephony/CellBroadcastHandler.java b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
deleted file mode 100644
index 08be268..0000000
--- a/src/java/com/android/internal/telephony/CellBroadcastHandler.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2013 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.internal.telephony;
-
-import static android.content.PermissionChecker.PERMISSION_GRANTED;
-import static android.provider.Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.app.AppOpsManager;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.PermissionChecker;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Telephony;
-import android.provider.Telephony.CellBroadcasts;
-import android.telephony.SmsCbMessage;
-import android.telephony.SubscriptionManager;
-import android.text.format.DateUtils;
-import android.util.LocalLog;
-import android.util.Log;
-
-import com.android.internal.telephony.CbGeoUtils.Geometry;
-import com.android.internal.telephony.CbGeoUtils.LatLng;
-import com.android.internal.telephony.metrics.TelephonyMetrics;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Dispatch new Cell Broadcasts to receivers. Acquires a private wakelock until the broadcast
- * completes and our result receiver is called.
- */
-public class CellBroadcastHandler extends WakeLockStateMachine {
-    private static final String EXTRA_MESSAGE = "message";
-
-    private final LocalLog mLocalLog = new LocalLog(100);
-
-    protected static final Uri CELL_BROADCAST_URI = Uri.parse("content://cellbroadcasts");
-
-    /** Uses to request the location update. */
-    public final LocationRequester mLocationRequester;
-
-    private CellBroadcastHandler(Context context, Phone phone) {
-        this("CellBroadcastHandler", context, phone);
-    }
-
-    protected CellBroadcastHandler(String debugTag, Context context, Phone phone) {
-        super(debugTag, context, phone);
-        mLocationRequester = new LocationRequester(
-                context,
-                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE),
-                getHandler().getLooper());
-    }
-
-    /**
-     * Create a new CellBroadcastHandler.
-     * @param context the context to use for dispatching Intents
-     * @return the new handler
-     */
-    public static CellBroadcastHandler makeCellBroadcastHandler(Context context, Phone phone) {
-        CellBroadcastHandler handler = new CellBroadcastHandler(context, phone);
-        handler.start();
-        return handler;
-    }
-
-    /**
-     * Handle Cell Broadcast messages from {@code CdmaInboundSmsHandler}.
-     * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass.
-     *
-     * @param message the message to process
-     * @return true if need to wait for geo-fencing or an ordered broadcast was sent.
-     */
-    @Override
-    protected boolean handleSmsMessage(Message message) {
-        if (message.obj instanceof SmsCbMessage) {
-            handleBroadcastSms((SmsCbMessage) message.obj);
-            return true;
-        } else {
-            loge("handleMessage got object of type: " + message.obj.getClass().getName());
-            return false;
-        }
-    }
-
-    /**
-     * Dispatch a Cell Broadcast message to listeners.
-     * @param message the Cell Broadcast to broadcast
-     */
-    protected void handleBroadcastSms(SmsCbMessage message) {
-        // Log Cellbroadcast msg received event
-        TelephonyMetrics metrics = TelephonyMetrics.getInstance();
-        metrics.writeNewCBSms(mPhone.getPhoneId(), message.getMessageFormat(),
-                message.getMessagePriority(), message.isCmasMessage(), message.isEtwsMessage(),
-                message.getServiceCategory(), message.getSerialNumber(),
-                System.currentTimeMillis());
-
-        // TODO: Database inserting can be time consuming, therefore this should be changed to
-        // asynchronous.
-        ContentValues cv = message.getContentValues();
-        Uri uri = mContext.getContentResolver().insert(CELL_BROADCAST_URI, cv);
-
-        if (message.needGeoFencingCheck()) {
-            if (DBG) {
-                log("Request location update for geo-fencing. serialNumber = "
-                        + message.getSerialNumber());
-            }
-
-            requestLocationUpdate(location -> {
-                if (location == null) {
-                    // Broadcast the message directly if the location is not available.
-                    broadcastMessage(message, uri);
-                } else {
-                    performGeoFencing(message, uri, message.getGeometries(), location);
-                }
-            }, message.getMaximumWaitingTime());
-        } else {
-            if (DBG) {
-                log("Broadcast the message directly because no geo-fencing required, "
-                        + "serialNumber = " + message.getSerialNumber()
-                        + " needGeoFencing = " + message.needGeoFencingCheck());
-            }
-            broadcastMessage(message, uri);
-        }
-    }
-
-    /**
-     * Perform a geo-fencing check for {@code message}. Broadcast the {@code message} if the
-     * {@code location} is inside the {@code broadcastArea}.
-     * @param message the message need to geo-fencing check
-     * @param uri the message's uri
-     * @param broadcastArea the broadcast area of the message
-     * @param location current location
-     */
-    protected void performGeoFencing(SmsCbMessage message, Uri uri, List<Geometry> broadcastArea,
-            LatLng location) {
-
-        if (DBG) {
-            logd("Perform geo-fencing check for message identifier = "
-                    + message.getServiceCategory()
-                    + " serialNumber = " + message.getSerialNumber());
-        }
-
-        for (Geometry geo : broadcastArea) {
-            if (geo.contains(location)) {
-                broadcastMessage(message, uri);
-                return;
-            }
-        }
-
-        if (DBG) {
-            logd("Device location is outside the broadcast area "
-                    + CbGeoUtils.encodeGeometriesToString(broadcastArea));
-        }
-
-        sendMessage(EVENT_BROADCAST_NOT_REQUIRED);
-    }
-
-    /**
-     * Request a single location update.
-     * @param callback a callback will be called when the location is available.
-     * @param maximumWaitTimeSec the maximum wait time of this request. If location is not updated
-     * within the maximum wait time, {@code callback#onLocationUpadte(null)} will be called.
-     */
-    protected void requestLocationUpdate(LocationUpdateCallback callback, int maximumWaitTimeSec) {
-        mLocationRequester.requestLocationUpdate(callback, maximumWaitTimeSec);
-    }
-
-    /**
-     * Broadcast a list of cell broadcast messages.
-     * @param cbMessages a list of cell broadcast message.
-     * @param cbMessageUris the corresponding {@link Uri} of the cell broadcast messages.
-     */
-    protected void broadcastMessage(List<SmsCbMessage> cbMessages, List<Uri> cbMessageUris) {
-        for (int i = 0; i < cbMessages.size(); i++) {
-            broadcastMessage(cbMessages.get(i), cbMessageUris.get(i));
-        }
-    }
-
-    /**
-     * Broadcast the {@code message} to the applications.
-     * @param message a message need to broadcast
-     * @param messageUri message's uri
-     */
-    protected void broadcastMessage(@NonNull SmsCbMessage message, @Nullable Uri messageUri) {
-        String receiverPermission;
-        int appOp;
-        String msg;
-        Intent intent;
-        if (message.isEmergencyMessage()) {
-            msg = "Dispatching emergency SMS CB, SmsCbMessage is: " + message;
-            log(msg);
-            mLocalLog.log(msg);
-            intent = new Intent(Telephony.Sms.Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION);
-            //Emergency alerts need to be delivered with high priority
-            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            receiverPermission = Manifest.permission.RECEIVE_EMERGENCY_BROADCAST;
-            appOp = AppOpsManager.OP_RECEIVE_EMERGECY_SMS;
-
-            intent.putExtra(EXTRA_MESSAGE, message);
-            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
-
-            if (Build.IS_DEBUGGABLE) {
-                // Send additional broadcast intent to the specified package. This is only for sl4a
-                // automation tests.
-                final String additionalPackage = Settings.Secure.getString(
-                        mContext.getContentResolver(), CMAS_ADDITIONAL_BROADCAST_PKG);
-                if (additionalPackage != null) {
-                    Intent additionalIntent = new Intent(intent);
-                    additionalIntent.setPackage(additionalPackage);
-                    mContext.sendOrderedBroadcastAsUser(additionalIntent, UserHandle.ALL,
-                            receiverPermission, appOp, null, getHandler(), Activity.RESULT_OK,
-                            null, null);
-                }
-            }
-
-            String[] pkgs = mContext.getResources().getStringArray(
-                    com.android.internal.R.array.config_defaultCellBroadcastReceiverPkgs);
-            mReceiverCount.addAndGet(pkgs.length);
-            for (String pkg : pkgs) {
-                // Explicitly send the intent to all the configured cell broadcast receivers.
-                intent.setPackage(pkg);
-                mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission,
-                        appOp, mReceiver, getHandler(), Activity.RESULT_OK, null, null);
-            }
-        } else {
-            msg = "Dispatching SMS CB, SmsCbMessage is: " + message;
-            log(msg);
-            mLocalLog.log(msg);
-            intent = new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION);
-            // Send implicit intent since there are various 3rd party carrier apps listen to
-            // this intent.
-            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-            receiverPermission = Manifest.permission.RECEIVE_SMS;
-            appOp = AppOpsManager.OP_RECEIVE_SMS;
-
-            intent.putExtra(EXTRA_MESSAGE, message);
-            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
-
-            mReceiverCount.incrementAndGet();
-            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission, appOp,
-                    mReceiver, getHandler(), Activity.RESULT_OK, null, null);
-        }
-
-        if (messageUri != null) {
-            ContentValues cv = new ContentValues();
-            cv.put(CellBroadcasts.MESSAGE_BROADCASTED, 1);
-            mContext.getContentResolver().update(CELL_BROADCAST_URI, cv,
-                    CellBroadcasts._ID + "=?", new String[] {messageUri.getLastPathSegment()});
-        }
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("CellBroadcastHandler:");
-        mLocalLog.dump(fd, pw, args);
-        pw.flush();
-    }
-
-    /** The callback interface of a location request. */
-    public interface LocationUpdateCallback {
-        /**
-         * Call when the location update is available.
-         * @param location a location in (latitude, longitude) format, or {@code null} if the
-         * location service is not available.
-         */
-        void onLocationUpdate(@Nullable LatLng location);
-    }
-
-    private static final class LocationRequester {
-        private static final String TAG = LocationRequester.class.getSimpleName();
-
-        /**
-         * Use as the default maximum wait time if the cell broadcast doesn't specify the value.
-         * Most of the location request should be responded within 20 seconds.
-         */
-        private static final int DEFAULT_MAXIMUM_WAIT_TIME_SEC = 20;
-
-        /**
-         * Trigger this event when the {@link LocationManager} is not responded within the given
-         * time.
-         */
-        private static final int EVENT_LOCATION_REQUEST_TIMEOUT = 1;
-
-        /** Request a single location update. */
-        private static final int EVENT_REQUEST_LOCATION_UPDATE = 2;
-
-        /**
-         * Request location update from network or gps location provider. Network provider will be
-         * used if available, otherwise use the gps provider.
-         */
-        private static final List<String> LOCATION_PROVIDERS = Arrays.asList(
-                LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER);
-
-        private final LocationManager mLocationManager;
-        private final Looper mLooper;
-        private final List<LocationUpdateCallback> mCallbacks;
-        private final Context mContext;
-        private Handler mLocationHandler;
-
-        LocationRequester(Context context, LocationManager locationManager, Looper looper) {
-            mLocationManager = locationManager;
-            mLooper = looper;
-            mCallbacks = new ArrayList<>();
-            mContext = context;
-            mLocationHandler = new LocationHandler(looper);
-        }
-
-        /**
-         * Request a single location update. If the location is not available, a callback with
-         * {@code null} location will be called immediately.
-         *
-         * @param callback a callback to the the response when the location is available
-         * @param maximumWaitTimeSec the maximum wait time of this request. If location is not
-         * updated within the maximum wait time, {@code callback#onLocationUpadte(null)} will be
-         * called.
-         */
-        void requestLocationUpdate(@NonNull LocationUpdateCallback callback,
-                int maximumWaitTimeSec) {
-            mLocationHandler.obtainMessage(EVENT_REQUEST_LOCATION_UPDATE, maximumWaitTimeSec,
-                    0 /* arg2 */, callback).sendToTarget();
-        }
-
-        private void onLocationUpdate(@Nullable LatLng location) {
-            for (LocationUpdateCallback callback : mCallbacks) {
-                callback.onLocationUpdate(location);
-            }
-            mCallbacks.clear();
-        }
-
-        private void requestLocationUpdateInternal(@NonNull LocationUpdateCallback callback,
-                int maximumWaitTimeSec) {
-            if (DBG) Log.d(TAG, "requestLocationUpdate");
-            if (!isLocationServiceAvailable()) {
-                if (DBG) {
-                    Log.d(TAG, "Can't request location update because of no location permission");
-                }
-                callback.onLocationUpdate(null);
-                return;
-            }
-
-            if (!mLocationHandler.hasMessages(EVENT_LOCATION_REQUEST_TIMEOUT)) {
-                if (maximumWaitTimeSec == SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET) {
-                    maximumWaitTimeSec = DEFAULT_MAXIMUM_WAIT_TIME_SEC;
-                }
-                mLocationHandler.sendMessageDelayed(
-                        mLocationHandler.obtainMessage(EVENT_LOCATION_REQUEST_TIMEOUT),
-                        maximumWaitTimeSec * DateUtils.SECOND_IN_MILLIS);
-            }
-
-            mCallbacks.add(callback);
-
-            for (String provider : LOCATION_PROVIDERS) {
-                if (mLocationManager.isProviderEnabled(provider)) {
-                    mLocationManager.requestSingleUpdate(provider, mLocationListener, mLooper);
-                    break;
-                }
-            }
-        }
-
-        private boolean isLocationServiceAvailable() {
-            if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)
-                    && !hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) return false;
-            for (String provider : LOCATION_PROVIDERS) {
-                if (mLocationManager.isProviderEnabled(provider)) return true;
-            }
-            return false;
-        }
-
-        private boolean hasPermission(String permission) {
-            return PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(mContext, permission)
-                    == PERMISSION_GRANTED;
-        }
-
-        private final LocationListener mLocationListener = new LocationListener() {
-            @Override
-            public void onLocationChanged(Location location) {
-                mLocationHandler.removeMessages(EVENT_LOCATION_REQUEST_TIMEOUT);
-                onLocationUpdate(new LatLng(location.getLatitude(), location.getLongitude()));
-            }
-
-            @Override
-            public void onStatusChanged(String provider, int status, Bundle extras) {}
-
-            @Override
-            public void onProviderEnabled(String provider) {}
-
-            @Override
-            public void onProviderDisabled(String provider) {}
-        };
-
-        private final class LocationHandler extends Handler {
-            LocationHandler(Looper looper) {
-                super(looper);
-            }
-
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case EVENT_LOCATION_REQUEST_TIMEOUT:
-                        if (DBG) Log.d(TAG, "location request timeout");
-                        onLocationUpdate(null);
-                        break;
-                    case EVENT_REQUEST_LOCATION_UPDATE:
-                        requestLocationUpdateInternal((LocationUpdateCallback) msg.obj, msg.arg1);
-                        break;
-                    default:
-                        Log.e(TAG, "Unsupported message type " + msg.what);
-                }
-            }
-        }
-    }
-}
diff --git a/src/java/com/android/internal/telephony/CellBroadcastServiceManager.java b/src/java/com/android/internal/telephony/CellBroadcastServiceManager.java
index 132ea3b..09465ee 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastServiceManager.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastServiceManager.java
@@ -60,7 +60,7 @@
     private static final int EVENT_NEW_GSM_SMS_CB = 0;
     private static final int EVENT_NEW_CDMA_SMS_CB = 1;
     private static final int EVENT_NEW_CDMA_SCP_MESSAGE = 2;
-    private boolean mEnabled;
+    private boolean mEnabled = false;
 
     public CellBroadcastServiceManager(Context context, Phone phone) {
         Log.d(TAG, "CellBroadcastServiceManager created for phone " + phone.getPhoneId());
@@ -111,6 +111,9 @@
      * Disable the CB module. The manager's handler will no longer receive CB messages from the RIL.
      */
     public void disable() {
+        if (mEnabled == false) {
+            return;
+        }
         mEnabled = false;
         mPhone.mCi.unSetOnNewGsmBroadcastSms(mModuleCellBroadcastHandler);
         if (sServiceConnection.mService != null) {
diff --git a/src/java/com/android/internal/telephony/CellularNetworkService.java b/src/java/com/android/internal/telephony/CellularNetworkService.java
index b45d63d..4971643 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkService.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkService.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.telephony;
 
-import android.hardware.radio.V1_0.CellInfoType;
 import android.hardware.radio.V1_0.RegState;
 import android.hardware.radio.V1_4.DataRegStateResult.VopsInfo.hidl_discriminator;
 import android.os.AsyncResult;
@@ -27,20 +26,16 @@
 import android.telephony.AccessNetworkConstants;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CellIdentity;
-import android.telephony.CellIdentityCdma;
-import android.telephony.CellIdentityGsm;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityTdscdma;
-import android.telephony.CellIdentityWcdma;
 import android.telephony.LteVopsSupportInfo;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.NetworkService;
 import android.telephony.NetworkServiceCallback;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import com.android.telephony.Rlog;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
@@ -228,8 +223,7 @@
                 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator;
                 List<Integer> availableServices = getAvailableServices(
                         regState, domain, emergencyOnly);
-                CellIdentity cellIdentity =
-                        convertHalCellIdentityToCellIdentity(voiceRegState.cellIdentity);
+                CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
 
                 return new NetworkRegistrationInfo(domain, transportType, regState,
                         networkType, reasonForDenial, emergencyOnly, availableServices,
@@ -251,8 +245,7 @@
                 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator;
                 List<Integer> availableServices = getAvailableServices(
                         regState, domain, emergencyOnly);
-                CellIdentity cellIdentity =
-                        convertHalCellIdentityToCellIdentity(voiceRegState.cellIdentity);
+                CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
 
                 return new NetworkRegistrationInfo(domain, transportType, regState,
                         networkType, reasonForDenial, emergencyOnly, availableServices,
@@ -289,8 +282,7 @@
                 reasonForDenial = dataRegState.reasonDataDenied;
                 emergencyOnly = isEmergencyOnly(dataRegState.regState);
                 maxDataCalls = dataRegState.maxDataCalls;
-
-                cellIdentity = convertHalCellIdentityToCellIdentity(dataRegState.cellIdentity);
+                cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
             } else if (result instanceof android.hardware.radio.V1_2.DataRegStateResult) {
                 android.hardware.radio.V1_2.DataRegStateResult dataRegState =
                         (android.hardware.radio.V1_2.DataRegStateResult) result;
@@ -299,7 +291,7 @@
                 reasonForDenial = dataRegState.reasonDataDenied;
                 emergencyOnly = isEmergencyOnly(dataRegState.regState);
                 maxDataCalls = dataRegState.maxDataCalls;
-                cellIdentity = convertHalCellIdentityToCellIdentity(dataRegState.cellIdentity);
+                cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
             } else if (result instanceof android.hardware.radio.V1_4.DataRegStateResult) {
                 android.hardware.radio.V1_4.DataRegStateResult dataRegState =
                         (android.hardware.radio.V1_4.DataRegStateResult) result;
@@ -309,7 +301,7 @@
                 reasonForDenial = dataRegState.base.reasonDataDenied;
                 emergencyOnly = isEmergencyOnly(dataRegState.base.regState);
                 maxDataCalls = dataRegState.base.maxDataCalls;
-                cellIdentity = convertHalCellIdentityToCellIdentity(dataRegState.base.cellIdentity);
+                cellIdentity = CellIdentity.create(dataRegState.base.cellIdentity);
                 android.hardware.radio.V1_4.NrIndicators nrIndicators = dataRegState.nrIndicators;
 
                 // Check for lteVopsInfo only if its initialized and RAT is EUTRAN
@@ -362,118 +354,6 @@
             return new LteVopsSupportInfo(vops, emergency);
         }
 
-        private CellIdentity convertHalCellIdentityToCellIdentity(
-                android.hardware.radio.V1_0.CellIdentity cellIdentity) {
-            if (cellIdentity == null) {
-                return null;
-            }
-
-            CellIdentity result = null;
-            switch(cellIdentity.cellInfoType) {
-                case CellInfoType.GSM: {
-                    if (cellIdentity.cellIdentityGsm.size() == 1) {
-                        android.hardware.radio.V1_0.CellIdentityGsm cellIdentityGsm =
-                                cellIdentity.cellIdentityGsm.get(0);
-                        result = new CellIdentityGsm(cellIdentityGsm);
-                    }
-                    break;
-                }
-                case CellInfoType.WCDMA: {
-                    if (cellIdentity.cellIdentityWcdma.size() == 1) {
-                        android.hardware.radio.V1_0.CellIdentityWcdma cellIdentityWcdma =
-                                cellIdentity.cellIdentityWcdma.get(0);
-                        result = new CellIdentityWcdma(cellIdentityWcdma);
-                    }
-                    break;
-                }
-                case CellInfoType.TD_SCDMA: {
-                    if (cellIdentity.cellIdentityTdscdma.size() == 1) {
-                        android.hardware.radio.V1_0.CellIdentityTdscdma cellIdentityTdscdma =
-                                cellIdentity.cellIdentityTdscdma.get(0);
-                        result = new  CellIdentityTdscdma(cellIdentityTdscdma);
-                    }
-                    break;
-                }
-                case CellInfoType.LTE: {
-                    if (cellIdentity.cellIdentityLte.size() == 1) {
-                        android.hardware.radio.V1_0.CellIdentityLte cellIdentityLte =
-                                cellIdentity.cellIdentityLte.get(0);
-                        result = new CellIdentityLte(cellIdentityLte);
-                    }
-                    break;
-                }
-                case CellInfoType.CDMA: {
-                    if (cellIdentity.cellIdentityCdma.size() == 1) {
-                        android.hardware.radio.V1_0.CellIdentityCdma cellIdentityCdma =
-                                cellIdentity.cellIdentityCdma.get(0);
-                        result = new CellIdentityCdma(cellIdentityCdma);
-                    }
-                    break;
-                }
-                case CellInfoType.NONE:
-                default:
-                    break;
-            }
-
-            return result;
-        }
-
-        private CellIdentity convertHalCellIdentityToCellIdentity(
-                android.hardware.radio.V1_2.CellIdentity cellIdentity) {
-            if (cellIdentity == null) {
-                return null;
-            }
-
-            CellIdentity result = null;
-            switch(cellIdentity.cellInfoType) {
-                case CellInfoType.GSM: {
-                    if (cellIdentity.cellIdentityGsm.size() == 1) {
-                        android.hardware.radio.V1_2.CellIdentityGsm cellIdentityGsm =
-                                cellIdentity.cellIdentityGsm.get(0);
-                        result = new CellIdentityGsm(cellIdentityGsm);
-                    }
-                    break;
-                }
-                case CellInfoType.WCDMA: {
-                    if (cellIdentity.cellIdentityWcdma.size() == 1) {
-                        android.hardware.radio.V1_2.CellIdentityWcdma cellIdentityWcdma =
-                                cellIdentity.cellIdentityWcdma.get(0);
-                        result = new CellIdentityWcdma(cellIdentityWcdma);
-                    }
-                    break;
-                }
-                case CellInfoType.TD_SCDMA: {
-                    if (cellIdentity.cellIdentityTdscdma.size() == 1) {
-                        android.hardware.radio.V1_2.CellIdentityTdscdma cellIdentityTdscdma =
-                                cellIdentity.cellIdentityTdscdma.get(0);
-                        result = new  CellIdentityTdscdma(cellIdentityTdscdma);
-                    }
-                    break;
-                }
-                case CellInfoType.LTE: {
-                    if (cellIdentity.cellIdentityLte.size() == 1) {
-                        android.hardware.radio.V1_2.CellIdentityLte cellIdentityLte =
-                                cellIdentity.cellIdentityLte.get(0);
-                        result = new CellIdentityLte(cellIdentityLte);
-                    }
-                    break;
-                }
-                case CellInfoType.CDMA: {
-                    if (cellIdentity.cellIdentityCdma.size() == 1) {
-                        android.hardware.radio.V1_2.CellIdentityCdma cellIdentityCdma =
-                                cellIdentity.cellIdentityCdma.get(0);
-                        result = new CellIdentityCdma(cellIdentityCdma);
-                    }
-                    break;
-                }
-                case CellInfoType.NONE:
-                default:
-                    break;
-            }
-
-            return result;
-        }
-
         @Override
         public void requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback) {
             if (DBG) log("requestNetworkRegistrationInfo for domain " + domain);
diff --git a/src/java/com/android/internal/telephony/CellularNetworkValidator.java b/src/java/com/android/internal/telephony/CellularNetworkValidator.java
index 48a90ea..4b8e102 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkValidator.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkValidator.java
@@ -21,6 +21,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.TelephonyNetworkSpecifier;
 import android.os.Handler;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
@@ -101,7 +102,7 @@
      */
     public boolean isValidationFeatureSupported() {
         return PhoneConfigurationManager.getInstance().getCurrentPhoneCapability()
-                .validationBeforeSwitchSupported;
+                .getPsDataConnectionLingerTimeMillis() > 0;
     }
 
     @VisibleForTesting
@@ -193,7 +194,8 @@
         return new NetworkRequest.Builder()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                .setNetworkSpecifier(String.valueOf(mSubId))
+                .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+                        .setSubscriptionId(mSubId).build())
                 .build();
     }
 
diff --git a/src/java/com/android/internal/telephony/ClientWakelockAccountant.java b/src/java/com/android/internal/telephony/ClientWakelockAccountant.java
index c47faab..a78b520 100644
--- a/src/java/com/android/internal/telephony/ClientWakelockAccountant.java
+++ b/src/java/com/android/internal/telephony/ClientWakelockAccountant.java
@@ -17,9 +17,10 @@
 package com.android.internal.telephony;
 
 import android.telephony.ClientRequestStats;
-import android.telephony.Rlog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
+
 import java.util.ArrayList;
 
 public class ClientWakelockAccountant {
diff --git a/src/java/com/android/internal/telephony/CommandException.java b/src/java/com/android/internal/telephony/CommandException.java
index 31ffcd2..ccd9251 100644
--- a/src/java/com/android/internal/telephony/CommandException.java
+++ b/src/java/com/android/internal/telephony/CommandException.java
@@ -16,8 +16,9 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+import android.compat.annotation.UnsupportedAppUsage;
+
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index de4f7c0..cf6c38c 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -16,16 +16,18 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.net.KeepalivePacketData;
 import android.net.LinkProperties;
 import android.os.Handler;
 import android.os.Message;
 import android.os.WorkSource;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CarrierRestrictionRules;
 import android.telephony.ClientRequestStats;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.data.DataProfile;
 import android.telephony.emergency.EmergencyNumber;
 
@@ -73,6 +75,7 @@
     static final String CB_FACILITY_BA_MT        = "AC";
     static final String CB_FACILITY_BA_SIM       = "SC";
     static final String CB_FACILITY_BA_FD        = "FD";
+    static final String CB_FACILITY_BIC_ACR      = "AR";
 
 
     // Used for various supp services apis
@@ -480,6 +483,20 @@
     void unSetOnSs(Handler h);
 
     /**
+     * Register for unsolicited NATT Keepalive Status Indications
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void setOnRegistrationFailed(Handler h, int what, Object obj) {}
+
+    /**
+     * @param h Handler for notification message.
+     */
+    default void unSetOnRegistrationFailed(Handler h) {}
+
+    /**
      * Sets the handler for Event Notifications for CDMA Display Info.
      * Unlike the register* methods, there's only one notification handler
      *
@@ -654,6 +671,22 @@
      void unregisterForRilConnected(Handler h);
 
     /**
+     * Registers the handler for RIL_UNSOL_SIM_DETACH_FROM_NETWORK_CONFIG_CHANGED events.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerUiccApplicationEnablementChanged(Handler h, int what, Object obj) {};
+
+    /**
+     * Unregisters the handler for RIL_UNSOL_SIM_DETACH_FROM_NETWORK_CONFIG_CHANGED events.
+     *
+     * @param h Handler for notification message.
+     */
+    default void unregisterUiccApplicationEnablementChanged(Handler h) {};
+
+    /**
      * Supply the ICC PIN to the ICC card
      *
      *  returned message
@@ -1151,6 +1184,8 @@
      */
     void sendCdmaSms(byte[] pdu, Message response);
 
+    void sendCdmaSMSExpectMore(byte[] pdu, Message response);
+
     /**
      * send SMS over IMS with 3GPP/GSM SMS format
      * @param smscPDU is smsc address in PDU form GSM BCD format prefixed
@@ -1342,8 +1377,15 @@
     @UnsupportedAppUsage
     void setNetworkSelectionModeAutomatic(Message response);
 
+    /**
+     * Ask the radio to connect to the input network with specific RadioAccessNetwork
+     * and change selection mode to manual.
+     * @param operatorNumeric PLMN ID of the network to select.
+     * @param ran radio access network type (see {@link AccessNetworkType}).
+     * @param response callback message.
+     */
     @UnsupportedAppUsage
-    void setNetworkSelectionModeManual(String operatorNumeric, Message response);
+    void setNetworkSelectionModeManual(String operatorNumeric, int ran, Message response);
 
     /**
      * Queries whether the current network selection mode is automatic
@@ -2229,17 +2271,30 @@
     void setUnsolResponseFilter(int filter, Message result);
 
     /**
-     * Send the signal strength reporting criteria to the modem.
+     * Sets the signal strength reporting criteria.
      *
-     * @param hysteresisMs A hysteresis time in milliseconds. A value of 0 disables hysteresis.
-     * @param hysteresisDb An interval in dB defining the required magnitude change between reports.
-     *     A value of 0 disables hysteresis.
-     * @param thresholdsDbm An array of trigger thresholds in dBm. A size of 0 disables thresholds.
-     * @param ran RadioAccessNetwork for which to apply criteria.
+     * The resulting reporting rules are the AND of all the supplied criteria. For each RAN
+     * The hysteresisDb and thresholds apply to only the following measured quantities:
+     * -GERAN    - RSSI
+     * -CDMA2000 - RSSI
+     * -UTRAN    - RSCP
+     * -EUTRAN   - RSRP/RSRQ/RSSNR
+     * -NGRAN    - SSRSRP/SSRSRQ/SSSINR
+     *
+     * Note: Reporting criteria must be individually set for each RAN. For any unset reporting
+     * criteria, the value is implementation-defined.
+     *
+     * Response callback is
+     * IRadioResponse.setSignalStrengthReportingCriteriaResponse_1_5()
+     *
+     * @param signalThresholdInfo Signal threshold info including the threshold values,
+     *                            hysteresisDb, and hysteresisMs. See @1.5::SignalThresholdInfo
+     *                            for details.
+     * @param ran The type of network for which to apply these thresholds.
      * @param result callback message contains the information of SUCCESS/FAILURE
      */
-    void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb, int[] thresholdsDbm,
-            int ran, Message result);
+    void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo, int ran,
+            Message result);
 
     /**
      * Send the link capacity reporting criteria to the modem
@@ -2378,6 +2433,28 @@
      */
     default void getModemStatus(Message result) {};
 
+    /**
+     * Enable or disable uicc applications on the SIM.
+     *
+     * @param enable enable or disable UiccApplications on the SIM.
+     * @param onCompleteMessage a Message to return to the requester
+     */
+    default void enableUiccApplications(boolean enable, Message onCompleteMessage) {}
+
+    /**
+     * Whether uicc applications are enabled or not.
+     *
+     * @param onCompleteMessage a Message to return to the requester
+     */
+    default void areUiccApplicationsEnabled(Message onCompleteMessage) {}
+
+    /**
+     * Whether {@link #enableUiccApplications} is supported, based on IRadio version.
+     */
+    default boolean canToggleUiccApplicationsEnablement() {
+        return false;
+    }
+
     default List<ClientRequestStats> getClientRequestStats() {
         return null;
     }
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
old mode 100755
new mode 100644
index ede22e1..18901ce
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -16,19 +16,21 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.telephony.DisconnectCause;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
+import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.emergency.EmergencyNumber;
 import android.util.Log;
 
 import com.android.ims.internal.ConferenceParticipant;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,6 +43,8 @@
 public abstract class Connection {
     private static final String TAG = "Connection";
 
+    public static final String ADHOC_CONFERENCE_ADDRESS = "tel:conf-factory";
+
     public interface PostDialListener {
         void onPostDialWait();
         void onPostDialChar(char c);
@@ -94,7 +98,7 @@
     public interface Listener {
         public void onVideoStateChanged(int videoState);
         public void onConnectionCapabilitiesChanged(int capability);
-        public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat);
+        public void onCallRadioTechChanged(@RilRadioTechnology int vrat);
         public void onVideoProviderChanged(
                 android.telecom.Connection.VideoProvider videoProvider);
         public void onAudioQualityChanged(int audioQuality);
@@ -125,7 +129,7 @@
         @Override
         public void onConnectionCapabilitiesChanged(int capability) {}
         @Override
-        public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {}
+        public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {}
         @Override
         public void onVideoProviderChanged(
                 android.telecom.Connection.VideoProvider videoProvider) {}
@@ -183,6 +187,8 @@
     protected String mAddress;     // MAY BE NULL!!!
     @UnsupportedAppUsage
     protected String mDialString;          // outgoing calls only
+    protected String[] mParticipantsToDial;// outgoing calls only
+    protected boolean mIsAdhocConference;
     @UnsupportedAppUsage
     protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
     @UnsupportedAppUsage
@@ -216,6 +222,9 @@
     protected int mCause = DisconnectCause.NOT_DISCONNECTED;
     protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
 
+    // Store the current audio code
+    protected int mAudioCodec;
+
     @UnsupportedAppUsage
     private static String LOG_TAG = "Connection";
 
@@ -227,7 +236,7 @@
      *
      * This is used to propagate the call radio technology to upper layer.
      */
-    private @ServiceState.RilRadioTechnology int mCallRadioTech =
+    private @RilRadioTechnology int mCallRadioTech =
             ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
     private boolean mAudioModeIsVoip;
     private int mAudioQuality;
@@ -238,6 +247,7 @@
     private int mPhoneType;
     private boolean mAnsweringDisconnectsActiveCall;
     private boolean mAllowAddCallDuringVideoCall;
+    private boolean mAllowHoldingVideoCall;
 
     private boolean mIsEmergencyCall;
 
@@ -308,6 +318,20 @@
     }
 
     /**
+     * Gets the participants address (e.g. phone number) associated with connection.
+     *
+     * @return address or null if unavailable
+     */
+    public String[] getParticipantsToDial() {
+        return mParticipantsToDial;
+    }
+
+    // return whether connection is AdhocConference or not
+    public boolean isAdhocConference() {
+        return mIsAdhocConference;
+    }
+
+    /**
      * Gets CNAP name associated with connection.
      * @return cnap name or null if unavailable
      */
@@ -902,7 +926,7 @@
      * @return the RIL Voice Radio Technology used for current connection,
      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      */
-    public @ServiceState.RilRadioTechnology int getCallRadioTech() {
+    public @RilRadioTechnology int getCallRadioTech() {
         return mCallRadioTech;
     }
 
@@ -980,7 +1004,7 @@
      * @param vrat the RIL voice radio technology for current connection,
      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      */
-    public void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+    public void setCallRadioTech(@RilRadioTechnology int vrat) {
         if (mCallRadioTech == vrat) {
             return;
         }
@@ -1024,7 +1048,7 @@
             int previousCount = mExtras.size();
             // Prevent vendors from passing in extras other than primitive types and android API
             // parcelables.
-            mExtras = mExtras.filterValues();
+            mExtras = TelephonyUtils.filterValues(mExtras);
             int filteredCount = mExtras.size();
             if (filteredCount != previousCount) {
                 Rlog.i(TAG, "setConnectionExtras: filtering " + (previousCount - filteredCount)
@@ -1075,6 +1099,14 @@
         mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
     }
 
+    public boolean shouldAllowHoldingVideoCall() {
+        return mAllowHoldingVideoCall;
+    }
+
+    public void setAllowHoldingVideoCall(boolean allowHoldingVideoCall) {
+        mAllowHoldingVideoCall = allowHoldingVideoCall;
+    }
+
     /**
      * Sets whether the connection is the result of an external call which was pulled to the local
      * device.
@@ -1354,4 +1386,12 @@
                 .append(" post dial state: " + getPostDialState());
         return str.toString();
     }
+
+    /**
+     * Get current audio codec.
+     * @return current audio codec.
+     */
+    public int getAudioCodec() {
+        return mAudioCodec;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/DebugService.java b/src/java/com/android/internal/telephony/DebugService.java
index 0002f14..3a08243 100644
--- a/src/java/com/android/internal/telephony/DebugService.java
+++ b/src/java/com/android/internal/telephony/DebugService.java
@@ -16,10 +16,10 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 9cce7bc..e8aafe7 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -17,32 +17,28 @@
 package com.android.internal.telephony;
 
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
-import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.telephony.TelephonyRegistryManager;
 import android.telephony.Annotation.DataFailureCause;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SrvccState;
 import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.CellLocation;
 import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
-import android.telephony.Rlog;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.data.ApnSetting;
+import android.telephony.TelephonyRegistryManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
 import com.android.internal.telephony.PhoneInternalInterface.DataActivityState;
+import com.android.telephony.Rlog;
+
 import java.util.List;
 
 /**
@@ -84,7 +80,7 @@
         int phoneId = sender.getPhoneId();
         int subId = sender.getSubId();
 
-        Rlog.d(LOG_TAG, "nofityServiceState: mRegistry=" + mRegistry + " ss=" + ss
+        Rlog.d(LOG_TAG, "notifyServiceState: mRegistry=" + mRegistry + " ss=" + ss
             + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId);
         if (ss == null) {
             ss = new ServiceState();
@@ -134,59 +130,20 @@
     }
 
     @Override
-    public void notifyDataConnection(Phone sender, String apnType,
-        PhoneConstants.DataState state) {
-        doNotifyDataConnection(sender, apnType, state);
-    }
+    public void notifyDataConnection(
+            Phone sender, String apnType, PreciseDataConnectionState preciseState) {
 
-    private void doNotifyDataConnection(Phone sender, String apnType,
-        PhoneConstants.DataState state) {
         int subId = sender.getSubId();
         int phoneId = sender.getPhoneId();
-        long dds = SubscriptionManager.getDefaultDataSubscriptionId();
-        if (DBG) {
-            log("subId = " + subId + ", DDS = " + dds);
-        }
 
-        // TODO
-        // use apnType as the key to which connection we're talking about.
-        // pass apnType back up to fetch particular for this one.
-        TelephonyManager telephony = TelephonyManager.getDefault();
-        LinkProperties linkProperties = null;
-        NetworkCapabilities networkCapabilities = null;
-        boolean roaming = false;
-
-        if (state == PhoneConstants.DataState.CONNECTED) {
-            linkProperties = sender.getLinkProperties(apnType);
-            networkCapabilities = sender.getNetworkCapabilities(apnType);
-        }
-        ServiceState ss = sender.getServiceState();
-        if (ss != null) {
-            roaming = ss.getDataRoaming();
-        }
-        mTelephonyRegistryMgr.notifyDataConnectionForSubscriber(phoneId, subId,
-            PhoneConstantConversions.convertDataState(state),
-            sender.isDataAllowed(ApnSetting.getApnTypesBitmaskFromString(apnType)),
-            sender.getActiveApnHost(apnType),
-            apnType,
-            linkProperties,
-            networkCapabilities,
-            ((telephony != null) ? telephony.getDataNetworkType(subId) :
-                TelephonyManager.NETWORK_TYPE_UNKNOWN), roaming);
+        mTelephonyRegistryMgr.notifyDataConnectionForSubscriber(
+                phoneId, subId, apnType, preciseState);
     }
 
     @Override
-    public void notifyDataConnectionFailed(Phone sender, String apnType) {
-        mTelephonyRegistryMgr.notifyDataConnectionFailed(sender.getSubId(), sender.getPhoneId(),
-            apnType);
-    }
-
-    @Override
-    public void notifyCellLocation(Phone sender, CellLocation cl) {
+    public void notifyCellLocation(Phone sender, CellIdentity cellIdentity) {
         int subId = sender.getSubId();
-        Bundle data = new Bundle();
-        cl.fillInNotifierBundle(data);
-        mTelephonyRegistryMgr.notifyCellLocation(subId, data);
+        mTelephonyRegistryMgr.notifyCellLocation(subId, cellIdentity);
     }
 
     @Override
@@ -195,26 +152,6 @@
         mTelephonyRegistryMgr.notifyCellInfoChanged(subId, cellInfo);
     }
 
-    @Override
-    public void notifyPhysicalChannelConfiguration(Phone sender,
-        List<PhysicalChannelConfig> configs) {
-        int subId = sender.getSubId();
-        int phoneId = sender.getPhoneId();
-        try {
-            if (mRegistry != null) {
-                mRegistry.notifyPhysicalChannelConfigurationForSubscriber(phoneId, subId, configs);
-            }
-        } catch (RemoteException ex) {
-            // system process is dead
-        }
-    }
-
-    @Override
-    public void notifyOtaspChanged(Phone sender, int otaspMode) {
-        int subId = sender.getSubId();
-        mTelephonyRegistryMgr.notifyOtaspChanged(subId, otaspMode);
-    }
-
     public void notifyPreciseCallState(Phone sender) {
         Call ringingCall = sender.getRingingCall();
         Call foregroundCall = sender.getForegroundCall();
@@ -237,7 +174,9 @@
         mTelephonyRegistryMgr.notifyImsDisconnectCause(sender.getSubId(), imsReasonInfo);
     }
 
-    public void notifyPreciseDataConnectionFailed(Phone sender, String apnType,
+    @Override
+    /** Notify the TelephonyRegistry that a data connection has failed with a specified cause */
+    public void notifyDataConnectionFailed(Phone sender, String apnType,
         String apn, @DataFailureCause int failCause) {
         mTelephonyRegistryMgr.notifyPreciseDataConnectionFailed(sender.getSubId(),
             sender.getPhoneId(), apnType, apn, failCause);
@@ -319,6 +258,13 @@
             callQuality, callNetworkType);
     }
 
+    @Override
+    public void notifyRegistrationFailed(Phone sender, @NonNull CellIdentity cellIdentity,
+            @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
+        mTelephonyRegistryMgr.notifyRegistrationFailed(sender.getPhoneId(), sender.getSubId(),
+                cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode);
+    }
+
     /**
      * Convert the {@link DataActivityState} enum into the TelephonyManager.DATA_* constants for the
      * public API.
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index f4d782c..c94c4c3 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -36,7 +36,7 @@
 import android.os.PowerManager;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.TelephonyManager;
 import android.util.LocalLog;
 import android.util.SparseIntArray;
@@ -44,6 +44,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -75,6 +76,7 @@
     static final int EVENT_RADIO_AVAILABLE              = 6;
     @VisibleForTesting
     static final int EVENT_WIFI_CONNECTION_CHANGED      = 7;
+    static final int EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH = 8;
 
     // TODO(b/74006656) load hysteresis values from a property when DeviceStateMonitor starts
     private static final int HYSTERESIS_KBPS = 50;
@@ -162,6 +164,11 @@
      */
     private boolean mIsWifiConnected;
 
+    /**
+     * True indicates we should always enable the signal strength reporting from radio.
+     */
+    private boolean mIsAlwaysSignalStrengthReportingEnabled;
+
     @VisibleForTesting
     static final int CELL_INFO_INTERVAL_SHORT_MS = 2000;
     @VisibleForTesting
@@ -312,7 +319,8 @@
         // 3. When the update mode is IGNORE_SCREEN_OFF. This mode is used in some corner cases like
         //    when Bluetooth carkit is connected, we still want to update signal strength even
         //    when screen is off.
-        if (mIsCharging || mIsScreenOn
+        // 4. Any of system services is registrating to always listen to signal strength changes
+        if (mIsAlwaysSignalStrengthReportingEnabled || mIsCharging || mIsScreenOn
                 || mUpdateModes.get(TelephonyManager.INDICATION_FILTER_SIGNAL_STRENGTH)
                 == TelephonyManager.INDICATION_UPDATE_MODE_IGNORE_SCREEN_OFF) {
             return false;
@@ -409,6 +417,15 @@
         sendMessage(obtainMessage(EVENT_UPDATE_MODE_CHANGED, filters, mode));
     }
 
+    /**
+     * Set if Telephony need always report signal strength.
+     *
+     * @param isEnable
+     */
+    public void setAlwaysReportSignalStrength(boolean isEnable) {
+        sendMessage(obtainMessage(EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH, isEnable ? 1 : 0));
+    }
+
     private void onSetIndicationUpdateMode(int filters, int mode) {
         if ((filters & TelephonyManager.INDICATION_FILTER_SIGNAL_STRENGTH) != 0) {
             mUpdateModes.put(TelephonyManager.INDICATION_FILTER_SIGNAL_STRENGTH, mode);
@@ -452,6 +469,9 @@
             case EVENT_WIFI_CONNECTION_CHANGED:
                 onUpdateDeviceState(msg.what, msg.arg1 != WIFI_UNAVAILABLE);
                 break;
+            case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH:
+                onUpdateDeviceState(msg.what, msg.arg1 != 0);
+                break;
             default:
                 throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what);
         }
@@ -486,7 +506,10 @@
             case EVENT_WIFI_CONNECTION_CHANGED:
                 if (mIsWifiConnected == state) return;
                 mIsWifiConnected = state;
-
+                break;
+            case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH:
+                if (mIsAlwaysSignalStrengthReportingEnabled == state) return;
+                mIsAlwaysSignalStrengthReportingEnabled = state;
                 break;
             default:
                 return;
@@ -587,14 +610,28 @@
     }
 
     private void setSignalStrengthReportingCriteria() {
-        mPhone.setSignalStrengthReportingCriteria(
-                AccessNetworkThresholds.GERAN, AccessNetworkType.GERAN);
-        mPhone.setSignalStrengthReportingCriteria(
-                AccessNetworkThresholds.UTRAN, AccessNetworkType.UTRAN);
-        mPhone.setSignalStrengthReportingCriteria(
-                AccessNetworkThresholds.EUTRAN, AccessNetworkType.EUTRAN);
-        mPhone.setSignalStrengthReportingCriteria(
-                AccessNetworkThresholds.CDMA2000, AccessNetworkType.CDMA2000);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
+                AccessNetworkThresholds.GERAN, AccessNetworkType.GERAN, true);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSCP,
+                AccessNetworkThresholds.UTRAN, AccessNetworkType.UTRAN, true);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRP,
+                AccessNetworkThresholds.EUTRAN_RSRP, AccessNetworkType.EUTRAN, true);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
+                AccessNetworkThresholds.CDMA2000, AccessNetworkType.CDMA2000, true);
+        if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRQ,
+                    AccessNetworkThresholds.EUTRAN_RSRQ, AccessNetworkType.EUTRAN, false);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSNR,
+                    AccessNetworkThresholds.EUTRAN_RSSNR, AccessNetworkType.EUTRAN, true);
+
+            // Defaultly we only need SSRSRP for NGRAN signal criterial reporting
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRP,
+                    AccessNetworkThresholds.NGRAN_RSRSRP, AccessNetworkType.NGRAN, true);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRQ,
+                    AccessNetworkThresholds.NGRAN_RSRSRQ, AccessNetworkType.NGRAN, false);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSSINR,
+                    AccessNetworkThresholds.NGRAN_SSSINR, AccessNetworkType.NGRAN, false);
+        }
     }
 
     private void setLinkCapacityReportingCriteria() {
@@ -730,11 +767,11 @@
         };
 
         /**
-         * List of default dBm thresholds for EUTRAN {@link AccessNetworkType}.
+         * List of default dBm RSRP thresholds for EUTRAN {@link AccessNetworkType}.
          *
          * These thresholds are taken from the LTE RSRP defaults in {@link CarrierConfigManager}.
          */
-        public static final int[] EUTRAN = new int[] {
+        public static final int[] EUTRAN_RSRP = new int[] {
             -128, /* SIGNAL_STRENGTH_POOR */
             -118, /* SIGNAL_STRENGTH_MODERATE */
             -108, /* SIGNAL_STRENGTH_GOOD */
@@ -742,6 +779,30 @@
         };
 
         /**
+         * List of default dB RSRQ thresholds for EUTRAN {@link AccessNetworkType}.
+         *
+         * These thresholds are taken from the LTE RSRQ defaults in {@link CarrierConfigManager}.
+         */
+        public static final int[] EUTRAN_RSRQ = new int[] {
+            -19,  /* SIGNAL_STRENGTH_POOR */
+            -17,  /* SIGNAL_STRENGTH_MODERATE */
+            -14,  /* SIGNAL_STRENGTH_GOOD */
+            -12   /* SIGNAL_STRENGTH_GREAT */
+        };
+
+        /**
+         * List of default 10*dB RSSNR thresholds for EUTRAN {@link AccessNetworkType}.
+         *
+         * These thresholds are taken from the LTE RSSNR defaults in {@link CarrierConfigManager}.
+         */
+        public static final int[] EUTRAN_RSSNR = new int[] {
+            -30,  /* SIGNAL_STRENGTH_POOR */
+            10,   /* SIGNAL_STRENGTH_MODERATE */
+            45,   /* SIGNAL_STRENGTH_GOOD */
+            130   /* SIGNAL_STRENGTH_GREAT */
+        };
+
+        /**
          * List of dBm thresholds for CDMA2000 {@link AccessNetworkType}.
          *
          * These correspond to EVDO level thresholds.
@@ -752,6 +813,36 @@
             -75,
             -65
         };
+
+        /**
+         * List of dB thresholds for NGRAN {@link AccessNetworkType} RSRSRP
+         */
+        public static final int[] NGRAN_RSRSRP = new int[] {
+            -110, /* SIGNAL_STRENGTH_POOR */
+            -90, /* SIGNAL_STRENGTH_MODERATE */
+            -80, /* SIGNAL_STRENGTH_GOOD */
+            -65,  /* SIGNAL_STRENGTH_GREAT */
+        };
+
+        /**
+         * List of dB thresholds for NGRAN {@link AccessNetworkType} RSRSRP
+         */
+        public static final int[] NGRAN_RSRSRQ = new int[] {
+            -16, /* SIGNAL_STRENGTH_POOR */
+            -11, /* SIGNAL_STRENGTH_MODERATE */
+            -9, /* SIGNAL_STRENGTH_GOOD */
+            -7  /* SIGNAL_STRENGTH_GREAT */
+        };
+
+        /**
+         * List of dB thresholds for NGRAN {@link AccessNetworkType} SSSINR
+         */
+        public static final int[] NGRAN_SSSINR = new int[] {
+            -5, /* SIGNAL_STRENGTH_POOR */
+            5, /* SIGNAL_STRENGTH_MODERATE */
+            15, /* SIGNAL_STRENGTH_GOOD */
+            30  /* SIGNAL_STRENGTH_GREAT */
+        };
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/DriverCall.java b/src/java/com/android/internal/telephony/DriverCall.java
index 3a7947d..a67de7a 100644
--- a/src/java/com/android/internal/telephony/DriverCall.java
+++ b/src/java/com/android/internal/telephony/DriverCall.java
@@ -16,9 +16,10 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCall.java b/src/java/com/android/internal/telephony/GsmCdmaCall.java
index da2b057..cc1b2c0 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCall.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCall.java
@@ -16,7 +16,8 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
 import java.util.List;
 
 /**
@@ -60,6 +61,16 @@
         mOwner.hangup(this);
     }
 
+    /**
+     * Hangup the ringing call with a specified reason; reason is not supported on GSM/CDMA.
+     * @param rejectReason
+     */
+    @Override
+    public void hangup(@android.telecom.Call.RejectReason int rejectReason)
+            throws CallStateException {
+        mOwner.hangup(this);
+    }
+
     @Override
     public String toString() {
         return mState.toString();
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 1bbcd5e..2e86855 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,14 +28,13 @@
 import android.os.PersistableBundle;
 import android.os.Registrant;
 import android.os.RegistrantList;
-import android.os.SystemProperties;
+import android.sysprop.TelephonyProperties;
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellLocation;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
-import android.telephony.ServiceState;
+import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
@@ -45,6 +44,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -656,14 +656,13 @@
      * @throws CallStateException
      */
     public void checkForDialIssues(boolean isEmergencyCall) throws CallStateException {
-        String disableCall = SystemProperties.get(
-                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
+        boolean disableCall = TelephonyProperties.disable_call().orElse(false);
 
         if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_ON) {
             throw new CallStateException(CallStateException.ERROR_POWER_OFF,
                     "Modem not powered");
         }
-        if (disableCall.equals("true")) {
+        if (disableCall) {
             throw new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
                     "Calling disabled via ro.telephony.disable-call property");
         }
@@ -896,8 +895,6 @@
                                 hoConnection.mPreHandoverState != GsmCdmaCall.State.HOLDING &&
                                 dc.state == DriverCall.State.ACTIVE) {
                             mConnections[i].onConnectedInOrOut();
-                        } else {
-                            mConnections[i].onConnectedConnectionMigrated();
                         }
 
                         mHandoverConnections.remove(hoConnection);
@@ -1468,6 +1465,13 @@
                 if (isPhoneTypeGsm()) {
                     ar = (AsyncResult) msg.obj;
                     if (ar.exception != null) {
+                        if (msg.what == EVENT_SWITCH_RESULT) {
+                            Connection connection = mForegroundCall.getLatestConnection();
+                            if (connection != null) {
+                                connection.onConnectionEvent(
+                                        android.telecom.Connection.EVENT_CALL_SWITCH_FAILED, null);
+                            }
+                        }
                         mPhone.notifySuppServiceFailed(getFailedService(msg.what));
                     }
                     operationComplete();
@@ -1534,7 +1538,7 @@
                     causeCode == CallFailCause.BEARER_NOT_AVAIL ||
                     causeCode == CallFailCause.ERROR_UNSPECIFIED) {
 
-                    CellLocation loc = mPhone.getCellLocation();
+                    CellLocation loc = mPhone.getCellIdentity().asCellLocation();
                     int cid = -1;
                     if (loc != null) {
                         if (loc instanceof GsmCellLocation) {
@@ -1654,7 +1658,7 @@
      * @param vrat the RIL voice radio technology for CS calls,
      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      */
-    public void dispatchCsCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+    public void dispatchCsCallRadioTech(@RilRadioTechnology int vrat) {
         if (mConnections == null) {
             log("dispatchCsCallRadioTech: mConnections is null");
             return;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index b3dea8e..1c49f20 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -15,28 +15,28 @@
  */
 
 package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
-import android.os.PowerManager;
 import android.os.Registrant;
 import android.os.SystemClock;
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
 import com.android.internal.telephony.uicc.UiccCardApplication;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
@@ -74,27 +74,20 @@
 
     Handler mHandler;
 
-    private PowerManager.WakeLock mPartialWakeLock;
-
     // The cached delay to be used between DTMF tones fetched from carrier config.
     private int mDtmfToneDelay = 0;
 
-    // Store the current audio codec
-    private int mAudioCodec = DriverCall.AUDIO_QUALITY_UNSPECIFIED;
-
     private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
 
     //***** Event Constants
     static final int EVENT_DTMF_DONE = 1;
     static final int EVENT_PAUSE_DONE = 2;
     static final int EVENT_NEXT_POST_DIAL = 3;
-    static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
     static final int EVENT_DTMF_DELAY_DONE = 5;
 
     //***** Constants
     static final int PAUSE_DELAY_MILLIS_GSM = 3 * 1000;
     static final int PAUSE_DELAY_MILLIS_CDMA = 2 * 1000;
-    static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
 
     //***** Inner Classes
 
@@ -111,9 +104,6 @@
                 case EVENT_PAUSE_DONE:
                     processNextPostDialChar();
                     break;
-                case EVENT_WAKE_LOCK_TIMEOUT:
-                    releaseWakeLock();
-                    break;
                 case EVENT_DTMF_DONE:
                     // We may need to add a delay specified by carrier between DTMF tones that are
                     // sent out.
@@ -129,8 +119,6 @@
     /** This is probably an MT call that we first saw in a CLCC response or a hand over. */
     public GsmCdmaConnection (GsmCdmaPhone phone, DriverCall dc, GsmCdmaCallTracker ct, int index) {
         super(phone.getPhoneType());
-        createWakeLock(phone.getContext());
-        acquireWakeLock();
 
         mOwner = ct;
         mHandler = new MyHandler(mOwner.getLooper());
@@ -161,8 +149,6 @@
     public GsmCdmaConnection (GsmCdmaPhone phone, String dialString, GsmCdmaCallTracker ct,
                               GsmCdmaCall parent, boolean isEmergencyCall) {
         super(phone.getPhoneType());
-        createWakeLock(phone.getContext());
-        acquireWakeLock();
 
         mOwner = ct;
         mHandler = new MyHandler(mOwner.getLooper());
@@ -217,8 +203,6 @@
     public GsmCdmaConnection(Context context, CdmaCallWaitingNotification cw, GsmCdmaCallTracker ct,
                              GsmCdmaCall parent) {
         super(parent.getPhone().getPhoneType());
-        createWakeLock(context);
-        acquireWakeLock();
 
         mOwner = ct;
         mHandler = new MyHandler(mOwner.getLooper());
@@ -242,7 +226,6 @@
         if (mParent != null) {
             mParent.detach(this);
         }
-        releaseAllWakeLocks();
     }
 
     static boolean equalsHandlesNulls(Object a, Object b) {
@@ -623,7 +606,6 @@
             mOrigConnection = null;
         }
         clearPostDialListeners();
-        releaseWakeLock();
         return changed;
     }
 
@@ -639,7 +621,6 @@
                 mParent.detach(this);
             }
         }
-        releaseWakeLock();
     }
 
     // Returns true if state has changed, false if nothing changed
@@ -780,23 +761,9 @@
         if (!mIsIncoming) {
             // outgoing calls only
             processNextPostDialChar();
-        } else {
-            // Only release wake lock for incoming calls, for outgoing calls the wake lock
-            // will be released after any pause-dial is completed
-            releaseWakeLock();
         }
     }
 
-    /**
-     * We have completed the migration of another connection to this GsmCdmaConnection (for example,
-     * in the case of SRVCC) and not still DIALING/ALERTING/INCOMING/WAITING.
-     */
-    void onConnectedConnectionMigrated() {
-        // We can release the wakelock in this case, the migrated call is not still
-        // DIALING/ALERTING/INCOMING/WAITING.
-        releaseWakeLock();
-    }
-
     private void
     doDisconnect() {
         mIndex = -1;
@@ -881,17 +848,7 @@
     @Override
     protected void finalize()
     {
-        /**
-         * It is understood that This finalizer is not guaranteed
-         * to be called and the release lock call is here just in
-         * case there is some path that doesn't call onDisconnect
-         * and or onConnectedInOrOut.
-         */
-        if (mPartialWakeLock != null && mPartialWakeLock.isHeld()) {
-            Rlog.e(LOG_TAG, "UNEXPECTED; mPartialWakeLock is held when finalizing.");
-        }
         clearPostDialListeners();
-        releaseWakeLock();
     }
 
     private void
@@ -900,7 +857,6 @@
         Registrant postDialHandler;
 
         if (mPostDialState == PostDialState.CANCELLED) {
-            releaseWakeLock();
             return;
         }
 
@@ -908,9 +864,6 @@
                 mPostDialString.length() <= mNextPostDialChar) {
             setPostDialState(PostDialState.COMPLETE);
 
-            // We were holding a wake lock until pause-dial was complete, so give it up now
-            releaseWakeLock();
-
             // notifyMessage.arg1 is 0 on complete
             c = 0;
         } else {
@@ -1004,60 +957,18 @@
      * @param s new PostDialState
      */
     private void setPostDialState(PostDialState s) {
-        if (s == PostDialState.STARTED ||
-                s == PostDialState.PAUSE) {
-            synchronized (mPartialWakeLock) {
-                if (mPartialWakeLock.isHeld()) {
-                    mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
-                } else {
-                    acquireWakeLock();
-                }
-                Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
-                mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
-            }
-        } else {
-            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
-            releaseWakeLock();
-        }
         mPostDialState = s;
         notifyPostDialListeners();
     }
 
     @UnsupportedAppUsage
     private void createWakeLock(Context context) {
-        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
+        // no-op
     }
 
     @UnsupportedAppUsage
     private void acquireWakeLock() {
-        if (mPartialWakeLock != null) {
-            synchronized (mPartialWakeLock) {
-                log("acquireWakeLock");
-                mPartialWakeLock.acquire();
-            }
-        }
-    }
-
-    private void releaseWakeLock() {
-        if (mPartialWakeLock != null) {
-            synchronized (mPartialWakeLock) {
-                if (mPartialWakeLock.isHeld()) {
-                    log("releaseWakeLock");
-                    mPartialWakeLock.release();
-                }
-            }
-        }
-    }
-
-    private void releaseAllWakeLocks() {
-        if (mPartialWakeLock != null) {
-            synchronized (mPartialWakeLock) {
-                while (mPartialWakeLock.isHeld()) {
-                    mPartialWakeLock.release();
-                }
-            }
-        }
+        // no-op
     }
 
     @UnsupportedAppUsage
@@ -1205,6 +1116,20 @@
     }
 
     /**
+     * Get the corresponding EmergencyNumberTracker associated with the connection.
+     * @return the EmergencyNumberTracker
+     */
+    public EmergencyNumberTracker getEmergencyNumberTracker() {
+        if (mOwner != null) {
+            Phone phone = mOwner.getPhone();
+            if (phone != null) {
+                return phone.getEmergencyNumberTracker();
+            }
+        }
+        return null;
+    }
+
+    /**
      * @return {@code true} if this call is an OTASP activation call, {@code false} otherwise.
      */
     public boolean isOtaspCall() {
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 82bb78b..e703b2a 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -30,8 +30,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -55,16 +55,20 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Telephony;
+import android.sysprop.TelephonyProperties;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
-import android.telephony.CellLocation;
+import android.telephony.CellIdentity;
+import android.telephony.DataFailCause;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkScanRequest;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
+import android.telephony.ServiceState.RilRadioTechnology;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -86,6 +90,7 @@
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
+import com.android.internal.telephony.uicc.IccCardStatus;
 import com.android.internal.telephony.uicc.IccException;
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.IccVmNotSupportedException;
@@ -98,7 +103,8 @@
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.telephony.uicc.UiccSlot;
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.ArrayUtils;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -135,7 +141,7 @@
 
     //CDMA
     // Default Emergency Callback Mode exit timer
-    private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
+    private static final long DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
     private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
     public static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
     public static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
@@ -150,6 +156,7 @@
     private String mMeid;
     // string to define how the carrier specifies its own ota sp number
     private String mCarrierOtaSpNumSchema;
+    private Boolean mUiccApplicationsEnabled = null;
 
     // A runnable which is used to automatically exit from Ecm after a period of time.
     private Runnable mExitEcmRunnable = new Runnable() {
@@ -322,7 +329,10 @@
         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mCi.registerForOn(this, EVENT_RADIO_ON, null);
         mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+        mCi.registerUiccApplicationEnablementChanged(this, EVENT_UICC_APPS_ENABLEMENT_CHANGED,
+                null);
         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
+        mCi.setOnRegistrationFailed(this, EVENT_REGISTRATION_FAILED, null);
 
         //GSM
         mCi.setOnUSSD(this, EVENT_USSD, null);
@@ -340,8 +350,8 @@
         mCarrierOtaSpNumSchema = TelephonyManager.from(mContext).getOtaSpNumberSchemaForPhone(
                 getPhoneId(), "");
 
-        mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
-                TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
+        mResetModemOnRadioTechnologyChange = TelephonyProperties.reset_on_radio_tech_change()
+                .orElse(false);
 
         mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
         mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
@@ -378,8 +388,7 @@
             mIsPhoneInEcmState = getInEcmMode();
             if (mIsPhoneInEcmState) {
                 // Send a message which will invoke handleExitEmergencyCallbackMode
-                mCi.exitEmergencyCallbackMode(
-                        obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
+                mCi.exitEmergencyCallbackMode(null);
             }
 
             mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
@@ -495,6 +504,7 @@
 
     @UnsupportedAppUsage
     @Override
+    @NonNull
     public ServiceState getServiceState() {
         if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
             if (mImsPhone != null) {
@@ -512,8 +522,8 @@
     }
 
     @Override
-    public void getCellLocation(WorkSource workSource, Message rspMsg) {
-        mSST.requestCellLocation(workSource, rspMsg);
+    public void getCellIdentity(WorkSource workSource, Message rspMsg) {
+        mSST.requestCellIdentity(workSource, rspMsg);
     }
 
     @UnsupportedAppUsage
@@ -586,12 +596,53 @@
         return mPendingMMIs;
     }
 
+    private @NonNull DcTracker getActiveDcTrackerForApn(@NonNull String apnType) {
+        int currentTransport = mTransportManager.getCurrentTransport(
+                ApnSetting.getApnTypesBitmaskFromString(apnType));
+        return getDcTracker(currentTransport);
+    }
+
+    @Override
+    public PreciseDataConnectionState getPreciseDataConnectionState(String apnType) {
+        // If we are OOS, then all data connections are null.
+        // FIXME: we need to figure out how to report the EIMS PDN connectivity here, which
+        // should imply emergency attach - today emergency attach is unknown at the AP,
+        // so, we take a guess.
+        boolean isEmergencyData = isPhoneTypeGsm()
+                && apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY);
+
+        if (mSST == null
+                || ((mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE)
+                        && !isEmergencyData)) {
+            return new PreciseDataConnectionState(TelephonyManager.DATA_DISCONNECTED,
+                    TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                    ApnSetting.getApnTypesBitmaskFromString(apnType),
+                    apnType, null, DataFailCause.NONE, null);
+        }
+
+        // must never be null
+        final DcTracker dctForApn = getActiveDcTrackerForApn(apnType);
+
+        int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        // Always non-null
+        ServiceState ss = getServiceState();
+        if (ss != null) {
+            networkType = ss.getDataNetworkType();
+        }
+
+        return dctForApn.getPreciseDataConnectionState(apnType, isDataSuspended(), networkType);
+    }
+
+    boolean isDataSuspended() {
+        return mCT.mState != PhoneConstants.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed();
+    }
+
     @Override
     public PhoneConstants.DataState getDataConnectionState(String apnType) {
         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
 
         if (mSST == null) {
-            // Radio Technology Change is ongoning, dispose() and removeReferences() have
+            // Radio Technology Change is ongoing, dispose() and removeReferences() have
             // already been called
 
             ret = PhoneConstants.DataState.DISCONNECTED;
@@ -612,8 +663,7 @@
                 switch (getDcTracker(currentTransport).getState(apnType)) {
                     case CONNECTED:
                     case DISCONNECTING:
-                        if (mCT.mState != PhoneConstants.State.IDLE
-                                && !mSST.isConcurrentVoiceAndDataAllowed()) {
+                        if (isDataSuspended()) {
                             ret = PhoneConstants.DataState.SUSPENDED;
                         } else {
                             ret = PhoneConstants.DataState.CONNECTED;
@@ -761,12 +811,12 @@
     }
 
     /**
-     * Notify that the CellLocation has changed.
+     * Notify that the cell location has changed.
      *
-     * @param cl the new CellLocation
+     * @param cellIdentity the new CellIdentity
      */
-    public void notifyLocationChanged(CellLocation cl) {
-        mNotifier.notifyCellLocation(this, cl);
+    public void notifyLocationChanged(CellIdentity cellIdentity) {
+        mNotifier.notifyCellLocation(this, cellIdentity);
     }
 
     @Override
@@ -947,27 +997,27 @@
     /**
      * ImsService reports "IN_SERVICE" for its voice registration state even if the device
      * has lost the physical link to the tower. This helper method merges the IMS and modem
-     * ServiceState, only overriding the voice registration state when we are registered to IMS over
-     * IWLAN. In this case the voice registration state will always be "OUT_OF_SERVICE", so override
-     * the voice registration state with the data registration state.
+     * ServiceState, only overriding the voice registration state when we are registered to IMS. In
+     * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice
+     * registration state with the data registration state.
      */
     private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) {
+        // No need to merge states if the baseSs is IN_SERVICE.
+        if (baseSs.getState() == ServiceState.STATE_IN_SERVICE) {
+            return baseSs;
+        }
         // "IN_SERVICE" in this case means IMS is registered.
-        if (imsSs.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
+        if (imsSs.getState() != ServiceState.STATE_IN_SERVICE) {
             return baseSs;
         }
 
-        if (imsSs.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
-            ServiceState newSs = new ServiceState(baseSs);
-            // Voice override for IWLAN. In this case, voice registration is OUT_OF_SERVICE, but
-            // the data RAT is IWLAN, so use that as a basis for determining whether or not the
-            // physical link is available.
-            newSs.setVoiceRegState(baseSs.getDataRegState());
-            newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
-            return newSs;
-        }
-
-        return baseSs;
+        ServiceState newSs = new ServiceState(baseSs);
+        // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but
+        // IMS is available, so use data registration state as a basis for determining
+        // whether or not the physical link is available.
+        newSs.setVoiceRegState(baseSs.getDataRegistrationState());
+        newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
+        return newSs;
     }
 
     private boolean handleCallDeflectionIncallSupplementaryService(
@@ -1171,6 +1221,38 @@
                 ringingCallState.isAlive());
     }
 
+    private boolean useImsForCall(DialArgs dialArgs) {
+        return isImsUseEnabled()
+                && mImsPhone != null
+                && (mImsPhone.isVolteEnabled() || mImsPhone.isWifiCallingEnabled() ||
+                (mImsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState)))
+                && (mImsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
+    }
+
+    @Override
+    public Connection startConference(String[] participantsToDial, DialArgs dialArgs)
+            throws CallStateException {
+        Phone imsPhone = mImsPhone;
+        boolean useImsForCall = useImsForCall(dialArgs);
+        logd("useImsForCall=" + useImsForCall);
+        if (useImsForCall) {
+            try {
+                if (DBG) logd("Trying IMS PS Conference call");
+                return imsPhone.startConference(participantsToDial, dialArgs);
+            } catch (CallStateException e) {
+                if (DBG) logd("IMS PS conference call exception " + e +
+                        "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone);
+                 CallStateException ce = new CallStateException(e.getError(), e.getMessage());
+                 ce.setStackTrace(e.getStackTrace());
+                 throw ce;
+            }
+        } else {
+            throw new CallStateException(
+                CallStateException.ERROR_OUT_OF_SERVICE,
+                "cannot dial conference call in out of service");
+        }
+    }
+
     @Override
     public Connection dial(String dialString, @NonNull DialArgs dialArgs)
             throws CallStateException {
@@ -1191,11 +1273,7 @@
         boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId())
                 .getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);
 
-        boolean useImsForCall = isImsUseEnabled()
-                 && imsPhone != null
-                 && (imsPhone.isVolteEnabled() || imsPhone.isWifiCallingEnabled() ||
-                 (imsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState)))
-                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
+        boolean useImsForCall = useImsForCall(dialArgs)
                  && (isWpsCall ? allowWpsOverIms : true);
 
         boolean useImsForEmergency = imsPhone != null
@@ -1252,7 +1330,8 @@
         }
 
         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE
-                && mSST.mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE && !isEmergency) {
+                && mSST.mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE
+                && !isEmergency) {
             throw new CallStateException("cannot dial in current state");
         }
         // Check non-emergency voice CS call - shouldn't dial when POWER_OFF
@@ -1265,11 +1344,12 @@
                 "cannot dial voice call in airplane mode");
         }
         // Check for service before placing non emergency CS voice call.
-        // Allow dial only if either CS is camped on any RAT (or) PS is in LTE service.
+        // Allow dial only if either CS is camped on any RAT (or) PS is in LTE/NR service.
         if (mSST != null
                 && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE /* CS out of service */
-                && !(mSST.mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
-                    && ServiceState.isLte(mSST.mSS.getRilDataRadioTechnology())) /* PS not in LTE */
+                && !(mSST.mSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE
+                && ServiceState.isPsOnlyTech(
+                        mSST.mSS.getRilDataRadioTechnology())) /* PS not in LTE/NR */
                 && !VideoProfile.isVideo(dialArgs.videoState) /* voice call */
                 && !isEmergency /* non-emergency call */) {
             throw new CallStateException(
@@ -1687,7 +1767,10 @@
 
     @Override
     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
-        return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType, mContext);
+        String operatorNumeric = TelephonyManager.from(mContext)
+                .getSimOperatorNumericForPhone(mPhoneId);
+        return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType,
+                mContext, operatorNumeric);
     }
 
     @Override
@@ -1731,6 +1814,11 @@
     }
 
     @Override
+    public int getEmergencyNumberDbVersion() {
+        return getEmergencyNumberTracker().getEmergencyNumberDbVersion();
+    }
+
+    @Override
     public void resetCarrierKeysForImsiEncryption() {
         mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId);
     }
@@ -2397,6 +2485,8 @@
 
         mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
         mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
+        mCi.areUiccApplicationsEnabled(obtainMessage(EVENT_GET_UICC_APPS_ENABLEMENT_DONE));
+
         startLceAfterRadioIsAvailable();
     }
 
@@ -2697,11 +2787,18 @@
                 }
                 break;
 
+            case EVENT_REGISTRATION_FAILED:
+                logd("Event RegistrationFailed Received");
+                ar = (AsyncResult) msg.obj;
+                RegistrationFailedEvent rfe = (RegistrationFailedEvent) ar.result;
+                mNotifier.notifyRegistrationFailed(this, rfe.cellIdentity, rfe.chosenPlmn,
+                        rfe.domain, rfe.causeCode, rfe.additionalCauseCode);
+                break;
+
             case EVENT_SET_CALL_FORWARD_DONE:
                 ar = (AsyncResult)msg.obj;
-                IccRecords r = mIccRecords.get();
                 Cfu cfu = (Cfu) ar.userObj;
-                if (ar.exception == null && r != null) {
+                if (ar.exception == null) {
                     setVoiceCallForwardingFlag(1, msg.arg1 == 1, cfu.mSetCfNumber);
                 }
                 if (cfu.mOnComplete != null) {
@@ -2836,6 +2933,35 @@
                     onComplete.sendToTarget();
                 }
                 break;
+            case EVENT_GET_UICC_APPS_ENABLEMENT_DONE:
+            case EVENT_UICC_APPS_ENABLEMENT_CHANGED: {
+                ar = (AsyncResult) msg.obj;
+                if (ar == null) return;
+                if (ar.exception != null) {
+                    logd("Received exception on event" + msg.what + " : " + ar.exception);
+                    return;
+                }
+
+                mUiccApplicationsEnabled = (Boolean) ar.result;
+                reapplyUiccAppsEnablementIfNeeded();
+                break;
+            }
+            case EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE: {
+                ar = (AsyncResult) msg.obj;
+                if (ar == null || ar.exception == null) return;
+                // TODO: b/146181737 don't throw exception and uncomment the retry below.
+                boolean expectedValue = (boolean) ar.userObj;
+                CommandException.Error error = ((CommandException) ar.exception).getCommandError();
+                throw new RuntimeException("Error received when re-applying uicc application"
+                        + " setting to " +  expectedValue + " on phone " + mPhoneId
+                        + " Error code: " + error);
+//                if (error == INTERNAL_ERR || error == SIM_BUSY) {
+//                    // Retry for certain errors, but not for others like RADIO_NOT_AVAILABLE or
+//                    // SIM_ABSENT, as they will trigger it whey they become available.
+//                    postDelayed(()->reapplyUiccAppsEnablementIfNeeded(), 1000);
+//                }
+//                break;
+            }
             default:
                 super.handleMessage(msg);
         }
@@ -2933,6 +3059,8 @@
                 updateDataConnectionTracker();
             }
         }
+
+        reapplyUiccAppsEnablementIfNeeded();
     }
 
     private void processIccRecordEvents(int eventCode) {
@@ -3008,20 +3136,17 @@
     }
 
     private void handleCfuQueryResult(CallForwardInfo[] infos) {
-        IccRecords r = mIccRecords.get();
-        if (r != null) {
-            if (infos == null || infos.length == 0) {
-                // Assume the default is not active
-                // Set unconditional CFF in SIM to false
-                setVoiceCallForwardingFlag(1, false, null);
-            } else {
-                for (int i = 0, s = infos.length; i < s; i++) {
-                    if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
-                        setVoiceCallForwardingFlag(1, (infos[i].status == 1),
-                            infos[i].number);
-                        // should only have the one
-                        break;
-                    }
+        if (infos == null || infos.length == 0) {
+            // Assume the default is not active
+            // Set unconditional CFF in SIM to false
+            setVoiceCallForwardingFlag(1, false, null);
+        } else {
+            for (int i = 0, s = infos.length; i < s; i++) {
+                if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
+                    setVoiceCallForwardingFlag(1, (infos[i].status == 1),
+                        infos[i].number);
+                    // should only have the one
+                    break;
                 }
             }
         }
@@ -3185,16 +3310,13 @@
             Rlog.d(LOG_TAG, "exitEmergencyCallbackMode: mImsPhone=" + mImsPhone
                     + " isPhoneTypeGsm=" + isPhoneTypeGsm());
         }
-        if (isPhoneTypeGsm()) {
-            if (mImsPhone != null) {
-                mImsPhone.exitEmergencyCallbackMode();
-            }
+        if (mImsPhone != null && mImsPhone.isInImsEcm()) {
+            mImsPhone.exitEmergencyCallbackMode();
         } else {
             if (mWakeLock.isHeld()) {
                 mWakeLock.release();
             }
-            // Send a message which will invoke handleExitEmergencyCallbackMode
-            mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
+            mCi.exitEmergencyCallbackMode(null);
         }
     }
 
@@ -3213,8 +3335,8 @@
 
             // Post this runnable so we will automatically exit
             // if no one invokes exitEmergencyCallbackMode() directly.
-            long delayInMillis = SystemProperties.getLong(
-                    TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
+            long delayInMillis = TelephonyProperties.ecm_exit_timer()
+                    .orElse(DEFAULT_ECM_EXIT_TIMER_VALUE);
             postDelayed(mExitEcmRunnable, delayInMillis);
             // We don't want to go to sleep while in Ecm
             mWakeLock.acquire();
@@ -3271,8 +3393,8 @@
                 mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE);
                 break;
             case RESTART_ECM_TIMER:
-                long delayInMillis = SystemProperties.getLong(
-                        TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
+                long delayInMillis = TelephonyProperties.ecm_exit_timer()
+                        .orElse(DEFAULT_ECM_EXIT_TIMER_VALUE);
                 postDelayed(mExitEcmRunnable, delayInMillis);
                 mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE);
                 break;
@@ -3478,6 +3600,11 @@
     }
 
     @Override
+    public int getOtasp() {
+        return mSST.getOtasp();
+    }
+
+    @Override
     public int getCdmaEriIconIndex() {
         if (isPhoneTypeGsm()) {
             return super.getCdmaEriIconIndex();
@@ -3527,8 +3654,8 @@
     private void phoneObjectUpdater(int newVoiceRadioTech) {
         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
 
-        // Check for a voice over lte replacement
-        if (ServiceState.isLte(newVoiceRadioTech)
+        // Check for a voice over LTE/NR replacement
+        if (ServiceState.isPsOnlyTech(newVoiceRadioTech)
                 || (newVoiceRadioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)) {
             CarrierConfigManager configMgr = (CarrierConfigManager)
                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -3652,9 +3779,11 @@
     }
 
     @Override
-    public void setSignalStrengthReportingCriteria(int[] thresholds, int ran) {
-        mCi.setSignalStrengthReportingCriteria(REPORTING_HYSTERESIS_MILLIS, REPORTING_HYSTERESIS_DB,
-                thresholds, ran, null);
+    public void setSignalStrengthReportingCriteria(
+            int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
+        mCi.setSignalStrengthReportingCriteria(new SignalThresholdInfo(signalStrengthMeasure,
+                REPORTING_HYSTERESIS_MILLIS, REPORTING_HYSTERESIS_DB, thresholds, isEnabled),
+                ran, null);
     }
 
     @Override
@@ -3827,7 +3956,8 @@
     private static final int[] VOICE_PS_CALL_RADIO_TECHNOLOGY = {
             ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
             ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
+            ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
+            ServiceState.RIL_RADIO_TECHNOLOGY_NR
     };
 
     /**
@@ -3839,10 +3969,10 @@
      * @return the RIL voice radio technology used for CS calls,
      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      */
-    public @ServiceState.RilRadioTechnology int getCsCallRadioTech() {
+    public @RilRadioTechnology int getCsCallRadioTech() {
         int calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
         if (mSST != null) {
-            calcVrat = getCsCallRadioTech(mSST.mSS.getVoiceRegState(),
+            calcVrat = getCsCallRadioTech(mSST.mSS.getState(),
                     mSST.mSS.getRilVoiceRadioTechnology());
         }
 
@@ -3868,7 +3998,7 @@
      * @return the RIL voice radio technology used for CS calls,
      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      */
-    private @ServiceState.RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
+    private @RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
         logd("getCsCallRadioTech, current vrs=" + vrs + ", vrat=" + vrat);
         int calcVrat = vrat;
         if (vrs != ServiceState.STATE_IN_SERVICE
@@ -4027,4 +4157,55 @@
                 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF);
         updateUiTtyMode(ttyMode);
     }
+
+    private void reapplyUiccAppsEnablementIfNeeded() {
+        UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId);
+
+        // If no card is present or we don't have mUiccApplicationsEnabled yet, do nothing.
+        if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT
+                || mUiccApplicationsEnabled == null) {
+            return;
+        }
+
+        String iccId = slot.getIccId();
+        if (iccId == null) return;
+
+        SubscriptionInfo info = SubscriptionController.getInstance().getSubInfoForIccId(iccId);
+
+        // If info is null, it could be a new subscription. By default we enable it.
+        boolean expectedValue = info == null ? true : info.areUiccApplicationsEnabled();
+
+        // If for any reason current state is different from configured state, re-apply the
+        // configured state.
+        if (expectedValue != mUiccApplicationsEnabled) {
+            mCi.enableUiccApplications(expectedValue, Message.obtain(
+                    this, EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE, expectedValue));
+        }
+    }
+
+    // Enable or disable uicc applications.
+    @Override
+    public void enableUiccApplications(boolean enable, Message onCompleteMessage) {
+        // First check if card is present. Otherwise mUiccApplicationsDisabled doesn't make
+        // any sense.
+        UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId);
+        if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT) {
+            if (onCompleteMessage != null) {
+                AsyncResult.forMessage(onCompleteMessage, null,
+                        new IllegalStateException("No SIM card is present"));
+                onCompleteMessage.sendToTarget();
+            }
+            return;
+        }
+
+        mCi.enableUiccApplications(enable, onCompleteMessage);
+    }
+
+    /**
+     * Whether disabling a physical subscription is supported or not.
+     */
+    @Override
+    public boolean canDisablePhysicalSubscription() {
+        return mCi.canToggleUiccApplicationsEnablement();
+    }
 }
diff --git a/src/java/com/android/internal/telephony/HardwareConfig.java b/src/java/com/android/internal/telephony/HardwareConfig.java
index 8623354..cdce602 100644
--- a/src/java/com/android/internal/telephony/HardwareConfig.java
+++ b/src/java/com/android/internal/telephony/HardwareConfig.java
@@ -16,9 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.Rlog;
 import java.util.BitSet;
-import android.telephony.ServiceState;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/IccCard.java b/src/java/com/android/internal/telephony/IccCard.java
index d15c44c..b082516 100644
--- a/src/java/com/android/internal/telephony/IccCard.java
+++ b/src/java/com/android/internal/telephony/IccCard.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
diff --git a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index e619e61..a290c73 100644
--- a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -16,13 +16,12 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.PackageManager;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.uicc.AdnRecord;
 import com.android.internal.telephony.uicc.AdnRecordCache;
@@ -30,6 +29,7 @@
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccFileHandler;
 import com.android.internal.telephony.uicc.IccRecords;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/src/java/com/android/internal/telephony/IccProvider.java b/src/java/com/android/internal/telephony/IccProvider.java
index ae5cd7b..76dc518 100644
--- a/src/java/com/android/internal/telephony/IccProvider.java
+++ b/src/java/com/android/internal/telephony/IccProvider.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.UriMatcher;
@@ -26,17 +26,16 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.uicc.AdnRecord;
 import com.android.internal.telephony.uicc.IccConstants;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 
-
 /**
  * {@hide}
  */
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index c98d265..017cd95 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -21,11 +21,14 @@
 import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
 
 import android.Manifest;
-import android.annotation.UnsupportedAppUsage;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
@@ -33,12 +36,15 @@
 import android.os.AsyncResult;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.UserManager;
 import android.provider.Telephony;
-import android.telephony.Rlog;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SmsCbMessage;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.util.LocalLog;
 import android.util.Log;
@@ -49,7 +55,10 @@
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccFileHandler;
 import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.uicc.UiccController;
+import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.util.HexDump;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -126,7 +135,7 @@
                             markMessagesAsRead((ArrayList<byte[]>) ar.result);
                         } else {
                             if (Rlog.isLoggable("SMS", Log.DEBUG)) {
-                                log("Cannot load Sms records");
+                                loge("Cannot load Sms records");
                             }
                             mSms = null;
                         }
@@ -147,7 +156,7 @@
                         if (ar.exception == null) {
                             mSmsc = (String) ar.result;
                         } else {
-                            log("Cannot read SMSC");
+                            loge("Cannot read SMSC");
                             mSmsc = null;
                         }
                         mLock.notifyAll();
@@ -181,6 +190,31 @@
         mAppOps = appOps;
         mDispatchersController = dispatchersController;
         mSmsPermissions = new SmsPermissions(phone, context, appOps);
+
+        mContext.registerReceiver(
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED
+                                .equals(intent.getAction())) {
+                            if (mPhone.getPhoneId() == intent.getIntExtra(
+                                    CarrierConfigManager.EXTRA_SLOT_INDEX,
+                                    SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
+                                new Thread(() -> {
+                                    log("Carrier config changed. Update ranges.");
+                                    mCellBroadcastRangeManager.updateRanges();
+                                }).start();
+                            }
+                        }
+                    }
+                }, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+    }
+
+    private void enforceNotOnHandlerThread(String methodName) {
+        if (Looper.myLooper() == mHandler.getLooper()) {
+            throw new RuntimeException("This method " + methodName + " will deadlock if called from"
+                    + " the handler's thread.");
+        }
     }
 
     protected void markMessagesAsRead(ArrayList<byte[]> messages) {
@@ -194,7 +228,7 @@
             //shouldn't really happen, as messages are marked as read, only
             //after importing it from icc.
             if (Rlog.isLoggable("SMS", Log.DEBUG)) {
-                log("markMessagesAsRead - aborting, no icc card present.");
+                loge("markMessagesAsRead - aborting, no icc card present.");
             }
             return;
         }
@@ -243,6 +277,7 @@
                 " status=" + status + " ==> " +
                 "("+ Arrays.toString(pdu) + ")");
         enforceReceiveAndSend("Updating message on Icc");
+        enforceNotOnHandlerThread("updateMessageOnIccEf");
         if (mAppOps.noteOp(AppOpsManager.OPSTR_WRITE_ICC_SMS, Binder.getCallingUid(),
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return false;
@@ -276,20 +311,24 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to update by index");
+                loge("interrupted while trying to update by index");
             }
         }
         return mSuccess;
     }
 
     /**
-     * Copy a raw SMS PDU to the Icc.
+     * Copies a raw SMS PDU to the ICC.
      *
-     * @param pdu the raw PDU to store
-     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
-     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
-     * @return success or not
-     *
+     * @param callingPackage the package name of the calling app.
+     * @param status message status. One of these status:
+     *               <code>STATUS_ON_ICC_READ</code>
+     *               <code>STATUS_ON_ICC_UNREAD</code>
+     *               <code>STATUS_ON_ICC_SENT</code>
+     *               <code>STATUS_ON_ICC_UNSENT</code>
+     * @param pdu the raw PDU to store.
+     * @param smsc the SMSC for this message. Null means use default.
+     * @return true for success. Otherwise false.
      */
     @UnsupportedAppUsage
     public boolean copyMessageToIccEf(String callingPackage, int status, byte[] pdu, byte[] smsc) {
@@ -298,6 +337,7 @@
                 "pdu=("+ Arrays.toString(pdu) +
                 "), smsc=(" + Arrays.toString(smsc) +")");
         enforceReceiveAndSend("Copying message to Icc");
+        enforceNotOnHandlerThread("copyMessageToIccEf");
         if (mAppOps.noteOp(AppOpsManager.OPSTR_WRITE_ICC_SMS, Binder.getCallingUid(),
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return false;
@@ -317,7 +357,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to update by index");
+                loge("interrupted while trying to update by index");
             }
         }
         return mSuccess;
@@ -336,6 +376,7 @@
         mContext.enforceCallingOrSelfPermission(
                 Manifest.permission.RECEIVE_SMS,
                 "Reading messages from Icc");
+        enforceNotOnHandlerThread("getAllMessagesFromIccEf");
         if (mAppOps.noteOp(AppOpsManager.OPSTR_READ_ICC_SMS, Binder.getCallingUid(),
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return new ArrayList<SmsRawData>();
@@ -344,7 +385,7 @@
 
             IccFileHandler fh = mPhone.getIccFileHandler();
             if (fh == null) {
-                Rlog.e(LOG_TAG, "Cannot load Sms records. No icc card?");
+                loge("Cannot load Sms records. No icc card?");
                 mSms = null;
                 return mSms;
             }
@@ -355,7 +396,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to load from the Icc");
+                loge("interrupted while trying to load from the Icc");
             }
         }
         return mSms;
@@ -610,7 +651,7 @@
                         try {
                             receivedIntent.send(result);
                         } catch (PendingIntent.CanceledException e) {
-                            Rlog.d(LOG_TAG, "receivedIntent cancelled.");
+                            loge("receivedIntent cancelled.");
                         }
                     }
                 }
@@ -832,6 +873,7 @@
                 callingPackage, "getSmscAddressFromIccEf")) {
             return null;
         }
+        enforceNotOnHandlerThread("getSmscAddressFromIccEf");
         synchronized (mLock) {
             mSmsc = null;
             Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE);
@@ -839,7 +881,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to read SMSC");
+                loge("interrupted while trying to read SMSC");
             }
         }
         return mSmsc;
@@ -863,7 +905,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to write SMSC");
+                loge("interrupted while trying to write SMSC");
             }
         }
         return mSuccess;
@@ -881,9 +923,9 @@
         mContext.enforceCallingPermission("android.permission.RECEIVE_EMERGENCY_BROADCAST",
                 "enabling cell broadcast range [" + startMessageId + "-" + endMessageId + "]. "
                         + "ranType=" + ranType);
-        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM) {
+        if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) {
             return enableGsmBroadcastRange(startMessageId, endMessageId);
-        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA) {
+        } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2) {
             return enableCdmaBroadcastRange(startMessageId, endMessageId);
         } else {
             throw new IllegalArgumentException("Not a supported RAN Type");
@@ -894,9 +936,9 @@
         mContext.enforceCallingPermission("android.permission.RECEIVE_EMERGENCY_BROADCAST",
                 "disabling cell broadcast range [" + startMessageId + "-" + endMessageId
                         + "]. ranType=" + ranType);
-        if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_GSM ) {
+        if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP) {
             return disableGsmBroadcastRange(startMessageId, endMessageId);
-        } else if (ranType == SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA)  {
+        } else if (ranType == SmsCbMessage.MESSAGE_FORMAT_3GPP2)  {
             return disableCdmaBroadcastRange(startMessageId, endMessageId);
         } else {
             throw new IllegalArgumentException("Not a supported RAN Type");
@@ -1107,9 +1149,10 @@
 
     @UnsupportedAppUsage
     private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) {
-        if (DBG)
+        if (DBG) {
             log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");
-
+        }
+        enforceNotOnHandlerThread("setCellBroadcastConfig");
         synchronized (mLock) {
             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
 
@@ -1119,7 +1162,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to set cell broadcast config");
+                loge("interrupted while trying to set cell broadcast config");
             }
         }
 
@@ -1127,9 +1170,11 @@
     }
 
     private boolean setCellBroadcastActivation(boolean activate) {
-        if (DBG)
+        if (DBG) {
             log("Calling setCellBroadcastActivation(" + activate + ')');
+        }
 
+        enforceNotOnHandlerThread("setCellBroadcastConfig");
         synchronized (mLock) {
             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);
 
@@ -1139,7 +1184,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to set cell broadcast activation");
+                loge("interrupted while trying to set cell broadcast activation");
             }
         }
 
@@ -1148,9 +1193,11 @@
 
     @UnsupportedAppUsage
     private boolean setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs) {
-        if (DBG)
+        if (DBG) {
             log("Calling setCdmaBroadcastConfig with " + configs.length + " configurations");
+        }
 
+        enforceNotOnHandlerThread("setCdmaBroadcastConfig");
         synchronized (mLock) {
             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
 
@@ -1160,7 +1207,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to set cdma broadcast config");
+                loge("interrupted while trying to set cdma broadcast config");
             }
         }
 
@@ -1168,9 +1215,11 @@
     }
 
     private boolean setCdmaBroadcastActivation(boolean activate) {
-        if (DBG)
+        if (DBG) {
             log("Calling setCdmaBroadcastActivation(" + activate + ")");
+        }
 
+        enforceNotOnHandlerThread("setCdmaBroadcastActivation");
         synchronized (mLock) {
             Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_ACTIVATION_DONE);
 
@@ -1180,7 +1229,7 @@
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to set cdma broadcast activation");
+                loge("interrupted while trying to set cdma broadcast activation");
             }
         }
 
@@ -1189,7 +1238,15 @@
 
     @UnsupportedAppUsage
     protected void log(String msg) {
-        Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
+        Rlog.d(LOG_TAG, msg);
+    }
+
+    protected void loge(String msg) {
+        Rlog.e(LOG_TAG, msg);
+    }
+
+    protected void loge(String msg, Throwable e) {
+        Rlog.e(LOG_TAG, msg, e);
     }
 
     @UnsupportedAppUsage
@@ -1215,13 +1272,13 @@
         }
         final ContentResolver resolver = mContext.getContentResolver();
         if (!isFailedOrDraft(resolver, messageUri)) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: not FAILED or DRAFT message");
+            loge("sendStoredText: not FAILED or DRAFT message");
             returnUnspecifiedFailure(sentIntent);
             return;
         }
         final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
         if (textAndAddress == null) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: can not load text");
+            loge("sendStoredText: can not load text");
             returnUnspecifiedFailure(sentIntent);
             return;
         }
@@ -1242,20 +1299,19 @@
         }
         final ContentResolver resolver = mContext.getContentResolver();
         if (!isFailedOrDraft(resolver, messageUri)) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: "
-                    + "not FAILED or DRAFT message");
+            loge("sendStoredMultipartText: not FAILED or DRAFT message");
             returnUnspecifiedFailure(sentIntents);
             return;
         }
         final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
         if (textAndAddress == null) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not load text");
+            loge("sendStoredMultipartText: can not load text");
             returnUnspecifiedFailure(sentIntents);
             return;
         }
         final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]);
         if (parts == null || parts.size() < 1) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not divide text");
+            loge("sendStoredMultipartText: can not divide text");
             returnUnspecifiedFailure(sentIntents);
             return;
         }
@@ -1308,6 +1364,28 @@
                 SMS_MESSAGE_PERIOD_NOT_SPECIFIED);
     }
 
+    public int getSmsCapacityOnIcc() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+                "getSmsCapacityOnIcc");
+
+        int numberOnIcc = 0;
+        if (mPhone.getIccRecordsLoaded()) {
+            final UiccProfile uiccProfile = UiccController.getInstance()
+                    .getUiccProfileForPhone(mPhone.getPhoneId());
+            if(uiccProfile != null) {
+                numberOnIcc = uiccProfile.getIccRecords().getSmsCapacityOnIcc();
+            } else {
+                loge("uiccProfile is null");
+            }
+        } else {
+            loge("getSmsCapacityOnIcc - aborting, no icc card present.");
+        }
+
+        log("getSmsCapacityOnIcc().numberOnIcc = " + numberOnIcc);
+        return numberOnIcc;
+    }
+
     private boolean isFailedOrDraft(ContentResolver resolver, Uri messageUri) {
         // Clear the calling identity and query the database using the phone user id
         // Otherwise the AppOps check in TelephonyProvider would complain about mismatch
@@ -1327,7 +1405,7 @@
                         || type == Telephony.Sms.MESSAGE_TYPE_FAILED;
             }
         } catch (SQLiteException e) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]isFailedOrDraft: query message type failed", e);
+            loge("isFailedOrDraft: query message type failed", e);
         } finally {
             if (cursor != null) {
                 cursor.close();
@@ -1358,7 +1436,7 @@
                 return new String[]{ cursor.getString(0), cursor.getString(1) };
             }
         } catch (SQLiteException e) {
-            Log.e(LOG_TAG, "[IccSmsInterfaceManager]loadText: query message text failed", e);
+            loge("loadText: query message text failed", e);
         } finally {
             if (cursor != null) {
                 cursor.close();
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 4be189d..a14db4e 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -23,7 +23,6 @@
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.RegistrationManager;
@@ -41,6 +40,7 @@
 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.util.SMSDispatcherUtil;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -235,14 +235,9 @@
     public ImsSmsDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
         super(phone, smsDispatchersController);
 
-        mImsManagerConnector = new FeatureConnector<ImsManager>(mContext, mPhone.getPhoneId(),
+        mImsManagerConnector = new FeatureConnector<>(mContext, mPhone.getPhoneId(),
                 new FeatureConnector.Listener<ImsManager>() {
                     @Override
-                    public boolean isSupported() {
-                        return ImsManager.isImsSupportedOnDevice(mContext);
-                    }
-
-                    @Override
                     public ImsManager getFeatureManager() {
                         return ImsManager.getInstance(mContext, phone.getPhoneId());
                     }
@@ -275,9 +270,9 @@
     }
 
     private boolean isLteService() {
-        return ((mPhone.getServiceState().getRilVoiceRadioTechnology() ==
+        return ((mPhone.getServiceState().getRilDataRadioTechnology() ==
             ServiceState.RIL_RADIO_TECHNOLOGY_LTE) && (mPhone.getServiceState().
-                getState() == ServiceState.STATE_IN_SERVICE));
+                getDataRegistrationState() == ServiceState.STATE_IN_SERVICE));
     }
 
     private boolean isLimitedLteService() {
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 3d66b60..1c6cd4fa 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -19,7 +19,6 @@
 import static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE;
 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
 
-import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -27,6 +26,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -35,12 +35,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.IDeviceIdleController;
 import android.os.Message;
@@ -51,7 +51,6 @@
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
 import android.service.carrier.CarrierMessagingService;
-import android.telephony.Rlog;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -64,9 +63,11 @@
 import com.android.internal.telephony.SmsConstants.MessageClass;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.util.NotificationChannelController;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.telephony.Rlog;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
@@ -224,9 +225,6 @@
     protected Phone mPhone;
 
     @UnsupportedAppUsage
-    protected CellBroadcastHandler mCellBroadcastHandler;
-
-    @UnsupportedAppUsage
     private UserManager mUserManager;
 
     protected TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
@@ -236,8 +234,6 @@
     @UnsupportedAppUsage
     IDeviceIdleController mDeviceIdleController;
 
-    protected static boolean sEnableCbModule = false;
-
     protected CellBroadcastServiceManager mCellBroadcastServiceManager;
 
     // Delete permanently from raw table
@@ -262,13 +258,12 @@
      * @param storageMonitor the SmsStorageMonitor to check for storage availability
      */
     protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
-            Phone phone, CellBroadcastHandler cellBroadcastHandler) {
+            Phone phone) {
         super(name);
 
         mContext = context;
         mStorageMonitor = storageMonitor;
         mPhone = phone;
-        mCellBroadcastHandler = cellBroadcastHandler;
         mResolver = context.getContentResolver();
         mWapPush = new WapPushOverSms(context);
 
@@ -332,7 +327,7 @@
                 default: {
                     String errorText = "processMessage: unhandled message type " + msg.what +
                         " currState=" + getCurrentState().getName();
-                    if (Build.IS_DEBUGGABLE) {
+                    if (TelephonyUtils.IS_DEBUGGABLE) {
                         loge("---- Dumping InboundSmsHandler ----");
                         loge("Total records=" + getLogRecCount());
                         for (int i = Math.max(getLogRecSize() - 20, 0); i < getLogRecSize(); i++) {
@@ -1124,7 +1119,7 @@
      * @param user user to deliver the intent to
      */
     @UnsupportedAppUsage
-    public void dispatchIntent(Intent intent, String permission, int appOp,
+    public void dispatchIntent(Intent intent, String permission, String appOp,
             Bundle opts, BroadcastReceiver resultReceiver, UserHandle user, int subId) {
         intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
         final String action = intent.getAction();
@@ -1165,7 +1160,7 @@
                 UserHandle targetUser = UserHandle.of(users[i]);
                 if (users[i] != UserHandle.USER_SYSTEM) {
                     // Is the user not allowed to use SMS?
-                    if (mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
+                    if (hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
                         continue;
                     }
                     // Skip unknown users and managed profiles as well
@@ -1174,16 +1169,32 @@
                     }
                 }
                 // Only pass in the resultReceiver when the USER_SYSTEM is processed.
-                mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp, opts,
-                        users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
-                        getHandler(), Activity.RESULT_OK, null, null);
+                try {
+                    mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
+                            .sendOrderedBroadcast(intent, permission, appOp, opts,
+                                    users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
+                                    getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                    null /* initialExtras */);
+                } catch (PackageManager.NameNotFoundException ignored) {
+                }
             }
         } else {
-            mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,
-                    resultReceiver, getHandler(), Activity.RESULT_OK, null, null);
+            try {
+                mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user)
+                        .sendOrderedBroadcast(intent, permission, appOp, opts, resultReceiver,
+                                getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                null /* initialExtras */);
+            } catch (PackageManager.NameNotFoundException ignored) {
+            }
         }
     }
 
+    private boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
+        final List<UserManager.EnforcingUser> sources = mUserManager
+                .getUserRestrictionSources(restrictionKey, userHandle);
+        return (sources != null && !sources.isEmpty());
+    }
+
     /**
      * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table.
      */
@@ -1278,7 +1289,7 @@
 
         Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
         dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
-                AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
+                AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
     }
 
     /**
@@ -1465,7 +1476,7 @@
                 Bundle options = handleSmsWhitelisting(null, false /* bgActivityStartAllowed */);
 
                 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
-                        AppOpsManager.OP_RECEIVE_SMS,
+                        AppOpsManager.OPSTR_RECEIVE_SMS,
                         options, this, UserHandle.ALL, subId);
             } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
                 // Now dispatch the notification only intent
@@ -1488,7 +1499,7 @@
 
                 String mimeType = intent.getType();
                 dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
-                        WapPushOverSms.getAppOpsPermissionForIntent(mimeType), options, this,
+                        WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
                         UserHandle.SYSTEM, subId);
             } else {
                 // Now that the intents have been deleted we can clean up the PDU data.
@@ -1701,9 +1712,6 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         super.dump(fd, pw, args);
-        if (mCellBroadcastHandler != null) {
-            mCellBroadcastHandler.dump(fd, pw, args);
-        }
         if (mCellBroadcastServiceManager != null) {
             mCellBroadcastServiceManager.dump(fd, pw, args);
         }
@@ -1790,15 +1798,11 @@
     protected abstract class CbTestBroadcastReceiver extends BroadcastReceiver {
 
         protected abstract void handleTestAction(Intent intent);
-        protected abstract void handleToggleEnable();
-        protected abstract void handleToggleDisable(Context context);
 
         protected final String mTestAction;
-        protected final String mToggleAction;
 
-        public CbTestBroadcastReceiver(String testAction, String toggleAction) {
+        public CbTestBroadcastReceiver(String testAction) {
             mTestAction = testAction;
-            mToggleAction = toggleAction;
         }
 
         @Override
@@ -1812,19 +1816,6 @@
                     return;
                 }
                 handleTestAction(intent);
-            } else if (intent.getAction().equals(mToggleAction)) {
-                if (intent.hasExtra("enable")) {
-                    sEnableCbModule = intent.getBooleanExtra("enable", false);
-                } else {
-                    sEnableCbModule = !sEnableCbModule;
-                }
-                if (sEnableCbModule) {
-                    log("enabling CB module");
-                    handleToggleEnable();
-                } else {
-                    log("enabling legacy platform CB handling");
-                    handleToggleDisable(context);
-                }
             }
         }
     }
diff --git a/src/java/com/android/internal/telephony/InboundSmsTracker.java b/src/java/com/android/internal/telephony/InboundSmsTracker.java
index 4d9971e..30f63b2 100644
--- a/src/java/com/android/internal/telephony/InboundSmsTracker.java
+++ b/src/java/com/android/internal/telephony/InboundSmsTracker.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.util.Pair;
diff --git a/src/java/com/android/internal/telephony/IntRangeManager.java b/src/java/com/android/internal/telephony/IntRangeManager.java
index b82a20e..02880e0 100644
--- a/src/java/com/android/internal/telephony/IntRangeManager.java
+++ b/src/java/com/android/internal/telephony/IntRangeManager.java
@@ -16,7 +16,8 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 
diff --git a/src/java/com/android/internal/telephony/IntentBroadcaster.java b/src/java/com/android/internal/telephony/IntentBroadcaster.java
index e211c24..e1dca63 100644
--- a/src/java/com/android/internal/telephony/IntentBroadcaster.java
+++ b/src/java/com/android/internal/telephony/IntentBroadcaster.java
@@ -51,7 +51,7 @@
                     while (iterator.hasNext()) {
                         Map.Entry pair = (Map.Entry) iterator.next();
                         Intent i = (Intent) pair.getValue();
-                        i.putExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, true);
+                        i.putExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, true);
                         iterator.remove();
                         logd("Rebroadcasting intent " + i.getAction() + " "
                                 + i.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
diff --git a/src/java/com/android/internal/telephony/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index 1c9a7e0..704e09e 100755
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -26,15 +26,14 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.AsyncResult;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.sysprop.TelephonyProperties;
 import android.telephony.CellInfo;
 import android.telephony.CellInfoGsm;
 import android.telephony.CellInfoLte;
 import android.telephony.CellInfoWcdma;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -42,10 +41,14 @@
 import android.util.LocalLog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.MccTable.MccMnc;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -57,7 +60,6 @@
  */
 public class LocaleTracker extends Handler {
     private static final boolean DBG = true;
-    private static final String TAG = LocaleTracker.class.getSimpleName();
 
     /** Event for getting cell info from the modem */
     private static final int EVENT_REQUEST_CELL_INFO = 1;
@@ -124,6 +126,8 @@
     /** The maximum fail count to prevent delay time overflow */
     private static final int MAX_FAIL_COUNT = 30;
 
+    private String mTag;
+
     private final Phone mPhone;
 
     private final NitzStateMachine mNitzStateMachine;
@@ -240,10 +244,11 @@
         mPhone = phone;
         mNitzStateMachine = nitzStateMachine;
         mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
+        mTag = LocaleTracker.class.getSimpleName() + "-" + mPhone.getPhoneId();
 
         final IntentFilter filter = new IntentFilter();
         filter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
-        if (Build.IS_DEBUGGABLE) {
+        if (TelephonyUtils.IS_DEBUGGABLE) {
             filter.addAction(ACTION_COUNTRY_OVERRIDE);
         }
         mPhone.getContext().registerReceiver(mBroadcastReceiver, filter);
@@ -282,23 +287,16 @@
     private String getMccFromCellInfo() {
         String selectedMcc = null;
         if (mCellInfoList != null) {
-            Map<String, Integer> countryCodeMap = new HashMap<>();
+            Map<String, Integer> mccMap = new HashMap<>();
             int maxCount = 0;
             for (CellInfo cellInfo : mCellInfoList) {
-                String mcc = null;
-                if (cellInfo instanceof CellInfoGsm) {
-                    mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMccString();
-                } else if (cellInfo instanceof CellInfoLte) {
-                    mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMccString();
-                } else if (cellInfo instanceof CellInfoWcdma) {
-                    mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMccString();
-                }
+                String mcc = getNetworkMcc(cellInfo);
                 if (mcc != null) {
                     int count = 1;
-                    if (countryCodeMap.containsKey(mcc)) {
-                        count = countryCodeMap.get(mcc) + 1;
+                    if (mccMap.containsKey(mcc)) {
+                        count = mccMap.get(mcc) + 1;
                     }
-                    countryCodeMap.put(mcc, count);
+                    mccMap.put(mcc, count);
                     // This is unlikely, but if MCC from cell info looks different, we choose the
                     // MCC that occurs most.
                     if (count > maxCount) {
@@ -312,6 +310,70 @@
     }
 
     /**
+     * Get the most frequent MCC + MNC combination with the specified MCC using cell tower
+     * information. If no one combination is more frequent than any other an arbitrary MCC + MNC is
+     * returned with the matching MCC. The MNC value returned can be null if it is not provided by
+     * the cell tower information.
+     *
+     * @param mccToMatch the MCC to match
+     * @return a matching {@link MccMnc}. Null if the information is not available.
+     */
+    @Nullable
+    private MccMnc getMccMncFromCellInfo(@NonNull String mccToMatch) {
+        MccMnc selectedMccMnc = null;
+        if (mCellInfoList != null) {
+            Map<MccMnc, Integer> mccMncMap = new HashMap<>();
+            int maxCount = 0;
+            for (CellInfo cellInfo : mCellInfoList) {
+                String mcc = getNetworkMcc(cellInfo);
+                if (Objects.equals(mcc, mccToMatch)) {
+                    String mnc = getNetworkMnc(cellInfo);
+                    MccMnc mccMnc = new MccMnc(mcc, mnc);
+                    int count = 1;
+                    if (mccMncMap.containsKey(mccMnc)) {
+                        count = mccMncMap.get(mccMnc) + 1;
+                    }
+                    mccMncMap.put(mccMnc, count);
+                    // We keep track of the MCC+MNC combination that occurs most frequently, if
+                    // there is one. A null MNC is treated like any other distinct MCC+MNC
+                    // combination.
+                    if (count > maxCount) {
+                        maxCount = count;
+                        selectedMccMnc = mccMnc;
+                    }
+                }
+            }
+        }
+        return selectedMccMnc;
+    }
+
+    @Nullable
+    private static String getNetworkMcc(CellInfo cellInfo) {
+        String mccString = null;
+        if (cellInfo instanceof CellInfoGsm) {
+            mccString = ((CellInfoGsm) cellInfo).getCellIdentity().getMccString();
+        } else if (cellInfo instanceof CellInfoLte) {
+            mccString = ((CellInfoLte) cellInfo).getCellIdentity().getMccString();
+        } else if (cellInfo instanceof CellInfoWcdma) {
+            mccString = ((CellInfoWcdma) cellInfo).getCellIdentity().getMccString();
+        }
+        return mccString;
+    }
+
+    @Nullable
+    private static String getNetworkMnc(CellInfo cellInfo) {
+        String mccString = null;
+        if (cellInfo instanceof CellInfoGsm) {
+            mccString = ((CellInfoGsm) cellInfo).getCellIdentity().getMncString();
+        } else if (cellInfo instanceof CellInfoLte) {
+            mccString = ((CellInfoLte) cellInfo).getCellIdentity().getMncString();
+        } else if (cellInfo instanceof CellInfoWcdma) {
+            mccString = ((CellInfoWcdma) cellInfo).getCellIdentity().getMncString();
+        }
+        return mccString;
+    }
+
+    /**
      * Called when SIM card state changed. Only when we absolutely know the SIM is absent, we get
      * cell info from the network. Other SIM states like NOT_READY might be just a transitioning
      * state.
@@ -457,15 +519,23 @@
         String countryIso = getCarrierCountry();
         String countryIsoDebugInfo = "getCarrierCountry()";
 
+        // For time zone detection we want the best geographical match we can get, which may differ
+        // from the countryIso.
+        String timeZoneCountryIso = null;
+        String timeZoneCountryIsoDebugInfo = null;
+
         if (!TextUtils.isEmpty(mOperatorNumeric)) {
-            try {
-                String mcc = mOperatorNumeric.substring(0, 3);
-                countryIso = MccTable.countryCodeForMcc(mcc);
+            MccMnc mccMnc = MccMnc.fromOperatorNumeric(mOperatorNumeric);
+            if (mccMnc != null) {
+                countryIso = MccTable.countryCodeForMcc(mccMnc.mcc);
                 countryIsoDebugInfo = "OperatorNumeric(" + mOperatorNumeric
-                        + "): MccTable.countryCodeForMcc(\"" + mcc + "\")";
-            } catch (StringIndexOutOfBoundsException ex) {
+                        + "): MccTable.countryCodeForMcc(\"" + mccMnc.mcc + "\")";
+                timeZoneCountryIso = MccTable.geoCountryCodeForMccMnc(mccMnc);
+                timeZoneCountryIsoDebugInfo =
+                        "OperatorNumeric: MccTable.geoCountryCodeForMccMnc(" + mccMnc + ")";
+            } else {
                 loge("updateLocale: Can't get country from operator numeric. mOperatorNumeric = "
-                        + mOperatorNumeric + ". ex=" + ex);
+                        + mOperatorNumeric);
             }
         }
 
@@ -473,28 +543,44 @@
         // info.
         if (TextUtils.isEmpty(countryIso)) {
             String mcc = getMccFromCellInfo();
-            countryIso = MccTable.countryCodeForMcc(mcc);
-            countryIsoDebugInfo = "CellInfo: MccTable.countryCodeForMcc(\"" + mcc + "\")";
+            if (mcc != null) {
+                countryIso = MccTable.countryCodeForMcc(mcc);
+                countryIsoDebugInfo = "CellInfo: MccTable.countryCodeForMcc(\"" + mcc + "\")";
+
+                MccMnc mccMnc = getMccMncFromCellInfo(mcc);
+                if (mccMnc != null) {
+                    timeZoneCountryIso = MccTable.geoCountryCodeForMccMnc(mccMnc);
+                    timeZoneCountryIsoDebugInfo =
+                            "CellInfo: MccTable.geoCountryCodeForMccMnc(" + mccMnc + ")";
+                }
+            }
         }
 
         if (mCountryOverride != null) {
             countryIso = mCountryOverride;
             countryIsoDebugInfo = "mCountryOverride = \"" + mCountryOverride + "\"";
-            log("Override current country to " + mCountryOverride);
+            timeZoneCountryIso = countryIso;
+            timeZoneCountryIsoDebugInfo = countryIsoDebugInfo;
         }
 
         log("updateLocale: countryIso = " + countryIso
                 + ", countryIsoDebugInfo = " + countryIsoDebugInfo);
         if (!Objects.equals(countryIso, mCurrentCountryIso)) {
-            String msg = "updateLocale: Change the current country to \"" + countryIso
-                    + "\", countryIsoDebugInfo = " + countryIsoDebugInfo
+            String msg = "updateLocale: Change the current country to \"" + countryIso + "\""
+                    + ", countryIsoDebugInfo = " + countryIsoDebugInfo
                     + ", mCellInfoList = " + mCellInfoList;
             log(msg);
             mLocalLog.log(msg);
             mCurrentCountryIso = countryIso;
 
-            TelephonyManager.setTelephonyProperty(mPhone.getPhoneId(),
-                    TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, mCurrentCountryIso);
+            int phoneId = mPhone.getPhoneId();
+            if (SubscriptionManager.isValidPhoneId(phoneId)) {
+                List<String> newProp = new ArrayList<>(
+                        TelephonyProperties.operator_iso_country());
+                while (newProp.size() <= phoneId) newProp.add(null);
+                newProp.set(phoneId, mCurrentCountryIso);
+                TelephonyProperties.operator_iso_country(newProp);
+            }
 
             Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
             intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryIso);
@@ -502,19 +588,30 @@
             mPhone.getContext().sendBroadcast(intent);
         }
 
-        // For a test cell, the NitzStateMachine requires handleCountryDetected("") to pass
-        // compliance tests. http://b/142840879
+        // Pass the geographical country information to the telephony time zone detection code.
+
         boolean isTestMcc = false;
         if (!TextUtils.isEmpty(mOperatorNumeric)) {
+            // For a test cell (MCC 001), the NitzStateMachine requires handleCountryDetected("") in
+            // order to pass compliance tests. http://b/142840879
             if (mOperatorNumeric.startsWith("001")) {
                 isTestMcc = true;
-                countryIso = "";
+                timeZoneCountryIso = "";
+                timeZoneCountryIsoDebugInfo = "Test cell: " + mOperatorNumeric;
             }
         }
-        if (TextUtils.isEmpty(countryIso) && !isTestMcc) {
+        if (timeZoneCountryIso == null) {
+            // After this timeZoneCountryIso may still be null.
+            timeZoneCountryIso = countryIso;
+            timeZoneCountryIsoDebugInfo = "Defaulted: " + countryIsoDebugInfo;
+        }
+        log("updateLocale: timeZoneCountryIso = " + timeZoneCountryIso
+                + ", timeZoneCountryIsoDebugInfo = " + timeZoneCountryIsoDebugInfo);
+
+        if (TextUtils.isEmpty(timeZoneCountryIso) && !isTestMcc) {
             mNitzStateMachine.handleCountryUnavailable();
         } else {
-            mNitzStateMachine.handleCountryDetected(countryIso);
+            mNitzStateMachine.handleCountryDetected(timeZoneCountryIso);
         }
     }
 
@@ -524,11 +621,11 @@
     }
 
     private void log(String msg) {
-        Rlog.d(TAG, msg);
+        Rlog.d(mTag, msg);
     }
 
     private void loge(String msg) {
-        Rlog.e(TAG, msg);
+        Rlog.e(mTag, msg);
     }
 
     /**
@@ -540,7 +637,7 @@
      */
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        pw.println("LocaleTracker:");
+        pw.println("LocaleTracker-" + mPhone.getPhoneId() + ":");
         ipw.increaseIndent();
         ipw.println("mIsTracking = " + mIsTracking);
         ipw.println("mOperatorNumeric = " + mOperatorNumeric);
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index 31b8d0a..1492402 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -16,27 +16,31 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.icu.util.ULocale;
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.text.TextUtils;
-import android.util.Slog;
+import android.timezone.TelephonyLookup;
+import android.timezone.TelephonyNetwork;
+import android.timezone.TelephonyNetworkFinder;
 
-import com.android.internal.app.LocaleStore;
-import com.android.internal.app.LocaleStore.LocaleInfo;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Mobile Country Code
@@ -46,23 +50,30 @@
 public final class MccTable {
     static final String LOG_TAG = "MccTable";
 
+    @GuardedBy("MccTable.class")
+    private static TelephonyNetworkFinder sTelephonyNetworkFinder;
+
     static ArrayList<MccEntry> sTable;
 
-    static class MccEntry implements Comparable<MccEntry> {
+    /**
+     * Container class for mcc and iso. This class implements compareTo so that it can be sorted
+     * by mcc.
+     */
+    public static class MccEntry implements Comparable<MccEntry> {
         final int mMcc;
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                 publicAlternatives = "There is no alternative for {@code MccTable.MccEntry.mIso}, "
                         + "but it was included in hidden APIs due to a static analysis false "
                         + "positive and has been made greylist-max-q. Please file a bug if you "
                         + "still require this API.")
-        final String mIso;
+        public final String mIso;
         final int mSmallestDigitsMnc;
 
-        MccEntry(int mnc, String iso, int smallestDigitsMCC) {
+        MccEntry(int mcc, String iso, int smallestDigitsMCC) {
             if (iso == null) {
                 throw new NullPointerException();
             }
-            mMcc = mnc;
+            mMcc = mcc;
             mIso = iso;
             mSmallestDigitsMnc = smallestDigitsMCC;
         }
@@ -73,12 +84,83 @@
         }
     }
 
+    /**
+     * A combination of MCC and MNC. The MNC is optional and may be null.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static class MccMnc {
+        @NonNull
+        public final String mcc;
+
+        @Nullable
+        public final String mnc;
+
+        /**
+         * Splits the supplied String in two: the first three characters are treated as the MCC,
+         * the remaining characters are treated as the MNC.
+         */
+        @Nullable
+        public static MccMnc fromOperatorNumeric(@NonNull String operatorNumeric) {
+            Objects.requireNonNull(operatorNumeric);
+            String mcc;
+            try {
+                mcc = operatorNumeric.substring(0, 3);
+            } catch (StringIndexOutOfBoundsException e) {
+                return null;
+            }
+
+            String mnc;
+            try {
+                mnc = operatorNumeric.substring(3);
+            } catch (StringIndexOutOfBoundsException e) {
+                mnc = null;
+            }
+            return new MccMnc(mcc, mnc);
+        }
+
+        /**
+         * Creates an MccMnc using the supplied values.
+         */
+        public MccMnc(@NonNull String mcc, @Nullable String mnc) {
+            this.mcc = Objects.requireNonNull(mcc);
+            this.mnc = mnc;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            MccMnc mccMnc = (MccMnc) o;
+            return mcc.equals(mccMnc.mcc)
+                    && Objects.equals(mnc, mccMnc.mnc);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mcc, mnc);
+        }
+
+        @Override
+        public String toString() {
+            return "MccMnc{"
+                    + "mcc='" + mcc + '\''
+                    + ", mnc='" + mnc + '\''
+                    + '}';
+        }
+    }
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "There is no alternative for {@code MccTable.entryForMcc}, "
                     + "but it was included in hidden APIs due to a static analysis false positive "
                     + "and has been made greylist-max-q. Please file a bug if you still require "
                     + "this API.")
-    private static MccEntry entryForMcc(int mcc) {
+    public static MccEntry entryForMcc(int mcc) {
         MccEntry m = new MccEntry(mcc, "", 0);
 
         int index = Collections.binarySearch(sTable, m);
@@ -91,11 +173,11 @@
     }
 
     /**
-     * Given a GSM Mobile Country Code, returns
-     * an ISO two-character country code if available.
-     * Returns "" if unavailable.
+     * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
+     * available. Returns empty string if unavailable.
      */
     @UnsupportedAppUsage
+    @NonNull
     public static String countryCodeForMcc(int mcc) {
         MccEntry entry = entryForMcc(mcc);
 
@@ -107,11 +189,11 @@
     }
 
     /**
-     * Given a GSM Mobile Country Code, returns
-     * an ISO two-character country code if available.
-     * Returns empty string if unavailable.
+     * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
+     * available. Returns empty string if unavailable.
      */
-    public static String countryCodeForMcc(String mcc) {
+    @NonNull
+    public static String countryCodeForMcc(@NonNull String mcc) {
         try {
             return countryCodeForMcc(Integer.parseInt(mcc));
         } catch (NumberFormatException ex) {
@@ -120,37 +202,51 @@
     }
 
     /**
-     * Given a GSM Mobile Country Code, returns
-     * an ISO 2-3 character language code if available.
-     * Returns null if unavailable.
+     * Given a combination of MCC and MNC, returns a lower case ISO 3166 alpha-2 country code for
+     * the device's geographical location.
+     *
+     * <p>This can give a better geographical result than {@link #countryCodeForMcc(String)}
+     * (which provides the official "which country is the MCC assigned to?" answer) for cases when
+     * MNC is also available: Sometimes an MCC can be used by multiple countries and the MNC can
+     * help distinguish, or the MCC assigned to a country isn't used for geopolitical reasons.
+     * When the geographical country is needed  (e.g. time zone detection) this version can provide
+     * more pragmatic results than the official MCC-only answer. This method falls back to calling
+     * {@link #countryCodeForMcc(int)} if no special MCC+MNC cases are found.
+     * Returns empty string if no code can be determined.
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
-            publicAlternatives = "There is no alternative for {@code MccTable.defaultLanguageForMcc"
-                    + "}, but it was included in hidden APIs due to a static analysis false "
-                    + "positive and has been made greylist-max-q. Please file a bug if you still "
-                    + "require this API.")
-    public static String defaultLanguageForMcc(int mcc) {
-        MccEntry entry = entryForMcc(mcc);
-        if (entry == null) {
-            Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): no country for mcc");
+    @NonNull
+    public static String geoCountryCodeForMccMnc(@NonNull MccMnc mccMnc) {
+        String countryCode = null;
+        if (mccMnc.mnc != null) {
+            countryCode = countryCodeForMccMncNoFallback(mccMnc);
+        }
+        if (TextUtils.isEmpty(countryCode)) {
+            // Try the MCC-only fallback.
+            countryCode = MccTable.countryCodeForMcc(mccMnc.mcc);
+        }
+        return countryCode;
+    }
+
+    @Nullable
+    private static String countryCodeForMccMncNoFallback(MccMnc mccMnc) {
+        synchronized (MccTable.class) {
+            if (sTelephonyNetworkFinder == null) {
+                sTelephonyNetworkFinder = TelephonyLookup.getInstance().getTelephonyNetworkFinder();
+            }
+        }
+        if (sTelephonyNetworkFinder == null) {
+            // This should not happen under normal circumstances, only when the data is missing.
             return null;
         }
-
-        final String country = entry.mIso;
-
-        // Choose English as the default language for India.
-        if ("in".equals(country)) {
-            return "en";
+        TelephonyNetwork network =
+                sTelephonyNetworkFinder.findNetworkByMccMnc(mccMnc.mcc, mccMnc.mnc);
+        if (network == null) {
+            return null;
         }
-
-        // Ask CLDR for the language this country uses...
-        ULocale likelyLocale = ULocale.addLikelySubtags(new ULocale("und", country));
-        String likelyLanguage = likelyLocale.getLanguage();
-        Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): country " + country + " uses " +
-               likelyLanguage);
-        return likelyLanguage;
+        return network.getCountryIsoCode();
     }
 
+
     /**
      * Given a GSM Mobile Country Code, returns
      * the smallest number of digits that M if available.
@@ -178,13 +274,13 @@
      * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
      */
     public static void updateMccMncConfiguration(Context context, String mccmnc) {
-        Slog.d(LOG_TAG, "updateMccMncConfiguration mccmnc='" + mccmnc);
+        Rlog.d(LOG_TAG, "updateMccMncConfiguration mccmnc='" + mccmnc);
 
-        if (Build.IS_DEBUGGABLE) {
+        if (TelephonyUtils.IS_DEBUGGABLE) {
             String overrideMcc = SystemProperties.get("persist.sys.override_mcc");
             if (!TextUtils.isEmpty(overrideMcc)) {
                 mccmnc = overrideMcc;
-                Slog.d(LOG_TAG, "updateMccMncConfiguration overriding mccmnc='" + mccmnc + "'");
+                Rlog.d(LOG_TAG, "updateMccMncConfiguration overriding mccmnc='" + mccmnc + "'");
             }
         }
 
@@ -195,11 +291,11 @@
                 mcc = Integer.parseInt(mccmnc.substring(0, 3));
                 mnc = Integer.parseInt(mccmnc.substring(3));
             } catch (NumberFormatException | StringIndexOutOfBoundsException ex) {
-                Slog.e(LOG_TAG, "Error parsing IMSI: " + mccmnc + ". ex=" + ex);
+                Rlog.e(LOG_TAG, "Error parsing IMSI: " + mccmnc + ". ex=" + ex);
                 return;
             }
 
-            Slog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
+            Rlog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
 
             try {
                 Configuration config = new Configuration();
@@ -211,13 +307,13 @@
                 }
 
                 if (updateConfig) {
-                    Slog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config);
+                    Rlog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config);
                     ActivityManager.getService().updateConfiguration(config);
                 } else {
-                    Slog.d(LOG_TAG, "updateMccMncConfiguration nothing to update");
+                    Rlog.d(LOG_TAG, "updateMccMncConfiguration nothing to update");
                 }
             } catch (RemoteException e) {
-                Slog.e(LOG_TAG, "Can't update configuration", e);
+                Rlog.e(LOG_TAG, "Can't update configuration", e);
             }
         }
     }
@@ -225,161 +321,13 @@
     /**
      * Maps a given locale to a fallback locale that approximates it. This is a hack.
      */
-    private static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>();
+    public static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>();
 
     static {
         // If we have English (without a country) explicitly prioritize en_US. http://b/28998094
         FALLBACKS.put(Locale.ENGLISH, Locale.US);
     }
 
-    /**
-     * Finds a suitable locale among {@code candidates} to use as the fallback locale for
-     * {@code target}. This looks through the list of {@link #FALLBACKS}, and follows the chain
-     * until a locale in {@code candidates} is found.
-     * This function assumes that {@code target} is not in {@code candidates}.
-     *
-     * TODO: This should really follow the CLDR chain of parent locales! That might be a bit
-     * of a problem because we don't really have an en-001 locale on android.
-     *
-     * @return The fallback locale or {@code null} if there is no suitable fallback defined in the
-     *         lookup.
-     */
-    private static Locale lookupFallback(Locale target, List<Locale> candidates) {
-        Locale fallback = target;
-        while ((fallback = FALLBACKS.get(fallback)) != null) {
-            if (candidates.contains(fallback)) {
-                return fallback;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Return Locale for the language and country or null if no good match.
-     *
-     * @param context Context to act on.
-     * @param language Two character language code desired
-     * @param country Two character country code desired
-     *
-     * @return Locale or null if no appropriate value
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
-            publicAlternatives = "There is no alternative for {@code MccTable"
-                    + ".getLocaleForLanguageCountry}, but it was included in hidden APIs due to a "
-                    + "static analysis false positive and has been made greylist-max-q. Please "
-                    + "file a bug if you still require this API.")
-    private static Locale getLocaleForLanguageCountry(Context context, String language,
-            String country) {
-        if (language == null) {
-            Slog.d(LOG_TAG, "getLocaleForLanguageCountry: skipping no language");
-            return null; // no match possible
-        }
-        if (country == null) {
-            country = ""; // The Locale constructor throws if passed null.
-        }
-
-        final Locale target = new Locale(language, country);
-        try {
-            String[] localeArray = context.getAssets().getLocales();
-            List<String> locales = new ArrayList<>(Arrays.asList(localeArray));
-
-            // Even in developer mode, you don't want the pseudolocales.
-            locales.remove("ar-XB");
-            locales.remove("en-XA");
-
-            List<Locale> languageMatches = new ArrayList<>();
-            for (String locale : locales) {
-                final Locale l = Locale.forLanguageTag(locale.replace('_', '-'));
-
-                // Only consider locales with both language and country.
-                if (l == null || "und".equals(l.getLanguage()) ||
-                        l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
-                    continue;
-                }
-                if (l.getLanguage().equals(target.getLanguage())) {
-                    // If we got a perfect match, we're done.
-                    if (l.getCountry().equals(target.getCountry())) {
-                        Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got perfect match: " +
-                               l.toLanguageTag());
-                        return l;
-                    }
-
-                    // We've only matched the language, not the country.
-                    languageMatches.add(l);
-                }
-            }
-
-            if (languageMatches.isEmpty()) {
-                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: no locales for language " + language);
-                return null;
-            }
-
-            Locale bestMatch = lookupFallback(target, languageMatches);
-            if (bestMatch != null) {
-                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got a fallback match: "
-                        + bestMatch.toLanguageTag());
-                return bestMatch;
-            } else {
-                // Ask {@link LocaleStore} whether this locale is considered "translated".
-                // LocaleStore has a broader definition of translated than just the asset locales
-                // above: a locale is "translated" if it has translation assets, or another locale
-                // with the same language and script has translation assets.
-                // If a locale is "translated", it is selectable in setup wizard, and can therefore
-                // be considerd a valid result for this method.
-                if (!TextUtils.isEmpty(target.getCountry())) {
-                    LocaleStore.fillCache(context);
-                    LocaleInfo targetInfo = LocaleStore.getLocaleInfo(target);
-                    if (targetInfo.isTranslated()) {
-                        Slog.d(LOG_TAG, "getLocaleForLanguageCountry: "
-                                + "target locale is translated: " + target);
-                        return target;
-                    }
-                }
-
-                // Somewhat arbitrarily take the first locale for the language,
-                // unless we get a perfect match later. Note that these come back in no
-                // particular order, so there's no reason to think the first match is
-                // a particularly good match.
-                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got language-only match: "
-                        + language);
-                return languageMatches.get(0);
-            }
-        } catch (Exception e) {
-            Slog.d(LOG_TAG, "getLocaleForLanguageCountry: exception", e);
-        }
-
-        return null;
-    }
-
-    /**
-     * Get Locale based on the MCC of the SIM.
-     *
-     * @param context Context to act on.
-     * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
-     * @param simLanguage (nullable) the language from the SIM records (if present).
-     *
-     * @return locale for the mcc or null if none
-     */
-    public static Locale getLocaleFromMcc(Context context, int mcc, String simLanguage) {
-        boolean hasSimLanguage = !TextUtils.isEmpty(simLanguage);
-        String language = hasSimLanguage ? simLanguage : MccTable.defaultLanguageForMcc(mcc);
-        String country = MccTable.countryCodeForMcc(mcc);
-
-        Slog.d(LOG_TAG, "getLocaleFromMcc(" + language + ", " + country + ", " + mcc);
-        final Locale locale = getLocaleForLanguageCountry(context, language, country);
-
-        // If we couldn't find a locale that matches the SIM language, give it a go again
-        // with the "likely" language for the given country.
-        if (locale == null && hasSimLanguage) {
-            language = MccTable.defaultLanguageForMcc(mcc);
-            Slog.d(LOG_TAG, "[retry ] getLocaleFromMcc(" + language + ", " + country + ", " + mcc);
-            return getLocaleForLanguageCountry(context, language, country);
-        }
-
-        return locale;
-    }
-
     static {
         sTable = new ArrayList<MccEntry>(240);
 
diff --git a/src/java/com/android/internal/telephony/MmiCode.java b/src/java/com/android/internal/telephony/MmiCode.java
index eb09621..d4b1a0a 100644
--- a/src/java/com/android/internal/telephony/MmiCode.java
+++ b/src/java/com/android/internal/telephony/MmiCode.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.ResultReceiver;
 
 import java.util.regex.Pattern;
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index 1ce360f..7ad0de4 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -51,7 +51,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.ArrayUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -407,7 +407,7 @@
         if (DBG) log("onSubscriptionGroupChanged");
 
         List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup(
-                groupUuid, mContext.getOpPackageName());
+                groupUuid, mContext.getOpPackageName(), null);
         if (infoList == null || infoList.isEmpty()) return;
 
         // Get a reference subscription to copy settings from.
@@ -470,7 +470,8 @@
         if (!isReadyToReevaluate()) return;
 
         List<SubscriptionInfo> activeSubInfos = mSubController
-                .getActiveSubscriptionInfoList(mContext.getOpPackageName());
+                .getActiveSubscriptionInfoList(mContext.getOpPackageName(),
+                        null);
 
         if (ArrayUtils.isEmpty(activeSubInfos)) {
             mPrimarySubList.clear();
@@ -644,7 +645,8 @@
             if (phone != null && phone.isCdmaSubscriptionAppPresent()) {
                 cdmaPhoneCount++;
                 String simName = mSubController.getActiveSubscriptionInfo(
-                        subId, mContext.getOpPackageName()).getDisplayName().toString();
+                        subId, mContext.getOpPackageName(), null)
+                        .getDisplayName().toString();
                 if (TextUtils.isEmpty(simName)) {
                     // Fall back to carrier name.
                     simName = phone.getCarrierName();
@@ -700,7 +702,8 @@
     private void setUserDataEnabledForGroup(int subId, boolean enable) {
         log("setUserDataEnabledForGroup subId " + subId + " enable " + enable);
         List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup(
-                mSubController.getGroupUuid(subId), mContext.getOpPackageName());
+                mSubController.getGroupUuid(subId), mContext.getOpPackageName(),
+                null);
 
         if (infoList == null) return;
 
@@ -730,7 +733,8 @@
     private void setRoamingDataEnabledForGroup(int subId, boolean enable) {
         SubscriptionController subController = SubscriptionController.getInstance();
         List<SubscriptionInfo> infoList = subController.getSubscriptionsInGroup(
-                mSubController.getGroupUuid(subId), mContext.getOpPackageName());
+                mSubController.getGroupUuid(subId), mContext.getOpPackageName(),
+                null);
 
         if (infoList == null) return;
 
@@ -778,7 +782,7 @@
         if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;
 
         List<SubscriptionInfo> opptSubList = mSubController.getOpportunisticSubscriptions(
-                mContext.getOpPackageName());
+                mContext.getOpPackageName(), null);
 
         if (ArrayUtils.isEmpty(opptSubList)) return;
 
diff --git a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
index 1b28be4..716e7a2 100644
--- a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
+++ b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.IBinder;
@@ -37,10 +38,11 @@
 import android.telephony.INetworkServiceCallback;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.NetworkService;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 
+import com.android.telephony.Rlog;
+
 import java.util.Hashtable;
 import java.util.Map;
 
@@ -99,8 +101,14 @@
 
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
-        phone.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
-                intentFilter, null, null);
+        try {
+            Context contextAsUser = phone.getContext().createPackageContextAsUser(
+                    phone.getContext().getPackageName(), 0, UserHandle.ALL);
+            contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
+                    null /* broadcastPermission */, null);
+        } catch (PackageManager.NameNotFoundException e) {
+            loge("Package name not found: " + e.getMessage());
+        }
         PhoneConfigurationManager.registerForMultiSimConfigChange(
                 this, EVENT_BIND_NETWORK_SERVICE, null);
 
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index c848358..94ea9d0 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -19,6 +19,7 @@
 import static android.os.Binder.withCleanCallingIdentity;
 import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
 import static android.telephony.AccessNetworkConstants.AccessNetworkType.GERAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN;
 import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN;
 
 import android.content.Context;
@@ -66,10 +67,12 @@
     private static final int EVENT_STOP_NETWORK_SCAN_DONE = 5;
     private static final int CMD_INTERRUPT_NETWORK_SCAN = 6;
     private static final int EVENT_INTERRUPT_NETWORK_SCAN_DONE = 7;
+    private static final int EVENT_MODEM_RESET = 8;
 
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
+            Log.d(TAG, "Received Event :" + msg.what);
             switch (msg.what) {
                 case CMD_START_NETWORK_SCAN:
                     mScheduler.doStartScan((NetworkScanRequestInfo) msg.obj);
@@ -98,6 +101,14 @@
                 case EVENT_INTERRUPT_NETWORK_SCAN_DONE:
                     mScheduler.interruptScanDone((AsyncResult) msg.obj);
                     break;
+
+                case EVENT_MODEM_RESET:
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    mScheduler.deleteScanAndMayNotify(
+                            (NetworkScanRequestInfo) ar.userObj,
+                            NetworkScan.ERROR_MODEM_ERROR,
+                            true);
+                    break;
             }
         }
     };
@@ -123,7 +134,8 @@
         }
         for (RadioAccessSpecifier ras : nsri.mRequest.getSpecifiers()) {
             if (ras.getRadioAccessNetwork() != GERAN && ras.getRadioAccessNetwork() != UTRAN
-                    && ras.getRadioAccessNetwork() != EUTRAN) {
+                    && ras.getRadioAccessNetwork() != EUTRAN
+                    && ras.getRadioAccessNetwork() != NGRAN) {
                 return false;
             }
             if (ras.getBands() != null && ras.getBands().length > NetworkScanRequest.MAX_BANDS) {
@@ -179,7 +191,7 @@
      */
     public static Set<String> getAllowedMccMncsForLocationRestrictedScan(Context context) {
         return withCleanCallingIdentity(() -> SubscriptionController.getInstance()
-            .getAvailableSubscriptionInfoList(context.getOpPackageName()).stream()
+            .getAvailableSubscriptionInfoList(context.getOpPackageName(), null).stream()
             .flatMap(NetworkScanRequestTracker::getAllowableMccMncsFromSubscriptionInfo)
             .collect(Collectors.toSet()));
     }
@@ -551,6 +563,7 @@
                 mLiveRequestInfo = nsri;
                 nsri.mPhone.startNetworkScan(nsri.getRequest(),
                         mHandler.obtainMessage(EVENT_START_NETWORK_SCAN_DONE, nsri));
+                nsri.mPhone.mCi.registerForModemReset(mHandler, EVENT_MODEM_RESET, nsri);
                 return true;
             }
             return false;
@@ -570,6 +583,7 @@
                                 null);
                     }
                 }
+                mLiveRequestInfo.mPhone.mCi.unregisterForModemReset(mHandler);
                 mLiveRequestInfo = null;
                 if (mPendingRequestInfo != null) {
                     startNewScan(mPendingRequestInfo);
diff --git a/src/java/com/android/internal/telephony/NitzData.java b/src/java/com/android/internal/telephony/NitzData.java
index 8ecf742..f508d9e 100644
--- a/src/java/com/android/internal/telephony/NitzData.java
+++ b/src/java/com/android/internal/telephony/NitzData.java
@@ -18,9 +18,8 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 
-import android.telephony.Rlog;
-
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.Calendar;
 import java.util.TimeZone;
diff --git a/src/java/com/android/internal/telephony/NitzStateMachine.java b/src/java/com/android/internal/telephony/NitzStateMachine.java
index ec5aaa6..e1f854c 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachine.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachine.java
@@ -21,8 +21,8 @@
 import android.content.Context;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.TimestampedValue;
 import android.provider.Settings;
-import android.util.TimestampedValue;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -51,7 +51,8 @@
     void handleNetworkAvailable();
 
     /**
-     * Informs the {@link NitzStateMachine} that the network has become unavailable.
+     * Informs the {@link NitzStateMachine} that the network has become unavailable. Any network
+     * state, i.e. NITZ, should be cleared.
      */
     void handleNetworkUnavailable();
 
diff --git a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
index 23152ac..7a4a3b8 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
@@ -16,19 +16,19 @@
 
 package com.android.internal.telephony;
 
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.content.Context;
 import android.os.PowerManager;
-import android.telephony.Rlog;
+import android.os.TimestampedValue;
 import android.text.TextUtils;
+import android.timezone.CountryTimeZones.OffsetResult;
 import android.util.LocalLog;
-import android.util.TimestampedValue;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TimeZoneLookupHelper.CountryResult;
-import com.android.internal.telephony.TimeZoneLookupHelper.OffsetResult;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -89,8 +89,8 @@
     private boolean mNitzTimeZoneDetectionSuccessful = false;
 
     // Miscellaneous dependencies and helpers not related to detection state.
-    private final LocalLog mTimeLog = new LocalLog(30);
-    private final LocalLog mTimeZoneLog = new LocalLog(30);
+    private final LocalLog mTimeLog = new LocalLog(30, false /* useLocalTimestamps */);
+    private final LocalLog mTimeZoneLog = new LocalLog(30, false /* useLocalTimestamps */);
     private final Phone mPhone;
     private final DeviceState mDeviceState;
     private final TimeServiceHelper mTimeServiceHelper;
@@ -253,7 +253,7 @@
             // Set state as needed.
             if (zoneId != null) {
                 if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
-                    setAndBroadcastNetworkSetTimeZone(zoneId, logMsg);
+                    setTimeZone(zoneId, logMsg);
                 } else {
                     if (DBG) {
                         logMsg += " [Not setting device time zone]";
@@ -267,6 +267,8 @@
                     logMsg += " [Not setting device time zone (zoneId == null)]";
                     Rlog.d(LOG_TAG, logMsg);
                 }
+                mSavedTimeZoneId = null;
+                mNitzTimeZoneDetectionSuccessful = false;
             }
         } catch (RuntimeException ex) {
             Rlog.e(LOG_TAG, "updateTimeZoneFromCountryAndNitz: Processing NITZ data"
@@ -319,19 +321,27 @@
         mSavedNitzTime = null;
         mTimeLog.log("handleNetworkUnavailable: NITZ state cleared.");
 
+        TimestampedValue<NitzData> oldNitzSignal = mLatestNitzSignal;
         mLatestNitzSignal = null;
         mNitzTimeZoneDetectionSuccessful = false;
         mSavedTimeZoneId = null;
         mTimeZoneLog.log("handleNetworkUnavailable: NITZ state cleared.");
 
-        // mSavedTimeZoneId has been cleared but it might be sufficient to detect the time zone
-        // using only the country information that is left.
-        String isoCountryCode = mCountryIsoCode;
-        if (isoCountryCode != null) {
-            if (!TextUtils.isEmpty(isoCountryCode)) {
-                updateTimeZoneFromNetworkCountryCode(isoCountryCode);
-            }
+        // Avoid doing work unnecessarily: if the mLatestNitzSignal was already null we have nothing
+        // to do as it will have been done last time the mLatestNitzSignal was cleared.
+        if (oldNitzSignal == null) {
+            return;
         }
+
+        // mSavedTimeZoneId has been cleared but using only the country information that is left
+        // might be sufficient to detect the time zone.
+        String isoCountryCode = mCountryIsoCode;
+        // We don't need to do country-based time zone detection if the isoCountryCode is null
+        // (unknown) or empty (test cell). TextUtils.isEmpty() does both checks in one.
+        if (!TextUtils.isEmpty(isoCountryCode)) {
+            updateTimeZoneFromNetworkCountryCode(isoCountryCode);
+        }
+        sendEmptyTimeSuggestion("handleNetworkUnavailable");
     }
 
     @Override
@@ -348,7 +358,7 @@
     @Override
     public void handleNitzReceived(TimestampedValue<NitzData> nitzSignal) {
         // Always store the latest NITZ signal received.
-        mLatestNitzSignal = nitzSignal;
+        mLatestNitzSignal = Objects.requireNonNull(nitzSignal);
 
         updateTimeZoneFromCountryAndNitz();
         updateTimeFromNitz();
@@ -376,14 +386,30 @@
         mTimeLog.log("handleAirplaneModeChanged(" + on + "): Time state cleared.");
 
         mCountryIsoCode = null;
+
+        TimestampedValue<NitzData> oldNitzSignal = mLatestNitzSignal;
         mLatestNitzSignal = null;
         mNitzTimeZoneDetectionSuccessful = false;
         mSavedTimeZoneId = null;
+
+        if (oldNitzSignal == null) {
+            // No work to do - terminate early.
+            return;
+        }
+
         mTimeZoneLog.log("handleAirplaneModeChanged(" + on + "): Time zone state cleared.");
+        sendEmptyTimeSuggestion("handleAirplaneModeChanged(" + on + ")");
+    }
+
+    private void sendEmptyTimeSuggestion(String reason) {
+        TelephonyTimeSuggestion timeSuggestion =
+                new TelephonyTimeSuggestion.Builder(mPhone.getPhoneId()).build();
+        timeSuggestion.addDebugInfo("Empty suggestion, reason=" + reason);
+        mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
     }
 
     private void updateTimeFromNitz() {
-        TimestampedValue<NitzData> nitzSignal = mLatestNitzSignal;
+        TimestampedValue<NitzData> nitzSignal = Objects.requireNonNull(mLatestNitzSignal);
         try {
             boolean ignoreNitz = mDeviceState.getIgnoreNitz();
             if (ignoreNitz) {
@@ -459,10 +485,12 @@
                 Rlog.d(LOG_TAG, logMsg);
             }
             mTimeLog.log(logMsg);
-            PhoneTimeSuggestion phoneTimeSuggestion =
-                    new PhoneTimeSuggestion(mPhone.getPhoneId(), newNitzTime);
-            phoneTimeSuggestion.addDebugInfo(logMsg);
-            mTimeServiceHelper.suggestDeviceTime(phoneTimeSuggestion);
+            TelephonyTimeSuggestion timeSuggestion =
+                    new TelephonyTimeSuggestion.Builder(mPhone.getPhoneId())
+                            .setUtcTime(newNitzTime)
+                            .addDebugInfo(logMsg)
+                            .build();
+            mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
 
             TelephonyMetrics.getInstance().writeNITZEvent(
                     mPhone.getPhoneId(), newNitzTime.getValue());
@@ -476,7 +504,7 @@
         }
     }
 
-    private void setAndBroadcastNetworkSetTimeZone(String zoneId, String logMessage) {
+    private void setTimeZone(String zoneId, String logMessage) {
         logMessage += " [Setting device time zone to zoneId=" + zoneId + "]";
         if (DBG) {
             Rlog.d(LOG_TAG, logMessage);
@@ -503,7 +531,7 @@
         String logMsg = "handleAutoTimeZoneEnabled: "
                 + " mSavedTimeZoneId=" + mSavedTimeZoneId;
         if (mSavedTimeZoneId != null) {
-            setAndBroadcastNetworkSetTimeZone(mSavedTimeZoneId, logMsg);
+            setTimeZone(mSavedTimeZoneId, logMsg);
         } else {
             if (DBG) {
                 logMsg += " [Not setting device time zone]";
@@ -562,7 +590,7 @@
 
             String zoneId = lookupResult.zoneId;
             if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
-                setAndBroadcastNetworkSetTimeZone(zoneId, logMsg);
+                setTimeZone(zoneId, logMsg);
             } else {
                 if (DBG) {
                     logMsg += " [Not setting device time zone]";
@@ -576,6 +604,7 @@
                         + " iso=" + iso
                         + " lookupResult=" + lookupResult);
             }
+            mSavedTimeZoneId = null;
         }
     }
 
@@ -588,4 +617,9 @@
     public NitzData getCachedNitzData() {
         return mLatestNitzSignal != null ? mLatestNitzSignal.getValue() : null;
     }
+
+    // VisibleForTesting
+    public String getSavedTimeZoneId() {
+        return mSavedTimeZoneId;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index fd22e77..8a0e497 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -16,20 +16,18 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
-import android.content.BroadcastReceiver;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
 import android.net.NetworkStats;
 import android.net.Uri;
 import android.os.AsyncResult;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -40,20 +38,21 @@
 import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.preference.PreferenceManager;
+import android.sysprop.TelephonyProperties;
 import android.telecom.VideoProfile;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.DataFailureCause;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.CellLocation;
 import android.telephony.ClientRequestStats;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.PhysicalChannelConfig;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.RadioAccessFamily;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
@@ -70,6 +69,7 @@
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.dataconnection.DataConnectionReasons;
 import com.android.internal.telephony.dataconnection.DataEnabledSettings;
 import com.android.internal.telephony.dataconnection.DcTracker;
@@ -85,6 +85,8 @@
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UsimServiceTable;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -116,33 +118,6 @@
 
     protected final int USSD_MAX_QUEUE = 10;
 
-    private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Rlog.d(LOG_TAG, "mImsIntentReceiver: action " + intent.getAction());
-            if (intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
-                int extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
-                        SubscriptionManager.INVALID_PHONE_INDEX);
-                Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " + extraPhoneId);
-                if (extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
-                        extraPhoneId != getPhoneId()) {
-                    return;
-                }
-            }
-
-            synchronized (Phone.lockForRadioTechnologyChange) {
-                if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
-                    mImsServiceReady = true;
-                    updateImsPhone();
-                    ImsManager.getInstance(mContext, mPhoneId).updateImsServiceConfig(false);
-                } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
-                    mImsServiceReady = false;
-                    updateImsPhone();
-                }
-            }
-        }
-    };
-
     // Key used to read and write the saved network selection numeric value
     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
     // Key used to read and write the saved network selection operator name
@@ -198,7 +173,8 @@
     // other
     protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
     protected static final int EVENT_ICC_RECORD_EVENTS              = 29;
-    private static final int EVENT_ICC_CHANGED                      = 30;
+    @VisibleForTesting
+    protected static final int EVENT_ICC_CHANGED                    = 30;
     // Single Radio Voice Call Continuity
     private static final int EVENT_SRVCC_STATE_CHANGED              = 31;
     private static final int EVENT_INITIATE_SILENT_REDIAL           = 32;
@@ -224,9 +200,13 @@
     protected static final int EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE = 50;
     protected static final int EVENT_GET_AVAILABLE_NETWORKS_DONE    = 51;
 
-    private static final int EVENT_ALL_DATA_DISCONNECTED         = 52;
+    private static final int EVENT_ALL_DATA_DISCONNECTED            = 52;
+    protected static final int EVENT_UICC_APPS_ENABLEMENT_CHANGED   = 53;
+    protected static final int EVENT_GET_UICC_APPS_ENABLEMENT_DONE  = 54;
+    protected static final int EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE = 55;
+    protected static final int EVENT_REGISTRATION_FAILED = 56;
 
-    protected static final int EVENT_LAST = EVENT_ALL_DATA_DISCONNECTED;
+    protected static final int EVENT_LAST = EVENT_REGISTRATION_FAILED;
 
     // For shared prefs.
     private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
@@ -323,7 +303,6 @@
     @UnsupportedAppUsage
     protected int mPhoneId;
 
-    private boolean mImsServiceReady = false;
     @UnsupportedAppUsage
     protected Phone mImsPhone = null;
 
@@ -342,8 +321,20 @@
      * TODO: Replace this with a proper exception; {@link CallStateException} doesn't make sense.
      */
     public static final String CS_FALLBACK = "cs_fallback";
-    public static final String EXTRA_KEY_ALERT_TITLE = "alertTitle";
-    public static final String EXTRA_KEY_ALERT_MESSAGE = "alertMessage";
+    /**
+     * @deprecated Use {@link android.telephony.ims.ImsManager#EXTRA_WFC_REGISTRATION_FAILURE_TITLE}
+     * instead.
+     */
+    @Deprecated
+    public static final String EXTRA_KEY_ALERT_TITLE =
+            android.telephony.ims.ImsManager.EXTRA_WFC_REGISTRATION_FAILURE_TITLE;
+    /**
+     * @deprecated Use
+     * {@link android.telephony.ims.ImsManager#EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE} instead.
+     */
+    @Deprecated
+    public static final String EXTRA_KEY_ALERT_MESSAGE =
+            android.telephony.ims.ImsManager.EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE;
     public static final String EXTRA_KEY_ALERT_SHOW = "alertShow";
     public static final String EXTRA_KEY_NOTIFICATION_MESSAGE = "notificationMessage";
 
@@ -382,6 +373,10 @@
 
     private final RegistrantList mRedialRegistrants = new RegistrantList();
 
+    private final RegistrantList mPhysicalChannelConfigRegistrants = new RegistrantList();
+
+    private final RegistrantList mOtaspRegistrants = new RegistrantList();
+
     protected Registrant mPostDialHandler;
 
     protected final LocalLog mLocalLog;
@@ -452,27 +447,6 @@
     }
 
     /**
-     * Set a system property for the current phone, unless we're in unit test mode
-     */
-    // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
-    public void setSystemProperty(String property, String value) {
-        if (getUnitTestMode()) {
-            return;
-        }
-        TelephonyManager.setTelephonyProperty(mPhoneId, property, value);
-    }
-
-    /**
-     * Set a system property for all phones, unless we're in unit test mode
-     */
-    public void setGlobalSystemProperty(String property, String value) {
-        if (getUnitTestMode()) {
-            return;
-        }
-        TelephonyManager.setTelephonyProperty(property, value);
-    }
-
-    /**
      * Set a system property, unless we're in unit test mode
      */
     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
@@ -526,7 +500,7 @@
                 .makeAppSmsManager(context);
         mLocalLog = new LocalLog(64);
 
-        if (Build.IS_DEBUGGABLE) {
+        if (TelephonyUtils.IS_DEBUGGABLE) {
             mTelephonyTester = new TelephonyTester(this);
         }
 
@@ -542,8 +516,8 @@
         * This will be false on "data only" devices which can't make voice
         * calls and don't support any in-call UI.
         */
-        mIsVoiceCapable = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable);
+        mIsVoiceCapable = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
+                .isVoiceCapable();
 
         /**
          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
@@ -555,12 +529,11 @@
          * the RIL_UNSOL_CALL_RING so the default if there is no property is
          * true.
          */
-        mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
-                TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
+        mDoesRilSendMultipleCallRing = TelephonyProperties.ril_sends_multiple_call_ring()
+                .orElse(true);
         Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
 
-        mCallRingDelay = SystemProperties.getInt(
-                TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
+        mCallRingDelay = TelephonyProperties.call_ring_delay().orElse(3000);
         Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
 
         if (getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
@@ -586,34 +559,20 @@
     }
 
     /**
-     * Start listening for IMS service UP/DOWN events. If using the new ImsResolver APIs, we should
-     * always be setting up ImsPhones.
+     * Start setup of ImsPhone, which will start trying to connect to the ImsResolver. Will not be
+     * called if this device does not support FEATURE_IMS_TELEPHONY.
      */
-    public void startMonitoringImsService() {
+    public void createImsPhone() {
         if (getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
             return;
         }
 
         synchronized(Phone.lockForRadioTechnologyChange) {
-            IntentFilter filter = new IntentFilter();
-            ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId());
-            // Don't listen to deprecated intents using the new dynamic binding.
-            if (imsManager != null && !imsManager.isDynamicBinding()) {
-                filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
-                filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
-                mContext.registerReceiver(mImsIntentReceiver, filter);
-            }
-
-            // Monitor IMS service - but first poll to see if already up (could miss
-            // intent). Also, when using new ImsResolver APIs, the service will be available soon,
-            // so start trying to bind.
-            if (imsManager != null) {
-                // If it is dynamic binding, kick off ImsPhone creation now instead of waiting for
-                // the service to be available.
-                if (imsManager.isDynamicBinding() || imsManager.isServiceAvailable()) {
-                    mImsServiceReady = true;
-                    updateImsPhone();
-                }
+            if (mImsPhone == null) {
+                mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
+                CallManager.getInstance().registerPhone(mImsPhone);
+                mImsPhone.registerForSilentRedial(
+                        this, EVENT_INITIATE_SILENT_REDIAL, null);
             }
         }
     }
@@ -1425,7 +1384,7 @@
         nsm.operatorAlphaShort = network.getOperatorAlphaShort();
 
         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
-        mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
+        mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), network.getRan(), msg);
 
         if (persistSelection) {
             updateSavedNetworkOperator(nsm);
@@ -1918,17 +1877,16 @@
     /**
      * @return the current cell location if known
      */
-    @UnsupportedAppUsage
-    public CellLocation getCellLocation() {
-        return getServiceStateTracker().getCellLocation();
+    public CellIdentity getCellIdentity() {
+        return getServiceStateTracker().getCellIdentity();
     }
 
     /**
      * @param workSource calling WorkSource
      * @param rspMsg the response message containing the cell location
      */
-    public void getCellLocation(WorkSource workSource, Message rspMsg) {
-        getServiceStateTracker().requestCellLocation(workSource, rspMsg);
+    public void getCellIdentity(WorkSource workSource, Message rspMsg) {
+        getServiceStateTracker().requestCellIdentity(workSource, rspMsg);
     }
 
     /**
@@ -2010,10 +1968,11 @@
 
     public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
         setCallForwardingIndicatorInSharedPref(enable);
-        IccRecords r = mIccRecords.get();
+        IccRecords r = getIccRecords();
         if (r != null) {
             r.setVoiceCallForwardingFlag(line, enable, number);
         }
+        notifyCallForwardingIndicator();
     }
 
     /**
@@ -2027,7 +1986,10 @@
     public void setVoiceCallForwardingFlag(IccRecords r, int line, boolean enable,
                                               String number) {
         setCallForwardingIndicatorInSharedPref(enable);
-        r.setVoiceCallForwardingFlag(line, enable, number);
+        if (r != null) {
+            r.setVoiceCallForwardingFlag(line, enable, number);
+        }
+        notifyCallForwardingIndicator();
     }
 
     /**
@@ -2041,7 +2003,7 @@
             Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
             return false;
         }
-        IccRecords r = mIccRecords.get();
+        IccRecords r = getIccRecords();
         int callForwardingIndicator = IccRecords.CALL_FORWARDING_STATUS_UNKNOWN;
         if (r != null) {
             callForwardingIndicator = r.getVoiceCallForwardingFlag();
@@ -2362,6 +2324,15 @@
         mCi.nvResetConfig(3 /* factory NV reset */, response);
     }
 
+    /**
+     * Perform modem configuration erase. Used for network reset
+     *
+     * @param response Callback message.
+     */
+    public void eraseModemConfig(Message response) {
+        mCi.nvResetConfig(2 /* erase NV */, response);
+    }
+
     public void notifyDataActivity() {
         mNotifier.notifyDataActivity(this);
     }
@@ -2375,23 +2346,22 @@
         mNotifier.notifyMessageWaitingChanged(this);
     }
 
+    /** Send notification with an updated PreciseDataConnectionState to a single data connection */
     public void notifyDataConnection(String apnType) {
-        mNotifier.notifyDataConnection(this, apnType, getDataConnectionState(apnType));
+        mNotifier.notifyDataConnection(this, apnType, getPreciseDataConnectionState(apnType));
     }
 
-    public void notifyDataConnection() {
+    /** Send notification with an updated PreciseDataConnectionState to all data connections */
+    public void notifyAllActiveDataConnections() {
         String types[] = getActiveApnTypes();
-        if (types != null) {
-            for (String apnType : types) {
-                mNotifier.notifyDataConnection(this, apnType,
-                        getDataConnectionState(apnType));
-            }
+        for (String apnType : types) {
+            mNotifier.notifyDataConnection(this, apnType, getPreciseDataConnectionState(apnType));
         }
     }
 
     @UnsupportedAppUsage
     public void notifyOtaspChanged(int otaspMode) {
-        mNotifier.notifyOtaspChanged(this, otaspMode);
+        mOtaspRegistrants.notifyRegistrants(new AsyncResult(null, otaspMode, null));
     }
 
     public void notifyVoiceActivationStateChanged(int state) {
@@ -2414,6 +2384,11 @@
         return PhoneConstants.DataState.DISCONNECTED;
     }
 
+    /** Default implementation to get the PreciseDataConnectionState */
+    public @Nullable PreciseDataConnectionState getPreciseDataConnectionState(String apnType) {
+        return null;
+    }
+
     public void notifyCellInfo(List<CellInfo> cellInfo) {
         AsyncResult ar = new AsyncResult(null, cellInfo, null);
         mCellInfoRegistrants.notifyRegistrants(ar);
@@ -2421,9 +2396,34 @@
         mNotifier.notifyCellInfo(this, cellInfo);
     }
 
+    /**
+     * Registration point for PhysicalChannelConfig change.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj.userObj
+     */
+    public void registerForPhysicalChannelConfig(Handler h, int what, Object obj) {
+        checkCorrectThread(h);
+        Registrant registrant = new Registrant(h, what, obj);
+        mPhysicalChannelConfigRegistrants.add(registrant);
+        // notify first
+        List<PhysicalChannelConfig> physicalChannelConfigs = getPhysicalChannelConfigList();
+        if (physicalChannelConfigs != null) {
+            registrant.notifyRegistrant(new AsyncResult(null, physicalChannelConfigs, null));
+        }
+    }
+
+    public void unregisterForPhysicalChannelConfig(Handler h) {
+        mPhysicalChannelConfigRegistrants.remove(h);
+    }
+
     /** Notify {@link PhysicalChannelConfig} changes. */
     public void notifyPhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
-        mNotifier.notifyPhysicalChannelConfiguration(this, configs);
+        mPhysicalChannelConfigRegistrants.notifyRegistrants(new AsyncResult(null, configs, null));
+    }
+
+    public List<PhysicalChannelConfig> getPhysicalChannelConfigList() {
+        return null;
     }
 
     /**
@@ -2458,7 +2458,7 @@
     // This property is used to handle phone process crashes, and is the same for CDMA and IMS
     // phones
     protected static boolean getInEcmMode() {
-        return SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false);
+        return TelephonyProperties.in_ecm_mode().orElse(false);
     }
 
     /**
@@ -2470,8 +2470,14 @@
         return mIsPhoneInEcmState;
     }
 
+    public boolean isInImsEcm() {
+        return false;
+    }
+
     public void setIsInEcm(boolean isInEcm) {
-        setGlobalSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, String.valueOf(isInEcm));
+        if (!getUnitTestMode()) {
+            TelephonyProperties.in_ecm_mode(isInEcm);
+        }
         mIsPhoneInEcmState = isInEcm;
     }
 
@@ -2620,7 +2626,8 @@
             options.setBackgroundActivityStartsAllowed(true);
             Intent intent = new Intent(TelephonyIntents.SECRET_CODE_ACTION,
                     Uri.parse("android_secret_code://" + code));
-            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+            intent.addFlags(
+                    Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);
             mContext.sendBroadcast(intent, null, options.toBundle());
 
             // {@link TelephonyManager.ACTION_SECRET_CODE} will replace {@link
@@ -2628,7 +2635,8 @@
             // that both of these two actions will be broadcast.
             Intent secrectCodeIntent = new Intent(TelephonyManager.ACTION_SECRET_CODE,
                     Uri.parse("android_secret_code://" + code));
-            secrectCodeIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+            secrectCodeIntent.addFlags(
+                    Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);
             mContext.sendBroadcast(secrectCodeIntent, null, options.toBundle());
         }
     }
@@ -2799,6 +2807,42 @@
     }
 
     /**
+     * Register for notifications when OTA Service Provisioning mode has changed.
+     *
+     * <p>The mode is integer. {@link TelephonyManager#OTASP_UNKNOWN}
+     * means the value is currently unknown and the system should wait until
+     * {@link TelephonyManager#OTASP_NEEDED} or {@link TelephonyManager#OTASP_NOT_NEEDED} is
+     * received before making the decision to perform OTASP or not.
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    public void registerForOtaspChange(Handler h, int what, Object obj) {
+        checkCorrectThread(h);
+        mOtaspRegistrants.addUnique(h, what, obj);
+        // notify first
+        new Registrant(h, what, obj).notifyRegistrant(new AsyncResult(null, getOtasp(), null));
+    }
+
+    /**
+     * Unegister for notifications when OTA Service Provisioning mode has changed.
+     * @param h Handler to be removed from the registrant list.
+     */
+    public void unregisterForOtaspChange(Handler h) {
+        mOtaspRegistrants.remove(h);
+    }
+
+    /**
+     * Returns the current OTA Service Provisioning mode.
+     *
+     * @see registerForOtaspChange
+     */
+    public int getOtasp() {
+        return TelephonyManager.OTASP_UNKNOWN;
+    }
+
+    /**
      * Register for notifications when CDMA call waiting comes
      *
      * @param h Handler that receives the notification message.
@@ -3045,26 +3089,26 @@
 
     /**
      * Returns an array of string identifiers for the APN types serviced by the
-     * currently active.
+     * currently active subscription.
      *
      * @return The string array of APN types. Return null if no active APN types.
      */
     @UnsupportedAppUsage
-    @Nullable
+    @NonNull
     public String[] getActiveApnTypes() {
-        if (mTransportManager != null) {
-            List<String> typesList = new ArrayList<>();
-            for (int transportType : mTransportManager.getAvailableTransports()) {
-                if (getDcTracker(transportType) != null) {
-                    typesList.addAll(Arrays.asList(
-                            getDcTracker(transportType).getActiveApnTypes()));
-                }
-            }
-
-            return typesList.toArray(new String[typesList.size()]);
+        if (mTransportManager == null || mDcTrackers == null)  {
+            Rlog.e(LOG_TAG, "Invalid state for Transport/DcTrackers");
+            return new String[0];
         }
 
-        return null;
+        Set<String> activeApnTypes = new HashSet<String>();
+        for (int transportType : mTransportManager.getAvailableTransports()) {
+            DcTracker dct = getDcTracker(transportType);
+            if (dct == null) continue; // TODO: should this ever happen?
+            activeApnTypes.addAll(Arrays.asList(dct.getActiveApnTypes()));
+        }
+
+        return activeApnTypes.toArray(new String[activeApnTypes.size()]);
     }
 
     /**
@@ -3240,6 +3284,17 @@
     }
 
     /**
+     * Enable or disable always reporting signal strength changes from radio.
+     *
+     * @param isEnable {@code true} for enabling; {@code false} for disabling.
+     */
+    public void setAlwaysReportSignalStrength(boolean isEnable) {
+        if (mDeviceStateMonitor != null) {
+            mDeviceStateMonitor.setAlwaysReportSignalStrength(isEnable);
+        }
+    }
+
+    /**
      * TODO: Adding a function for each property is not good.
      * A fucntion of type getPhoneProp(propType) where propType is an
      * enum of GSM+CDMA+LTE props would be a better approach.
@@ -3294,13 +3349,10 @@
     public void notifyCallForwardingIndicator() {
     }
 
-    public void notifyDataConnectionFailed(String apnType) {
-        mNotifier.notifyDataConnectionFailed(this, apnType);
-    }
-
-    public void notifyPreciseDataConnectionFailed(String apnType, String apn,
-                                                  @DataFailureCause int failCause) {
-        mNotifier.notifyPreciseDataConnectionFailed(this, apnType, apn, failCause);
+    /** Send a notification that a particular data connection has failed with specified cause. */
+    public void notifyDataConnectionFailed(
+            String apnType, String apn, @DataFailureCause int failCause) {
+        mNotifier.notifyDataConnectionFailed(this, apnType, apn, failCause);
     }
 
     /**
@@ -3421,6 +3473,10 @@
         return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
     }
 
+    public int getEmergencyNumberDbVersion() {
+        return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
+    }
+
     public void resolveSubscriptionCarrierId(String simState) {
     }
 
@@ -3448,28 +3504,6 @@
     public void dispose() {
     }
 
-    private void updateImsPhone() {
-        Rlog.d(LOG_TAG, "updateImsPhone"
-                + " mImsServiceReady=" + mImsServiceReady);
-
-        if (mImsServiceReady && (mImsPhone == null)) {
-            mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
-            CallManager.getInstance().registerPhone(mImsPhone);
-            mImsPhone.registerForSilentRedial(
-                    this, EVENT_INITIATE_SILENT_REDIAL, null);
-        } else if (!mImsServiceReady && (mImsPhone != null)) {
-            CallManager.getInstance().unregisterPhone(mImsPhone);
-            mImsPhone.unregisterForSilentRedial(this);
-
-            mImsPhone.dispose();
-            // Potential GC issue if someone keeps a reference to ImsPhone.
-            // However: this change will make sure that such a reference does
-            // not access functions through NULL pointer.
-            //mImsPhone.removeReferences();
-            mImsPhone = null;
-        }
-    }
-
     /**
      * Dials a number.
      *
@@ -3900,7 +3934,8 @@
     }
 
     /** Sets the SignalStrength reporting criteria. */
-    public void setSignalStrengthReportingCriteria(int[] thresholds, int ran) {
+    public void setSignalStrengthReportingCriteria(
+            int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
         // no-op default implementation
     }
 
@@ -4101,7 +4136,7 @@
                 ServiceState ss = phone.getServiceStateTracker().getServiceState();
                 // One of the phone is in service, hence the device is not emergency call only.
                 if (ss.getState() == ServiceState.STATE_IN_SERVICE
-                        || ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+                        || ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
                     return false;
                 }
                 isEmergencyCallOnly |= ss.isEmergencyOnly();
@@ -4126,6 +4161,20 @@
     }
 
     /**
+     * Enable or disable uicc applications.
+     * @param enable whether to enable or disable uicc applications.
+     * @param onCompleteMessage callback for async operation. Ignored if blockingCall is true.
+     */
+    public void enableUiccApplications(boolean enable, Message onCompleteMessage) {}
+
+    /**
+     * Whether disabling a physical subscription is supported or not.
+     */
+    public boolean canDisablePhysicalSubscription() {
+        return false;
+    }
+
+    /**
      * Get the HAL version.
      *
      * @return the current HalVersion
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index df73ef8..4304199 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -26,14 +26,15 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RegistrantList;
-import android.os.SystemProperties;
 import android.os.storage.StorageManager;
+import android.sysprop.TelephonyProperties;
 import android.telephony.PhoneCapability;
-import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -130,19 +131,6 @@
     }
 
     /**
-     * Whether the phoneId has a corresponding active slot / logical modem. If a DSDS capable
-     * device is in single SIM mode, phoneId=1 is valid but not active.
-     *
-     * TODO: b/139642279 combine with SubscriptionManager#isValidPhoneId when phone objects
-     * are dynamically allocated instead of always based on getMaxPhoneCount.
-     * @hide
-     */
-    public static boolean isPhoneActive(int phoneId) {
-        // Currently it simply depends on getPhoneCount. In future it can be generalized.
-        return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
-    }
-
-    /**
      * Handler class to handle callbacks
      */
     private final class ConfigManagerHandler extends Handler {
@@ -318,7 +306,7 @@
     }
 
     public int getNumberOfModemsWithSimultaneousDataConnections() {
-        return mStaticCapability.maxActiveData;
+        return mStaticCapability.getMaxActivePsVoice();
     }
 
     private void notifyCapabilityChanged() {
@@ -333,7 +321,7 @@
      */
     public void switchMultiSimConfig(int numOfSims) {
         log("switchMultiSimConfig: with numOfSims = " + numOfSims);
-        if (getStaticPhoneCapability().logicalModemList.size() < numOfSims) {
+        if (getStaticPhoneCapability().getLogicalModemUuids().size() < numOfSims) {
             log("switchMultiSimConfig: Phone is not capable of enabling "
                     + numOfSims + " sims, exiting!");
             return;
@@ -366,11 +354,12 @@
             pm.reboot("Multi-SIM config changed.");
         } else {
             log("onMultiSimConfigChanged: Rebooting is not required.");
+            mMi.notifyPhoneFactoryOnMultiSimConfigChanged(mContext, numOfActiveModems);
             broadcastMultiSimConfigChange(numOfActiveModems);
             // Register to RIL service if needed.
             for (int i = 0; i < mPhones.length; i++) {
                 Phone phone = mPhones[i];
-                phone.mCi.onSlotActiveStatusChange(isPhoneActive(i));
+                phone.mCi.onSlotActiveStatusChange(SubscriptionManager.isValidPhoneId(i));
             }
         }
     }
@@ -426,14 +415,19 @@
      */
     @VisibleForTesting
     public static class MockableInterface {
+        /**
+         * Wrapper function to decide whether reboot is required for modem config change.
+         */
         @VisibleForTesting
         public boolean isRebootRequiredForModemConfigChange() {
-            String rebootRequired = SystemProperties.get(
-                    TelephonyProperties.PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE);
+            boolean rebootRequired = TelephonyProperties.reboot_on_modem_change().orElse(false);
             log("isRebootRequiredForModemConfigChange: isRebootRequired = " + rebootRequired);
-            return !rebootRequired.equals("false");
+            return rebootRequired;
         }
 
+        /**
+         * Wrapper function to call setMultiSimProperties.
+         */
         @VisibleForTesting
         public void setMultiSimProperties(int numOfActiveModems) {
             String multiSimConfig;
@@ -449,7 +443,16 @@
             }
 
             log("setMultiSimProperties to " + multiSimConfig);
-            SystemProperties.set(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG, multiSimConfig);
+            TelephonyProperties.multi_sim_config(multiSimConfig);
+        }
+
+        /**
+         * Wrapper function to call PhoneFactory.onMultiSimConfigChanged.
+         */
+        @VisibleForTesting
+        public void notifyPhoneFactoryOnMultiSimConfigChanged(
+                Context context, int numOfActiveModems) {
+            PhoneFactory.onMultiSimConfigChanged(context, numOfActiveModems);
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index b92c68b..9b181d3 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -16,30 +16,32 @@
 
 package com.android.internal.telephony;
 
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA_LTE;
+
+import static java.util.Arrays.copyOf;
+
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.net.LocalServerSocket;
+import android.os.HandlerThread;
 import android.os.Looper;
-import android.os.ServiceManager;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.telephony.AnomalyReporter;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.LocalLog;
 
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
 import com.android.internal.telephony.dataconnection.TelephonyNetworkFactory;
 import com.android.internal.telephony.euicc.EuiccCardController;
 import com.android.internal.telephony.euicc.EuiccController;
-import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneFactory;
 import com.android.internal.telephony.sip.SipPhone;
@@ -47,6 +49,7 @@
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.util.NotificationChannelController;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -87,9 +90,7 @@
     static private Context sContext;
     static private PhoneConfigurationManager sPhoneConfigurationManager;
     static private PhoneSwitcher sPhoneSwitcher;
-    static private SubscriptionMonitor sSubscriptionMonitor;
     static private TelephonyNetworkFactory[] sTelephonyNetworkFactories;
-    static private ImsResolver sImsResolver;
     static private NotificationChannelController sNotificationChannelController;
     static private CellularNetworkValidator sCellularNetworkValidator;
 
@@ -146,7 +147,7 @@
                 /* In case of multi SIM mode two instances of Phone, RIL are created,
                    where as in single SIM mode only instance. isMultiSimEnabled() function checks
                    whether it is single SIM or multi SIM mode */
-                int numPhones = TelephonyManager.getDefault().getSupportedModemCount();
+                int numPhones = TelephonyManager.getDefault().getActiveModemCount();
 
                 int[] networkModes = new int[numPhones];
                 sPhones = new Phone[numPhones];
@@ -165,7 +166,7 @@
 
                 // Instantiate UiccController so that all other classes can just
                 // call getInstance()
-                sUiccController = UiccController.make(context, sCommandsInterfaces);
+                sUiccController = UiccController.make(context);
 
                 Rlog.i(LOG_TAG, "Creating SubscriptionController");
                 SubscriptionController sc = SubscriptionController.init(context);
@@ -178,28 +179,13 @@
                 }
 
                 for (int i = 0; i < numPhones; i++) {
-                    Phone phone = null;
-                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
-                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
-                        phone = new GsmCdmaPhone(context,
-                                sCommandsInterfaces[i], sPhoneNotifier, i,
-                                PhoneConstants.PHONE_TYPE_GSM,
-                                TelephonyComponentFactory.getInstance());
-                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
-                        phone = new GsmCdmaPhone(context,
-                                sCommandsInterfaces[i], sPhoneNotifier, i,
-                                PhoneConstants.PHONE_TYPE_CDMA_LTE,
-                                TelephonyComponentFactory.getInstance());
-                    }
-                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
-
-                    sPhones[i] = phone;
+                    sPhones[i] = createPhone(context, i);
                 }
 
                 // Set the default phone in base class.
                 // FIXME: This is a first best guess at what the defaults will be. It
                 // FIXME: needs to be done in a more controlled manner in the future.
-                sPhone = sPhones[0];
+                if (numPhones > 0) sPhone = sPhones[0];
 
                 // Ensure that we have a default SMS app. Requesting the app with
                 // updateIfNeeded set to true is enough to configure a default SMS app.
@@ -217,41 +203,24 @@
                 sMadeDefaults = true;
 
                 Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");
+                HandlerThread pfhandlerThread = new HandlerThread("PhoneFactoryHandlerThread");
+                pfhandlerThread.start();
                 sSubInfoRecordUpdater = new SubscriptionInfoUpdater(
-                        BackgroundThread.get().getLooper(), context, sCommandsInterfaces);
-                sc.updatePhonesAvailability(sPhones);
+                        pfhandlerThread.getLooper(), context, sCommandsInterfaces);
 
                 // Only bring up IMS if the device supports having an IMS stack.
                 if (context.getPackageManager().hasSystemFeature(
                         PackageManager.FEATURE_TELEPHONY_IMS)) {
-                    // Return whether or not the device should use dynamic binding or the static
-                    // implementation (deprecated)
-                    boolean isDynamicBinding = sContext.getResources().getBoolean(
-                            com.android.internal.R.bool.config_dynamic_bind_ims);
-                    // Get the package name of the default IMS implementation.
-                    String defaultImsPackage = sContext.getResources().getString(
-                            com.android.internal.R.string.config_ims_package);
-                    // Start ImsResolver and bind to ImsServices.
-                    Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage);
-                    sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones,
-                            isDynamicBinding);
-                    sImsResolver.initialize();
                     // Start monitoring after defaults have been made.
                     // Default phone must be ready before ImsPhone is created because ImsService
-                    // might need it when it is being opened. This should initialize multiple
-                    // ImsPhones for ImsResolver implementations of ImsService.
+                    // might need it when it is being opened.
                     for (int i = 0; i < numPhones; i++) {
-                        sPhones[i].startMonitoringImsService();
+                        sPhones[i].createImsPhone();
                     }
                 } else {
                     Rlog.i(LOG_TAG, "IMS is not supported on this device, skipping ImsResolver.");
                 }
 
-                ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
-                        ServiceManager.getService("telephony.registry"));
-
-                sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);
-
                 sPhoneConfigurationManager = PhoneConfigurationManager.init(sContext);
 
                 sCellularNetworkValidator = CellularNetworkValidator.make(sContext);
@@ -259,11 +228,9 @@
                 int maxActivePhones = sPhoneConfigurationManager
                         .getNumberOfModemsWithSimultaneousDataConnections();
 
-                sPhoneSwitcher = PhoneSwitcher.make(maxActivePhones, numPhones,
-                        sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
-                        sPhones);
+                sPhoneSwitcher = PhoneSwitcher.make(maxActivePhones, sContext, Looper.myLooper());
 
-                sProxyController = ProxyController.getInstance(context, sPhones, sPhoneSwitcher);
+                sProxyController = ProxyController.getInstance(context);
 
                 sIntentBroadcaster = IntentBroadcaster.getInstance(context);
 
@@ -271,12 +238,59 @@
 
                 for (int i = 0; i < numPhones; i++) {
                     sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
-                            sSubscriptionMonitor, Looper.myLooper(), sPhones[i]);
+                            Looper.myLooper(), sPhones[i]);
                 }
             }
         }
     }
 
+    /**
+     * Upon single SIM to dual SIM switch or vice versa, we dynamically allocate or de-allocate
+     * Phone and CommandInterface objects.
+     * @param context
+     * @param activeModemCount
+     */
+    public static void onMultiSimConfigChanged(Context context, int activeModemCount) {
+        synchronized (sLockProxyPhones) {
+            int prevActiveModemCount = sPhones.length;
+            if (prevActiveModemCount == activeModemCount) return;
+
+            // TODO: clean up sPhones, sCommandsInterfaces and sTelephonyNetworkFactories objects.
+            // Currently we will not clean up the 2nd Phone object, so that it can be re-used if
+            // user switches back.
+            if (prevActiveModemCount > activeModemCount) return;
+
+            sPhones = copyOf(sPhones, activeModemCount);
+            sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount);
+            sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+
+            int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
+            for (int i = prevActiveModemCount; i < activeModemCount; i++) {
+                sCommandsInterfaces[i] = new RIL(context, RILConstants.PREFERRED_NETWORK_MODE,
+                        cdmaSubscription, i);
+                sPhones[i] = createPhone(context, i);
+                if (context.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_TELEPHONY_IMS)) {
+                    sPhones[i].createImsPhone();
+                }
+                sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+                        Looper.myLooper(), sPhones[i]);
+            }
+        }
+    }
+
+    private static Phone createPhone(Context context, int phoneId) {
+        int phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
+        Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId);
+
+        // We always use PHONE_TYPE_CDMA_LTE now.
+        if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
+
+        return new GsmCdmaPhone(context,
+                sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType,
+                TelephonyComponentFactory.getInstance());
+    }
+
     @UnsupportedAppUsage
     public static Phone getDefaultPhone() {
         synchronized (sLockProxyPhones) {
@@ -331,14 +345,6 @@
     }
 
     /**
-     * @return The ImsResolver instance or null if IMS is not supported
-     * (FEATURE_TELEPHONY_IMS is not defined).
-     */
-    public static @Nullable ImsResolver getImsResolver() {
-        return sImsResolver;
-    }
-
-    /**
      * Get the network factory associated with a given phone ID.
      * @param phoneId the phone id
      * @return a factory for this phone ID, or null if none.
@@ -462,6 +468,15 @@
     }
 
     /**
+     * Get Command Interfaces.
+     */
+    public static CommandsInterface[] getCommandsInterfaces() {
+        synchronized (sLockProxyPhones) {
+            return sCommandsInterfaces;
+        }
+    }
+
+    /**
      * Adds a local log category.
      *
      * Only used within the telephony process.  Use localLog to add log entries.
@@ -528,26 +543,6 @@
             pw.println("++++++++++++++++++++++++++++++++");
         }
 
-        pw.println("ImsResolver:");
-        pw.increaseIndent();
-        try {
-            if (sImsResolver != null) sImsResolver.dump(fd, pw, args);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        pw.decreaseIndent();
-        pw.println("++++++++++++++++++++++++++++++++");
-
-        pw.println("SubscriptionMonitor:");
-        pw.increaseIndent();
-        try {
-            sSubscriptionMonitor.dump(fd, pw, args);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        pw.decreaseIndent();
-        pw.println("++++++++++++++++++++++++++++++++");
-
         pw.println("UiccController:");
         pw.increaseIndent();
         try {
diff --git a/src/java/com/android/internal/telephony/PhoneInternalInterface.java b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
index a7f0f3e..20976df 100644
--- a/src/java/com/android/internal/telephony/PhoneInternalInterface.java
+++ b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
@@ -17,7 +17,7 @@
 package com.android.internal.telephony;
 
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -25,6 +25,7 @@
 import android.telecom.VideoProfile;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 
@@ -237,6 +238,16 @@
     DataState getDataConnectionState(String apnType);
 
     /**
+     * Get the current Precise DataState. No change notification exists at this
+     * interface -- use
+     * {@link android.telephony.PhoneStateListener} instead.
+     *
+     * @param apnType specify for which apn to get connection state info.
+     * @return the PreciseDataConnectionState for the data connection supporting apnType
+     */
+    PreciseDataConnectionState getPreciseDataConnectionState(String apnType);
+
+    /**
      * Get the current DataActivityState. No change notification exists at this
      * interface -- use
      * {@link android.telephony.TelephonyManager} instead.
@@ -424,6 +435,21 @@
     Connection dial(String dialString, @NonNull DialArgs dialArgs) throws CallStateException;
 
     /**
+     * Initiate a new conference connection. This happens asynchronously, so you
+     * cannot assume the audio path is connected (or a call index has been
+     * assigned) until PhoneStateChanged notification has occurred.
+     *
+     * @param participantsToDial The participants to dial.
+     * @param dialArgs Parameters to perform the start conference with.
+     * @exception CallStateException if a new outgoing call is not currently
+     *                possible because no more call slots exist or a call exists
+     *                that is dialing, alerting, ringing, or waiting. Other
+     *                errors are handled asynchronously.
+     */
+    Connection startConference(String[] participantsToDial, @NonNull DialArgs dialArgs)
+            throws CallStateException;
+
+    /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
      *
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index 31cd71f..36fad5e 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -16,15 +16,16 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.telephony.Annotation.DataFailureCause;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SrvccState;
 import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.CellLocation;
 import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
@@ -39,8 +40,12 @@
 
     void notifyServiceState(Phone sender);
 
-    /** Notify registrants of the current CellLocation */
-    void notifyCellLocation(Phone sender, CellLocation cl);
+    /**
+     * Notify registrants of the current CellLocation.
+     *
+     * <p>Use CellIdentity that is Parcellable to pass AIDL; convert to CellLocation in client code.
+     */
+    void notifyCellLocation(Phone sender, CellIdentity cellIdentity);
 
     @UnsupportedAppUsage
     void notifySignalStrength(Phone sender);
@@ -50,40 +55,41 @@
 
     void notifyCallForwardingChanged(Phone sender);
 
-    void notifyDataConnection(Phone sender, String apnType, PhoneConstants.DataState state);
-
-    void notifyDataConnectionFailed(Phone sender, String apnType);
+    /** Send a notification that the Data Connection for a particular apnType has changed */
+    void notifyDataConnection(
+            Phone sender, String apnType, PreciseDataConnectionState preciseState);
 
     void notifyDataActivity(Phone sender);
 
-    void notifyOtaspChanged(Phone sender, int otaspMode);
-
     void notifyCellInfo(Phone sender, List<CellInfo> cellInfo);
 
-    /** Notify of change to PhysicalChannelConfiguration. */
-    void notifyPhysicalChannelConfiguration(Phone sender, List<PhysicalChannelConfig> configs);
-
     void notifyPreciseCallState(Phone sender);
 
     void notifyDisconnectCause(Phone sender, int cause, int preciseCause);
 
     void notifyImsDisconnectCause(Phone sender, ImsReasonInfo imsReasonInfo);
 
-    public void notifyPreciseDataConnectionFailed(Phone sender, String apnType, String apn,
+    /** Send a notification that a particular data connection has failed with specified cause. */
+    void notifyDataConnectionFailed(Phone sender, String apnType, String apn,
                                                   @DataFailureCause int failCause);
 
-    /** send a notification that the SRVCC state has changed.*/
+    /** Send a notification that the SRVCC state has changed.*/
     void notifySrvccStateChanged(Phone sender, @SrvccState int state);
 
-    public void notifyVoiceActivationStateChanged(Phone sender, int activationState);
+    /** Send a notification that the voice activation state has changed */
+    void notifyVoiceActivationStateChanged(Phone sender, int activationState);
 
-    public void notifyDataActivationStateChanged(Phone sender, int activationState);
+    /** Send a notification that the data activation state has changed */
+    void notifyDataActivationStateChanged(Phone sender, int activationState);
 
-    public void notifyUserMobileDataStateChanged(Phone sender, boolean state);
+    /** Send a notification that the users mobile data setting has changed */
+    void notifyUserMobileDataStateChanged(Phone sender, boolean state);
 
-    public void notifyOemHookRawEventForSubscriber(Phone sender, byte[] rawData);
+    /** Send a notification with an OEM hook payload */
+    void notifyOemHookRawEventForSubscriber(Phone sender, byte[] rawData);
 
-    public void notifyPhoneCapabilityChanged(PhoneCapability capability);
+    /** Send a notification that the phone capability has changed */
+    void notifyPhoneCapabilityChanged(PhoneCapability capability);
 
     void notifyRadioPowerStateChanged(Phone sender, @RadioPowerState int state);
 
@@ -98,4 +104,8 @@
 
     /** Notify of a change to the call quality of an active foreground call. */
     void notifyCallQualityChanged(Phone sender, CallQuality callQuality, int callNetworkType);
+
+    /** Notify registration failed*/
+    void notifyRegistrationFailed(Phone sender, @NonNull CellIdentity cellIdentity,
+            @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
 }
diff --git a/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index 1d9f4f0..6d0b03c 100644
--- a/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,7 +26,8 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  *
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index c5b7eda..35af1b4 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -21,8 +21,10 @@
 import static android.Manifest.permission.MODIFY_PHONE_STATE;
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
 
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -30,12 +32,12 @@
 import android.os.ServiceManager;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 
 import com.android.internal.telephony.uicc.IsimRecords;
 import com.android.internal.telephony.uicc.UiccCard;
 import com.android.internal.telephony.uicc.UiccCardApplication;
+import com.android.telephony.Rlog;
 
 public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
     private static final String TAG = "PhoneSubInfoController";
@@ -43,13 +45,10 @@
     private static final boolean VDBG = false; // STOPSHIP if true
 
     @UnsupportedAppUsage
-    private final Phone[] mPhone;
-    @UnsupportedAppUsage
     private final Context mContext;
     private final AppOpsManager mAppOps;
 
-    public PhoneSubInfoController(Context context, Phone[] phone) {
-        mPhone = phone;
+    public PhoneSubInfoController(Context context) {
         if (ServiceManager.getService("iphonesubinfo") == null) {
             ServiceManager.addService("iphonesubinfo", this);
         }
@@ -57,29 +56,36 @@
         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
     }
 
+    @Deprecated
     public String getDeviceId(String callingPackage) {
+        return getDeviceIdWithFeature(callingPackage, null);
+    }
+
+    public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
         return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()),
-                callingPackage);
+                callingPackage, callingFeatureId);
     }
 
-    public String getDeviceIdForPhone(int phoneId, String callingPackage) {
+    public String getDeviceIdForPhone(int phoneId, String callingPackage,
+            String callingFeatureId) {
         return callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(phoneId, callingPackage,
-                "getDeviceId", (phone)-> phone.getDeviceId());
+                callingFeatureId, "getDeviceId", (phone) -> phone.getDeviceId());
     }
 
-    public String getNaiForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getNai",
-                (phone)-> phone.getNai());
+    public String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
+                callingFeatureId, "getNai", (phone)-> phone.getNai());
     }
 
-    public String getImeiForSubscriber(int subId, String callingPackage) {
+    public String getImeiForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
         return callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(subId, callingPackage,
-                "getImei", (phone)-> phone.getImei());
+                callingFeatureId, "getImei", (phone) -> phone.getImei());
     }
 
     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
                                                               String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+        return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
                 "getCarrierInfoForImsiEncryption",
                 (phone)-> phone.getCarrierInfoForImsiEncryption(keyType));
     }
@@ -103,42 +109,50 @@
      */
     public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
         callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
-                "setCarrierInfoForImsiEncryption",
+                "resetCarrierKeysForImsiEncryption",
                 (phone)-> {
                     phone.resetCarrierKeysForImsiEncryption();
                     return null;
                 });
     }
 
-
-    public String getDeviceSvn(String callingPackage) {
-        return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage);
+    public String getDeviceSvn(String callingPackage, String callingFeatureId) {
+        return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage, callingFeatureId);
     }
 
-    public String getDeviceSvnUsingSubId(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getDeviceSvn",
-                (phone)-> phone.getDeviceSvn());
+    public String getDeviceSvnUsingSubId(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
+                "getDeviceSvn", (phone)-> phone.getDeviceSvn());
     }
 
+    @Deprecated
     public String getSubscriberId(String callingPackage) {
-        return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage);
+        return getSubscriberIdWithFeature(callingPackage, null);
     }
 
-    public String getSubscriberIdForSubscriber(int subId, String callingPackage) {
+    public String getSubscriberIdWithFeature(String callingPackage, String callingFeatureId) {
+        return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
+    }
+
+    public String getSubscriberIdForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
         String message = "getSubscriberId";
         long identity = Binder.clearCallingIdentity();
         boolean isActive;
         try {
-            isActive = SubscriptionController.getInstance().isActiveSubId(subId, callingPackage);
+            isActive = SubscriptionController.getInstance().isActiveSubId(subId, callingPackage,
+                    callingFeatureId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
         if (isActive) {
             return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
-                    message, (phone) -> phone.getSubscriberId());
+                    callingFeatureId, message, (phone) -> phone.getSubscriberId());
         } else {
             if (!TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
-                    mContext, subId, callingPackage, message)) {
+                    mContext, subId, callingPackage, callingFeatureId, message)) {
                 return null;
             }
             identity = Binder.clearCallingIdentity();
@@ -150,52 +164,66 @@
         }
     }
 
+    @Deprecated
+    public String getIccSerialNumber(String callingPackage) {
+        return getIccSerialNumberWithFeature(callingPackage, null);
+    }
+
     /**
      * Retrieves the serial number of the ICC, if applicable.
      */
-    public String getIccSerialNumber(String callingPackage) {
-        return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId) {
+        return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
     }
 
-    public String getIccSerialNumberForSubscriber(int subId, String callingPackage) {
+    public String getIccSerialNumberForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
         return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
-                "getIccSerialNumber", (phone) -> phone.getIccSerialNumber());
+                callingFeatureId, "getIccSerialNumber", (phone) -> phone.getIccSerialNumber());
     }
 
-    public String getLine1Number(String callingPackage) {
-        return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getLine1Number(String callingPackage, String callingFeatureId) {
+        return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
     }
 
-    public String getLine1NumberForSubscriber(int subId, String callingPackage) {
+    public String getLine1NumberForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
         return callPhoneMethodForSubIdWithReadPhoneNumberCheck(
-                subId, callingPackage, "getLine1Number",
+                subId, callingPackage, callingFeatureId, "getLine1Number",
                 (phone)-> phone.getLine1Number());
     }
 
-    public String getLine1AlphaTag(String callingPackage) {
-        return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getLine1AlphaTag(String callingPackage, String callingFeatureId) {
+        return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
     }
 
-    public String getLine1AlphaTagForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getLine1AlphaTag",
-                (phone)-> phone.getLine1AlphaTag());
+    public String getLine1AlphaTagForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
+                "getLine1AlphaTag", (phone)-> phone.getLine1AlphaTag());
     }
 
-    public String getMsisdn(String callingPackage) {
-        return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getMsisdn(String callingPackage, String callingFeatureId) {
+        return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage, callingFeatureId);
     }
 
-    public String getMsisdnForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getMsisdn",
-                (phone)-> phone.getMsisdn());
+    public String getMsisdnForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
+                "getMsisdn", (phone)-> phone.getMsisdn());
     }
 
-    public String getVoiceMailNumber(String callingPackage) {
-        return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getVoiceMailNumber(String callingPackage, String callingFeatureId) {
+        return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
     }
 
-    public String getVoiceMailNumberForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+    public String getVoiceMailNumberForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
                 "getVoiceMailNumber", (phone)-> {
                     String number = PhoneNumberUtils.extractNetworkPortion(
                             phone.getVoiceMailNumber());
@@ -204,12 +232,14 @@
                 });
     }
 
-    public String getVoiceMailAlphaTag(String callingPackage) {
-        return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage);
+    public String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId) {
+        return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage,
+                callingFeatureId);
     }
 
-    public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+    public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
                 "getVoiceMailAlphaTag", (phone)-> phone.getVoiceMailAlphaTag());
     }
 
@@ -222,7 +252,7 @@
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
             phoneId = 0;
         }
-        return mPhone[phoneId];
+        return PhoneFactory.getPhone(phoneId);
     }
 
     /**
@@ -240,7 +270,7 @@
             return;
         }
         if (VDBG) log("No read privileged phone permission, check carrier privilege next.");
-        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, message);
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, message);
     }
 
     /**
@@ -357,16 +387,17 @@
             return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data);
         };
 
-        return callPhoneMethodWithPermissionCheck(
-                subId, null, "getIccSimChallengeResponse", toExecute,
-                (aContext, aSubId, aCallingPackage, aMessage)-> {
+        return callPhoneMethodWithPermissionCheck(subId, null, null, "getIccSimChallengeResponse",
+                toExecute,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) -> {
                     enforcePrivilegedPermissionOrCarrierPrivilege(aSubId, aMessage);
                     return true;
                 });
     }
 
-    public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage) {
-        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+    public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
                 "getGroupIdLevel1", (phone)-> phone.getGroupIdLevel1());
     }
 
@@ -385,14 +416,17 @@
         // If passes, it should return true.
         // If permission is not granted, throws SecurityException.
         // If permission is revoked by AppOps, return false.
-        boolean checkPermission(Context context, int subId, String callingPackage, String message);
+        boolean checkPermission(Context context, int subId, String callingPackage,
+                @Nullable String callingFeatureId, String message);
     }
 
     // Base utility method that others use.
     private <T> T callPhoneMethodWithPermissionCheck(int subId, String callingPackage,
-            String message, CallPhoneMethodHelper<T> callMethodHelper,
+            @Nullable String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper,
             PermissionCheckHelper permissionCheckHelper) {
-        if (!permissionCheckHelper.checkPermission(mContext, subId, callingPackage, message)) {
+        if (!permissionCheckHelper.checkPermission(mContext, subId, callingPackage,
+                callingFeatureId, message)) {
             return null;
         }
 
@@ -411,34 +445,39 @@
     }
 
     private <T> T callPhoneMethodForSubIdWithReadCheck(int subId, String callingPackage,
-            String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)->
+            @Nullable String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper) {
+        return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
+                message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
                         TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                                aContext, aSubId, aCallingPackage, aMessage));
+                                aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
     }
 
     private <T> T callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(int subId,
-            String callingPackage, String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)->
+            String callingPackage, @Nullable String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper) {
+        return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
+                message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
                         TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(
-                                aContext, aSubId, aCallingPackage, aMessage));
+                                aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
     }
 
     private <T> T callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(int subId,
-            String callingPackage, String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)->
+            String callingPackage, @Nullable String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper) {
+        return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
+                message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
                         TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
-                                aContext, aSubId, aCallingPackage, aMessage));
+                                aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
     }
 
-
     private <T> T callPhoneMethodForSubIdWithPrivilegedCheck(
             int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)-> {
+        return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) -> {
                     mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
                     return true;
                 });
@@ -446,33 +485,36 @@
 
     private <T> T callPhoneMethodForSubIdWithModifyCheck(int subId, String callingPackage,
             String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)-> {
+        return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> {
                     enforceModifyPermission();
                     return true;
                 });
     }
 
     private <T> T callPhoneMethodForSubIdWithReadPhoneNumberCheck(int subId, String callingPackage,
-            String message, CallPhoneMethodHelper<T> callMethodHelper) {
-        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
-                (aContext, aSubId, aCallingPackage, aMessage)->
+            @NonNull String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper) {
+        return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
+                message, callMethodHelper,
+                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) ->
                         TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
-                                aContext, aSubId, aCallingPackage, aMessage));
+                                aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
     }
 
     private <T> T callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(int phoneId,
-            String callingPackage, String message, CallPhoneMethodHelper<T> callMethodHelper) {
+            String callingPackage, @Nullable String callingFeatureId, String message,
+            CallPhoneMethodHelper<T> callMethodHelper) {
         // Getting subId before doing permission check.
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
             phoneId = 0;
         }
-        final Phone phone = mPhone[phoneId];
+        final Phone phone = PhoneFactory.getPhone(phoneId);
         if (phone == null) {
             return null;
         }
         if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
-                phone.getSubId(), callingPackage, message)) {
+                phone.getSubId(), callingPackage, callingFeatureId, message)) {
             return null;
         }
 
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index cf64a8b..bdfd925 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -25,7 +25,9 @@
 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
 
-import android.annotation.UnsupportedAppUsage;
+import static java.util.Arrays.copyOf;
+
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -37,7 +39,7 @@
 import android.net.NetworkFactory;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
-import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
@@ -46,13 +48,12 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
 import android.telephony.data.ApnSetting;
 import android.util.LocalLog;
 
@@ -62,7 +63,9 @@
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
+import com.android.internal.telephony.util.HandlerExecutor;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -154,15 +157,10 @@
     private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
     private final RegistrantList mActivePhoneRegistrants;
     private final SubscriptionController mSubscriptionController;
-    private final int[] mPhoneSubscriptions;
-    private final CommandsInterface[] mCommandsInterfaces;
     private final Context mContext;
-    private final PhoneState[] mPhoneStates;
-    @UnsupportedAppUsage
-    private final int mNumPhones;
-    @UnsupportedAppUsage
-    private final Phone[] mPhones;
     private final LocalLog mLocalLog;
+    private PhoneState[] mPhoneStates;
+    private int[] mPhoneSubscriptions;
     @VisibleForTesting
     public final PhoneStateListener mPhoneStateListener;
     private final CellularNetworkValidator mValidator;
@@ -170,8 +168,14 @@
     public final CellularNetworkValidator.ValidationCallback mValidationCallback =
             (validated, subId) -> Message.obtain(PhoneSwitcher.this,
                     EVENT_NETWORK_VALIDATION_DONE, subId, validated ? 1 : 0).sendToTarget();
+
     @UnsupportedAppUsage
-    private int mMaxActivePhones;
+    // How many phones (correspondingly logical modems) are allowed for PS attach. This is used
+    // when we specifically use setDataAllowed to initiate on-demand PS(data) attach for each phone.
+    private int mMaxDataAttachModemCount;
+    // Local cache of TelephonyManager#getActiveModemCount(). 1 if in single SIM mode, 2 if in dual
+    // SIM mode.
+    private int mActiveModemCount;
     private static PhoneSwitcher sPhoneSwitcher = null;
 
     // Which primary (non-opportunistic) subscription is set as data subscription among all primary
@@ -237,6 +241,9 @@
     private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY     = 115;
     // If it exists, remove the current mEmergencyOverride DDS override.
     private static final int EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE  = 116;
+    // If it exists, remove the current mEmergencyOverride DDS override.
+    @VisibleForTesting
+    public static final int EVENT_MULTI_SIM_CONFIG_CHANGED        = 117;
 
     // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's
     // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse
@@ -288,47 +295,21 @@
     /**
      * Method to create singleton instance.
      */
-    public static PhoneSwitcher make(int maxActivePhones, int numPhones, Context context,
-            SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
-            CommandsInterface[] cis, Phone[] phones) {
+    public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper) {
         if (sPhoneSwitcher == null) {
-            sPhoneSwitcher = new PhoneSwitcher(maxActivePhones, numPhones, context,
-                    subscriptionController, looper, tr, cis, phones);
+            sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper);
         }
 
         return sPhoneSwitcher;
     }
 
-    /** This constructor is only used for testing purpose. */
-    @VisibleForTesting
-    public PhoneSwitcher(int numPhones, Looper looper) {
-        super(looper);
-        mMaxActivePhones = 0;
-        mSubscriptionController = null;
-        mCommandsInterfaces = null;
-        mContext = null;
-        mPhoneStates = null;
-        mPhones = null;
-        mLocalLog = null;
-        mActivePhoneRegistrants = null;
-        mNumPhones = numPhones;
-        mPhoneSubscriptions = new int[numPhones];
-        mRadioConfig = RadioConfig.getInstance(mContext);
-        mPhoneStateListener = new PhoneStateListener(looper) {
-            public void onPhoneCapabilityChanged(PhoneCapability capability) {
-                onPhoneCapabilityChangedInternal(capability);
-            }
-        };
-        mValidator = CellularNetworkValidator.getInstance();
-    }
-
     private boolean isPhoneInVoiceCallChanged() {
         int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
         // If there's no active call, the value will become INVALID_PHONE_INDEX
         // and internet data will be switched back to system selected or user selected
         // subscription.
         mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
-        for (Phone phone : mPhones) {
+        for (Phone phone : PhoneFactory.getPhones()) {
             if (isPhoneInVoiceCall(phone) || isPhoneInVoiceCall(phone.getImsPhone())) {
                 mPhoneIdInVoiceCall = phone.getPhoneId();
                 break;
@@ -345,21 +326,19 @@
     }
 
     @VisibleForTesting
-    public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
-            SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
-            CommandsInterface[] cis, Phone[] phones) {
+    public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) {
         super(looper);
         mContext = context;
-        mNumPhones = numPhones;
-        mPhones = phones;
-        mPhoneSubscriptions = new int[numPhones];
-        mMaxActivePhones = maxActivePhones;
+        mActiveModemCount = getTm().getActiveModemCount();
+        mPhoneSubscriptions = new int[mActiveModemCount];
+        mPhoneStates = new PhoneState[mActiveModemCount];
+        mMaxDataAttachModemCount = maxActivePhones;
         mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES);
 
-        mSubscriptionController = subscriptionController;
+        mSubscriptionController = SubscriptionController.getInstance();
         mRadioConfig = RadioConfig.getInstance(mContext);
 
-        mPhoneStateListener = new PhoneStateListener(looper) {
+        mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(this)) {
             @Override
             public void onPhoneCapabilityChanged(PhoneCapability capability) {
                 onPhoneCapabilityChangedInternal(capability);
@@ -369,34 +348,31 @@
         mValidator = CellularNetworkValidator.getInstance();
 
         mActivePhoneRegistrants = new RegistrantList();
-        mPhoneStates = new PhoneState[numPhones];
-        for (int i = 0; i < numPhones; i++) {
+        for (int i = 0; i < mActiveModemCount; i++) {
             mPhoneStates[i] = new PhoneState();
-            if (mPhones[i] != null) {
-                mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
+            if (PhoneFactory.getPhone(i) != null) {
+                PhoneFactory.getPhone(i).registerForEmergencyCallToggle(
+                        this, EVENT_EMERGENCY_TOGGLE, null);
                 // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
-                mPhones[i].registerForPreciseCallStateChanged(
+                PhoneFactory.getPhone(i).registerForPreciseCallStateChanged(
                         this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
-                if (mPhones[i].getImsPhone() != null) {
-                    mPhones[i].getImsPhone().registerForPreciseCallStateChanged(
+                if (PhoneFactory.getPhone(i).getImsPhone() != null) {
+                    PhoneFactory.getPhone(i).getImsPhone().registerForPreciseCallStateChanged(
                             this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
                 }
-                mPhones[i].getDataEnabledSettings().registerForDataEnabledChanged(
+                PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged(
                         this, EVENT_DATA_ENABLED_CHANGED, null);
             }
         }
 
-        mCommandsInterfaces = cis;
-
-        if (numPhones > 0) {
-            mCommandsInterfaces[0].registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
+        if (mActiveModemCount > 0) {
+            PhoneFactory.getPhone(0).mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         }
 
-        try {
-            tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
-                    mSubscriptionsChangedListener);
-        } catch (RemoteException e) {
-        }
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        telephonyRegistryManager.addOnSubscriptionsChangedListener(
+                mSubscriptionsChangedListener, mSubscriptionsChangedListener.getHandlerExecutor());
 
         mConnectivityManager =
             (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -404,6 +380,9 @@
         mContext.registerReceiver(mDefaultDataChangedReceiver,
                 new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
 
+        PhoneConfigurationManager.registerForMultiSimConfigChange(
+                this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
+
         NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addTransportType(TRANSPORT_CELLULAR);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
@@ -438,8 +417,8 @@
         }
     };
 
-    private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
-            new IOnSubscriptionsChangedListener.Stub() {
+    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
+            new SubscriptionManager.OnSubscriptionsChangedListener() {
         @Override
         public void onSubscriptionsChanged() {
             Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED);
@@ -619,11 +598,43 @@
                 onEvaluate(REQUESTS_UNCHANGED, "emer_rm_override_dds");
                 break;
             }
+            case EVENT_MULTI_SIM_CONFIG_CHANGED: {
+                int activeModemCount = (int) ((AsyncResult) msg.obj).result;
+                onMultiSimConfigChanged(activeModemCount);
+                break;
+            }
+        }
+    }
+
+    private synchronized void onMultiSimConfigChanged(int activeModemCount) {
+        // No change.
+        if (mActiveModemCount == activeModemCount) return;
+        int oldActiveModemCount = mActiveModemCount;
+        mActiveModemCount = activeModemCount;
+
+        mPhoneSubscriptions = copyOf(mPhoneSubscriptions, mActiveModemCount);
+        mPhoneStates = copyOf(mPhoneStates, mActiveModemCount);
+
+        // Single SIM -> dual SIM switch.
+        for (int phoneId = oldActiveModemCount; phoneId < mActiveModemCount; phoneId++) {
+            mPhoneStates[phoneId] = new PhoneState();
+            Phone phone = PhoneFactory.getPhone(phoneId);
+            if (phone == null) continue;
+
+            phone.registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
+            // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
+            phone.registerForPreciseCallStateChanged(this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+            if (phone.getImsPhone() != null) {
+                phone.getImsPhone().registerForPreciseCallStateChanged(
+                        this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+            }
+            phone.getDataEnabledSettings().registerForDataEnabledChanged(
+                    this, EVENT_DATA_ENABLED_CHANGED, null);
         }
     }
 
     private boolean isInEmergencyCallbackMode() {
-        for (Phone p : mPhones) {
+        for (Phone p : PhoneFactory.getPhones()) {
             if (p == null) continue;
             if (p.isInEcm()) return true;
             Phone imsPhone = p.getImsPhone();
@@ -698,7 +709,7 @@
     private void collectRequestNetworkMetrics(NetworkRequest networkRequest) {
         // Request network for MMS will temporary disable the network on default data subscription,
         // this only happen on multi-sim device.
-        if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+        if (mActiveModemCount > 1 && networkRequest.networkCapabilities.hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_MMS)) {
             OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
             onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
@@ -710,7 +721,7 @@
     private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
         // Release network for MMS will recover the network on default data subscription, this only
         // happen on multi-sim device.
-        if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+        if (mActiveModemCount > 1 && networkRequest.networkCapabilities.hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_MMS)) {
             OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
             onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
@@ -719,6 +730,10 @@
         }
     }
 
+    private TelephonyManager getTm() {
+        return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
     private static final boolean REQUESTS_CHANGED   = true;
     private static final boolean REQUESTS_UNCHANGED = false;
     /**
@@ -748,7 +763,7 @@
         boolean hasAnyActiveSubscription = false;
 
         // Check if phoneId to subId mapping is changed.
-        for (int i = 0; i < mNumPhones; i++) {
+        for (int i = 0; i < mActiveModemCount; i++) {
             int sub = mSubscriptionController.getSubIdUsingPhoneId(i);
 
             if (SubscriptionManager.isValidSubscriptionId(sub)) hasAnyActiveSubscription = true;
@@ -789,7 +804,7 @@
                 // With HAL_COMMAND_PREFERRED_DATA, all phones are assumed to allow PS attach.
                 // So marking all phone as active, and the phone with mPreferredDataPhoneId
                 // will send radioConfig command.
-                for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
+                for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) {
                     mPhoneStates[phoneId].active = true;
                 }
                 sendRilCommands(mPreferredDataPhoneId);
@@ -801,9 +816,9 @@
                  * Otherwise, choose to activate phones according to requests. And
                  * if list is not full, add mPreferredDataPhoneId.
                  */
-                if (mMaxActivePhones == mPhones.length) {
-                    for (int i = 0; i < mMaxActivePhones; i++) {
-                        newActivePhones.add(mPhones[i].getPhoneId());
+                if (mMaxDataAttachModemCount == mActiveModemCount) {
+                    for (int i = 0; i < mMaxDataAttachModemCount; i++) {
+                        newActivePhones.add(i);
                     }
                 } else {
                     // First try to activate phone in voice call.
@@ -811,17 +826,17 @@
                         newActivePhones.add(mPhoneIdInVoiceCall);
                     }
 
-                    if (newActivePhones.size() < mMaxActivePhones) {
+                    if (newActivePhones.size() < mMaxDataAttachModemCount) {
                         for (DcRequest dcRequest : mPrioritizedDcRequests) {
                             int phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest);
                             if (phoneIdForRequest == INVALID_PHONE_INDEX) continue;
                             if (newActivePhones.contains(phoneIdForRequest)) continue;
                             newActivePhones.add(phoneIdForRequest);
-                            if (newActivePhones.size() >= mMaxActivePhones) break;
+                            if (newActivePhones.size() >= mMaxDataAttachModemCount) break;
                         }
                     }
 
-                    if (newActivePhones.size() < mMaxActivePhones
+                    if (newActivePhones.size() < mMaxDataAttachModemCount
                             && newActivePhones.contains(mPreferredDataPhoneId)
                             && SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) {
                         newActivePhones.add(mPreferredDataPhoneId);
@@ -831,14 +846,14 @@
                 if (VDBG) {
                     log("mPrimaryDataSubId = " + mPrimaryDataSubId);
                     log("mOpptDataSubId = " + mOpptDataSubId);
-                    for (int i = 0; i < mNumPhones; i++) {
+                    for (int i = 0; i < mActiveModemCount; i++) {
                         log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]");
                     }
                     log(" newActivePhones:");
                     for (Integer i : newActivePhones) log("  " + i);
                 }
 
-                for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
+                for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) {
                     if (!newActivePhones.contains(phoneId)) {
                         deactivate(phoneId);
                     }
@@ -887,7 +902,7 @@
      * want to resend setDataAllowed or setPreferredDataSubscriptionId
      */
     public void onRadioCapChanged(int phoneId) {
-        validatePhoneId(phoneId);
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
         Message msg = obtainMessage(EVENT_RADIO_CAPABILITY_CHANGED);
         msg.arg1 = phoneId;
         msg.sendToTarget();
@@ -912,7 +927,7 @@
      */
     public void overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec,
             CompletableFuture<Boolean> dataSwitchResult) {
-        validatePhoneId(phoneId);
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
         Message msg = obtainMessage(EVENT_OVERRIDE_DDS_FOR_EMERGENCY);
         EmergencyOverrideRequest request  = new EmergencyOverrideRequest();
         request.mPhoneId = phoneId;
@@ -923,13 +938,13 @@
     }
 
     private void sendRilCommands(int phoneId) {
-        if (!SubscriptionManager.isValidPhoneId(phoneId) || phoneId >= mNumPhones) return;
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
 
         Message message = Message.obtain(this, EVENT_MODEM_COMMAND_DONE, phoneId);
         if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
             // Skip ALLOW_DATA for single SIM device
-            if (mNumPhones > 1) {
-                mCommandsInterfaces[phoneId].setDataAllowed(isPhoneActive(phoneId), message);
+            if (mActiveModemCount > 1) {
+                PhoneFactory.getPhone(phoneId).mCi.setDataAllowed(isPhoneActive(phoneId), message);
             }
         } else if (phoneId == mPreferredDataPhoneId) {
             // Only setPreferredDataModem if the phoneId equals to current mPreferredDataPhoneId.
@@ -938,23 +953,23 @@
     }
 
     private void onPhoneCapabilityChangedInternal(PhoneCapability capability) {
-        int newMaxActivePhones = TelephonyManager.getDefault()
+        int newMaxDataAttachModemCount = TelephonyManager.getDefault()
                 .getNumberOfModemsWithSimultaneousDataConnections();
-        if (mMaxActivePhones != newMaxActivePhones) {
-            mMaxActivePhones = newMaxActivePhones;
-            log("Max active phones changed to " + mMaxActivePhones);
+        if (mMaxDataAttachModemCount != newMaxDataAttachModemCount) {
+            mMaxDataAttachModemCount = newMaxDataAttachModemCount;
+            log("Max active phones changed to " + mMaxDataAttachModemCount);
             onEvaluate(REQUESTS_UNCHANGED, "phoneCfgChanged");
         }
     }
 
     private int phoneIdForRequest(NetworkRequest netRequest) {
-        int subId = getSubIdFromNetworkSpecifier(netRequest.networkCapabilities
-                .getNetworkSpecifier());
+        int subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier());
 
         if (subId == DEFAULT_SUBSCRIPTION_ID) return mPreferredDataPhoneId;
         if (subId == INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX;
 
-        int preferredDataSubId = SubscriptionManager.isValidPhoneId(mPreferredDataPhoneId)
+        int preferredDataSubId = (mPreferredDataPhoneId >= 0
+                && mPreferredDataPhoneId < mActiveModemCount)
                 ? mPhoneSubscriptions[mPreferredDataPhoneId] : INVALID_SUBSCRIPTION_ID;
 
         // Currently we assume multi-SIM devices will only support one Internet PDN connection. So
@@ -972,7 +987,7 @@
 
         // Try to find matching phone ID. If it doesn't exist, we'll end up returning INVALID.
         int phoneId = INVALID_PHONE_INDEX;
-        for (int i = 0; i < mNumPhones; i++) {
+        for (int i = 0; i < mActiveModemCount; i++) {
             if (mPhoneSubscriptions[i] == subId) {
                 phoneId = i;
                 break;
@@ -985,22 +1000,10 @@
         if (specifier == null) {
             return DEFAULT_SUBSCRIPTION_ID;
         }
-
-        int subId;
-
-        if (specifier instanceof StringNetworkSpecifier) {
-            try {
-                subId = Integer.parseInt(((StringNetworkSpecifier) specifier).specifier);
-            } catch (NumberFormatException e) {
-                Rlog.e(LOG_TAG, "NumberFormatException on "
-                        + ((StringNetworkSpecifier) specifier).specifier);
-                return INVALID_SUBSCRIPTION_ID;
-            }
-        } else {
-            return INVALID_SUBSCRIPTION_ID;
+        if (specifier instanceof TelephonyNetworkSpecifier) {
+            return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
         }
-
-        return subId;
+        return INVALID_SUBSCRIPTION_ID;
     }
 
     private int getSubIdForDefaultNetworkRequests() {
@@ -1035,7 +1038,7 @@
             int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
 
             if (SubscriptionManager.isUsableSubIdValue(subId)) {
-                for (int i = 0; i < mNumPhones; i++) {
+                for (int i = 0; i < mActiveModemCount; i++) {
                     if (mPhoneSubscriptions[i] == subId) {
                         phoneId = i;
                         break;
@@ -1050,7 +1053,7 @@
     }
 
     private void transitionToEmergencyPhone() {
-        if (mNumPhones <= 0) {
+        if (mActiveModemCount <= 0) {
             log("No phones: unable to reset preferred phone for emergency");
             return;
         }
@@ -1067,14 +1070,15 @@
     }
 
     private Phone findPhoneById(final int phoneId) {
-        if (phoneId < 0 || phoneId >= mNumPhones) {
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
             return null;
         }
-        return mPhones[phoneId];
+        return PhoneFactory.getPhone(phoneId);
     }
 
-    public boolean shouldApplyNetworkRequest(NetworkRequest networkRequest, int phoneId) {
-        validatePhoneId(phoneId);
+    public synchronized boolean shouldApplyNetworkRequest(
+            NetworkRequest networkRequest, int phoneId) {
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) return false;
 
         // In any case, if phone state is inactive, don't apply the network request.
         if (!isPhoneActive(phoneId) || (
@@ -1094,6 +1098,8 @@
 
     @VisibleForTesting
     protected boolean isPhoneActive(int phoneId) {
+        if (phoneId >= mActiveModemCount)
+            return false;
         return mPhoneStates[phoneId].active;
     }
 
@@ -1111,13 +1117,6 @@
         mActivePhoneRegistrants.remove(h);
     }
 
-    @VisibleForTesting
-    protected void validatePhoneId(int phoneId) {
-        if (phoneId < 0 || phoneId >= mNumPhones) {
-            throw new IllegalArgumentException("Invalid PhoneId");
-        }
-    }
-
     /**
      * Set opportunistic data subscription. It's an indication to switch Internet data to this
      * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
@@ -1301,14 +1300,10 @@
      * See {@link PhoneStateListener#LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE}.
      */
     private void notifyPreferredDataSubIdChanged() {
-        ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                "telephony.registry"));
-        try {
-            log("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId);
-            tr.notifyActiveDataSubIdChanged(mPreferredDataSubId);
-        } catch (RemoteException ex) {
-            // Should never happen because its always available.
-        }
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) mContext
+                .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        log("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId);
+        telephonyRegistryManager.notifyActiveDataSubIdChanged(mPreferredDataSubId);
     }
 
     /**
@@ -1322,7 +1317,7 @@
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println("PhoneSwitcher:");
         Calendar c = Calendar.getInstance();
-        for (int i = 0; i < mNumPhones; i++) {
+        for (int i = 0; i < mActiveModemCount; i++) {
             PhoneState ps = mPhoneStates[i];
             c.setTimeInMillis(ps.lastRequested);
             pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" +
diff --git a/src/java/com/android/internal/telephony/ProxyController.java b/src/java/com/android/internal/telephony/ProxyController.java
index 54fcac9..d6ed87b 100644
--- a/src/java/com/android/internal/telephony/ProxyController.java
+++ b/src/java/com/android/internal/telephony/ProxyController.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import static java.util.Arrays.copyOf;
+
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.AsyncResult;
@@ -25,12 +27,12 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.telephony.RadioAccessFamily;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
-import com.android.internal.telephony.ims.RcsMessageController;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -40,11 +42,13 @@
 public class ProxyController {
     static final String LOG_TAG = "ProxyController";
 
-    private static final int EVENT_NOTIFICATION_RC_CHANGED        = 1;
+    private static final int EVENT_NOTIFICATION_RC_CHANGED  = 1;
     private static final int EVENT_START_RC_RESPONSE        = 2;
     private static final int EVENT_APPLY_RC_RESPONSE        = 3;
     private static final int EVENT_FINISH_RC_RESPONSE       = 4;
     private static final int EVENT_TIMEOUT                  = 5;
+    @VisibleForTesting
+    public static final int EVENT_MULTI_SIM_CONFIG_CHANGED  = 6;
 
     private static final int SET_RC_STATUS_IDLE             = 0;
     private static final int SET_RC_STATUS_STARTING         = 1;
@@ -105,9 +109,9 @@
 
 
     //***** Class Methods
-    public static ProxyController getInstance(Context context, Phone[] phone, PhoneSwitcher ps) {
+    public static ProxyController getInstance(Context context) {
         if (sProxyController == null) {
-            sProxyController = new ProxyController(context, phone, ps);
+            sProxyController = new ProxyController(context);
         }
         return sProxyController;
     }
@@ -117,17 +121,15 @@
         return sProxyController;
     }
 
-    private ProxyController(Context context, Phone[] phone, PhoneSwitcher phoneSwitcher) {
+    private ProxyController(Context context) {
         logd("Constructor - Enter");
 
         mContext = context;
-        mPhones = phone;
-        mPhoneSwitcher = phoneSwitcher;
+        mPhones = PhoneFactory.getPhones();
+        mPhoneSwitcher = PhoneSwitcher.getInstance();
 
-        RcsMessageController.init(context);
-
-        mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
-        mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);
+        mUiccPhoneBookController = new UiccPhoneBookController();
+        mPhoneSubInfoController = new PhoneSubInfoController(mContext);
         mSmsController = new SmsController(mContext);
         mSetRadioAccessFamilyStatus = new int[mPhones.length];
         mNewRadioAccessFamily = new int[mPhones.length];
@@ -146,6 +148,9 @@
             mPhones[i].registerForRadioCapabilityChanged(
                     mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
         }
+
+        PhoneConfigurationManager.registerForMultiSimConfigChange(
+                mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
         logd("Constructor - Exit");
     }
 
@@ -201,7 +206,7 @@
      */
     public boolean setRadioCapability(RadioAccessFamily[] rafs) {
         if (rafs.length != mPhones.length) {
-            throw new RuntimeException("Length of input rafs must equal to total phone count");
+            return false;
         }
         // Check if there is any ongoing transaction and throw an exception if there
         // is one as this is a programming error.
@@ -291,7 +296,8 @@
         return true;
     }
 
-    private Handler mHandler = new Handler() {
+    @VisibleForTesting
+    public final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             logd("handleMessage msg.what=" + msg.what);
@@ -316,12 +322,37 @@
                     onTimeoutRadioCapability(msg);
                     break;
 
+                case EVENT_MULTI_SIM_CONFIG_CHANGED:
+                    onMultiSimConfigChanged();
+                    break;
+
                 default:
                     break;
             }
         }
     };
 
+    private void onMultiSimConfigChanged() {
+        int oldPhoneCount = mPhones.length;
+        mPhones = PhoneFactory.getPhones();
+
+        // Re-size arrays.
+        mSetRadioAccessFamilyStatus = copyOf(mSetRadioAccessFamilyStatus, mPhones.length);
+        mNewRadioAccessFamily = copyOf(mNewRadioAccessFamily, mPhones.length);
+        mOldRadioAccessFamily = copyOf(mOldRadioAccessFamily, mPhones.length);
+        mCurrentLogicalModemIds = copyOf(mCurrentLogicalModemIds, mPhones.length);
+        mNewLogicalModemIds = copyOf(mNewLogicalModemIds, mPhones.length);
+
+        // Clear to be sure we're in the initial state
+        clearTransaction();
+
+        // Register radio cap change for new phones.
+        for (int i = oldPhoneCount; i < mPhones.length; i++) {
+            mPhones[i].registerForRadioCapabilityChanged(
+                    mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
+        }
+    }
+
     /**
      * Handle START response
      * @param msg obj field isa RadioCapability
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 4d7a687..b812432 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -19,7 +19,7 @@
 import static com.android.internal.telephony.RILConstants.*;
 import static com.android.internal.util.Preconditions.checkNotNull;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.radio.V1_0.Carrier;
 import android.hardware.radio.V1_0.CarrierRestrictions;
@@ -48,17 +48,16 @@
 import android.hardware.radio.V1_0.SimApdu;
 import android.hardware.radio.V1_0.SmsWriteArgs;
 import android.hardware.radio.V1_0.UusInfo;
-import android.hardware.radio.V1_2.AccessNetwork;
 import android.hardware.radio.V1_4.CarrierRestrictionsWithPriority;
 import android.hardware.radio.V1_4.SimLockMultiSimPolicy;
+import android.hardware.radio.V1_5.AccessNetwork;
+import android.hardware.radio.V1_5.RadioAccessNetworks;
 import android.hardware.radio.deprecated.V1_0.IOemHook;
-import android.net.ConnectivityManager;
+import android.net.InetAddresses;
 import android.net.KeepalivePacketData;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.NetworkUtils;
 import android.os.AsyncResult;
-import android.os.Build;
 import android.os.Handler;
 import android.os.HwBinder;
 import android.os.Message;
@@ -66,10 +65,10 @@
 import android.os.PowerManager.WakeLock;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.service.carrier.CarrierIdentifier;
+import android.sysprop.TelephonyProperties;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CarrierRestrictionRules;
 import android.telephony.CellInfo;
@@ -87,10 +86,11 @@
 import android.telephony.PhoneNumberUtils;
 import android.telephony.RadioAccessFamily;
 import android.telephony.RadioAccessSpecifier;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyHistogram;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.PrefNetworkMode;
@@ -112,6 +112,8 @@
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.nano.TelephonyProto.SmsSession;
 import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
@@ -129,6 +131,7 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
 
 /**
  * RIL implementation of the CommandsInterface.
@@ -179,6 +182,9 @@
     /** @hide */
     public static final HalVersion RADIO_HAL_VERSION_1_4 = new HalVersion(1, 4);
 
+    /** @hide */
+    public static final HalVersion RADIO_HAL_VERSION_1_5 = new HalVersion(1, 5);
+
     // IRadio version
     private HalVersion mRadioVersion = RADIO_HAL_VERSION_UNKNOWN;
 
@@ -233,7 +239,7 @@
     /** Radio bug detector instance */
     private RadioBugDetector mRadioBugDetector = null;
 
-    boolean mIsMobileNetworkSupported;
+    boolean mIsCellularSupported;
     RadioResponse mRadioResponse;
     RadioIndication mRadioIndication;
     volatile IRadio mRadioProxy = null;
@@ -378,7 +384,7 @@
         switch(rr.mRequest) {
             case RIL_REQUEST_GET_ACTIVITY_INFO:
                 timeoutResponse = new ModemActivityInfo(
-                        0, 0, 0, new int [ModemActivityInfo.TX_POWER_LEVELS], 0, 0);
+                        0, 0, 0, new int [ModemActivityInfo.TX_POWER_LEVELS], 0);
                 break;
         };
         return timeoutResponse;
@@ -413,8 +419,8 @@
     /** Returns a {@link IRadio} instance or null if the service is not available. */
     @VisibleForTesting
     public synchronized IRadio getRadioProxy(Message result) {
-        if (!PhoneConfigurationManager.isPhoneActive(mPhoneId)) return null;
-        if (!mIsMobileNetworkSupported) {
+        if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return null;
+        if (!mIsCellularSupported) {
             if (RILJ_LOGV) riljLog("getRadioProxy: Not calling getService(): wifi-only");
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -434,14 +440,23 @@
                         + " is disabled");
             } else {
                 try {
-                    mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
+                    mRadioProxy = android.hardware.radio.V1_5.IRadio.getService(
                             HIDL_SERVICE_NAME[mPhoneId], true);
-                    mRadioVersion = RADIO_HAL_VERSION_1_4;
+                    mRadioVersion = RADIO_HAL_VERSION_1_5;
                 } catch (NoSuchElementException e) {
                 }
 
                 if (mRadioProxy == null) {
                     try {
+                        mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
+                                HIDL_SERVICE_NAME[mPhoneId], true);
+                        mRadioVersion = RADIO_HAL_VERSION_1_4;
+                    } catch (NoSuchElementException e) {
+                    }
+                }
+
+                if (mRadioProxy == null) {
+                    try {
                         mRadioProxy = android.hardware.radio.V1_3.IRadio.getService(
                                 HIDL_SERVICE_NAME[mPhoneId], true);
                         mRadioVersion = RADIO_HAL_VERSION_1_3;
@@ -510,14 +525,16 @@
             // Try to connect to RIL services and set response functions.
             getRadioProxy(null);
             getOemHookProxy(null);
+        } else {
+            resetProxyAndRequestList();
         }
     }
 
     /** Returns an {@link IOemHook} instance or null if the service is not available. */
     @VisibleForTesting
     public synchronized IOemHook getOemHookProxy(Message result) {
-        if (!PhoneConfigurationManager.isPhoneActive(mPhoneId)) return null;
-        if (!mIsMobileNetworkSupported) {
+        if (!SubscriptionManager.isValidPhoneId((mPhoneId))) return null;
+        if (!mIsCellularSupported) {
             if (RILJ_LOGV) riljLog("getOemHookProxy: Not calling getService(): wifi-only");
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -591,9 +608,9 @@
             mRadioBugDetector = new RadioBugDetector(context, mPhoneId);
         }
 
-        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
-                Context.CONNECTIVITY_SERVICE);
-        mIsMobileNetworkSupported = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        mIsCellularSupported = tm.isVoiceCapable() || tm.isSmsCapable() || tm.isDataCapable();
 
         mRadioResponse = new RadioResponse(this);
         mRadioIndication = new RadioIndication(this);
@@ -607,10 +624,10 @@
         mWakeLock.setReferenceCounted(false);
         mAckWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RILJ_ACK_WAKELOCK_NAME);
         mAckWakeLock.setReferenceCounted(false);
-        mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT,
-                DEFAULT_WAKE_LOCK_TIMEOUT_MS);
-        mAckWakeLockTimeout = SystemProperties.getInt(
-                TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT, DEFAULT_ACK_WAKE_LOCK_TIMEOUT_MS);
+        mWakeLockTimeout = TelephonyProperties.wake_lock_timeout()
+                .orElse(DEFAULT_WAKE_LOCK_TIMEOUT_MS);
+        mAckWakeLockTimeout = TelephonyProperties.wake_lock_timeout()
+                .orElse(DEFAULT_ACK_WAKE_LOCK_TIMEOUT_MS);
         mWakeLockCount = 0;
         mRILDefaultWorkSource = new WorkSource(context.getApplicationInfo().uid,
                 context.getPackageName());
@@ -1423,7 +1440,7 @@
         // ServiceState.RIL_RADIO_TECHNOLOGY_XXXX.
         dpi.bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
                 dp.getBearerBitmask()) << 1;
-        dpi.mtu = dp.getMtu();
+        dpi.mtu = dp.getMtuV4();
         dpi.mvnoType = MvnoType.NONE;
         dpi.mvnoMatchData = "";
 
@@ -1457,7 +1474,45 @@
         // ServiceState.RIL_RADIO_TECHNOLOGY_XXXX.
         dpi.bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
                 dp.getBearerBitmask()) << 1;
-        dpi.mtu = dp.getMtu();
+        dpi.mtu = dp.getMtuV4();
+        dpi.persistent = dp.isPersistent();
+        dpi.preferred = dp.isPreferred();
+
+        // profile id is only meaningful when it's persistent on the modem.
+        dpi.profileId = (dpi.persistent) ? dp.getProfileId() : DataProfileId.INVALID;
+
+        return dpi;
+    }
+
+    /**
+     * Convert to DataProfileInfo defined in radio/1.5/types.hal
+     * @param dp Data profile
+     * @return A converted data profile
+     */
+    private static android.hardware.radio.V1_5.DataProfileInfo convertToHalDataProfile15(
+            DataProfile dp) {
+        android.hardware.radio.V1_5.DataProfileInfo dpi =
+                new android.hardware.radio.V1_5.DataProfileInfo();
+
+        dpi.apn = dp.getApn();
+        dpi.protocol = dp.getProtocolType();
+        dpi.roamingProtocol = dp.getRoamingProtocolType();
+        dpi.authType = dp.getAuthType();
+        dpi.user = dp.getUserName();
+        dpi.password = dp.getPassword();
+        dpi.type = dp.getType();
+        dpi.maxConnsTime = dp.getMaxConnectionsTime();
+        dpi.maxConns = dp.getMaxConnections();
+        dpi.waitTime = dp.getWaitTime();
+        dpi.enabled = dp.isEnabled();
+        dpi.supportedApnTypesBitmap = dp.getSupportedApnTypesBitmask();
+        // Shift by 1 bit due to the discrepancy between
+        // android.hardware.radio.V1_0.RadioAccessFamily and the bitmask version of
+        // ServiceState.RIL_RADIO_TECHNOLOGY_XXXX.
+        dpi.bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+            dp.getBearerBitmask()) << 1;
+        dpi.mtuV4 = dp.getMtuV4();
+        dpi.mtuV6 = dp.getMtuV6();
         dpi.persistent = dp.isPersistent();
         dpi.preferred = dp.isPreferred();
 
@@ -1511,7 +1566,40 @@
             }
 
             try {
-                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
+                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                    // IRadio V1.5
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+
+                    // Convert to HAL data profile
+                    android.hardware.radio.V1_5.DataProfileInfo dpi =
+                            convertToHalDataProfile15(dataProfile);
+
+                    ArrayList<android.hardware.radio.V1_5.LinkAddress> addresses15 =
+                            new ArrayList<>();
+                    if (linkProperties != null) {
+                        for (LinkAddress la : linkProperties.getAllLinkAddresses()) {
+                            android.hardware.radio.V1_5.LinkAddress linkAddress =
+                                    new android.hardware.radio.V1_5.LinkAddress();
+                            linkAddress.address = la.getAddress().getHostAddress();
+                            linkAddress.properties = la.getFlags();
+                            linkAddress.deprecationTime = la.getDeprecationTime();
+                            linkAddress.expirationTime = la.getExpirationTime();
+                            addresses15.add(linkAddress);
+                        }
+                    }
+
+                    if (RILJ_LOGD) {
+                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                + ",accessNetworkType="
+                                + AccessNetworkType.toString(accessNetworkType) + ",isRoaming="
+                                + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile
+                                + ",addresses=" + addresses15 + ",dnses=" + dnses);
+                    }
+
+                    radioProxy15.setupDataCall_1_5(rr.mSerial, accessNetworkType, dpi, allowRoaming,
+                            reason, addresses15, dnses);
+                } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
                     // IRadio V1.4
                     android.hardware.radio.V1_4.IRadio radioProxy14 =
                             (android.hardware.radio.V1_4.IRadio) radioProxy;
@@ -1600,7 +1688,7 @@
                     mRILDefaultWorkSource);
 
             if (RILJ_LOGD) {
-                if (Build.IS_DEBUGGABLE) {
+                if (TelephonyUtils.IS_DEBUGGABLE) {
                     riljLog(rr.serialString() + "> iccIO: "
                             + requestToString(rr.mRequest) + " command = 0x"
                             + Integer.toHexString(command) + " fileId = 0x"
@@ -2004,20 +2092,31 @@
     }
 
     @Override
-    public void setNetworkSelectionModeManual(String operatorNumeric, Message result) {
+    public void setNetworkSelectionModeManual(String operatorNumeric, int ran, Message result) {
         IRadio radioProxy = getRadioProxy(result);
         if (radioProxy != null) {
             RILRequest rr = obtainRequest(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, result,
                     mRILDefaultWorkSource);
-
-            if (RILJ_LOGD) {
-                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                        + " operatorNumeric = " + operatorNumeric);
-            }
-
             try {
-                radioProxy.setNetworkSelectionModeManual(rr.mSerial,
-                        convertNullToEmptyString(operatorNumeric));
+                int accessNetwork = convertRanToAnt(ran);
+                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+                    if (RILJ_LOGD) {
+                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                + " operatorNumeric = " + operatorNumeric
+                                + ", ran = " + accessNetwork);
+                    }
+                    radioProxy15.setNetworkSelectionModeManual_1_5(rr.mSerial,
+                            convertNullToEmptyString(operatorNumeric), accessNetwork);
+                } else {
+                    if (RILJ_LOGD) {
+                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                + " operatorNumeric = " + operatorNumeric);
+                    }
+                    radioProxy.setNetworkSelectionModeManual(rr.mSerial,
+                            convertNullToEmptyString(operatorNumeric));
+                }
             } catch (RemoteException | RuntimeException e) {
                 handleRadioProxyExceptionForRR(rr, "setNetworkSelectionModeManual", e);
             }
@@ -2077,12 +2176,83 @@
         return rasInHalFormat;
     }
 
+    private android.hardware.radio.V1_5.RadioAccessSpecifier
+            convertRadioAccessSpecifierToRadioHAL_1_5(RadioAccessSpecifier ras) {
+        android.hardware.radio.V1_5.RadioAccessSpecifier rasInHalFormat =
+                new android.hardware.radio.V1_5.RadioAccessSpecifier();
+        rasInHalFormat.radioAccessNetwork = ras.getRadioAccessNetwork();
+        List<Integer> bands = null;
+        switch (ras.getRadioAccessNetwork()) {
+            case AccessNetworkType.GERAN:
+                bands = rasInHalFormat.bands.geranBands();
+                break;
+            case AccessNetworkType.UTRAN:
+                bands = rasInHalFormat.bands.utranBands();
+                break;
+            case AccessNetworkType.EUTRAN:
+                bands = rasInHalFormat.bands.eutranBands();
+                break;
+            case AccessNetworkType.NGRAN:
+                bands = rasInHalFormat.bands.ngranBands();
+                break;
+            default:
+                Log.wtf(RILJ_LOG_TAG, "radioAccessNetwork " + ras.getRadioAccessNetwork()
+                        + " not supported!");
+                return null;
+        }
+
+        if (ras.getBands() != null) {
+            for (int band : ras.getBands()) {
+                bands.add(band);
+            }
+        }
+        if (ras.getChannels() != null) {
+            for (int channel : ras.getChannels()) {
+                rasInHalFormat.channels.add(channel);
+            }
+        }
+
+        return rasInHalFormat;
+    }
+
     @Override
     public void startNetworkScan(NetworkScanRequest nsr, Message result) {
         IRadio radioProxy = getRadioProxy(result);
         if (radioProxy != null) {
-            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) {
+            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                android.hardware.radio.V1_5.NetworkScanRequest request =
+                        new android.hardware.radio.V1_5.NetworkScanRequest();
+                request.type = nsr.getScanType();
+                request.interval = nsr.getSearchPeriodicity();
+                request.maxSearchTime = nsr.getMaxSearchTime();
+                request.incrementalResultsPeriodicity = nsr.getIncrementalResultsPeriodicity();
+                request.incrementalResults = nsr.getIncrementalResults();
 
+                for (RadioAccessSpecifier ras : nsr.getSpecifiers()) {
+                    android.hardware.radio.V1_5.RadioAccessSpecifier rasInHalFormat =
+                            convertRadioAccessSpecifierToRadioHAL_1_5(ras);
+                    if (rasInHalFormat == null) {
+                        return;
+                    }
+                    request.specifiers.add(rasInHalFormat);
+                }
+
+                request.mccMncs.addAll(nsr.getPlmns());
+                RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result,
+                        mRILDefaultWorkSource);
+
+                if (RILJ_LOGD) {
+                    riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+                }
+
+                try {
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+                    radioProxy15.startNetworkScan_1_5(rr.mSerial, request);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "startNetworkScan", e);
+                }
+            } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) {
                 android.hardware.radio.V1_2.NetworkScanRequest request =
                         new android.hardware.radio.V1_2.NetworkScanRequest();
                 request.type = nsr.getScanType();
@@ -2528,7 +2698,8 @@
 
             if (RILJ_LOGD) {
                 riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " contents = "
-                        + (Build.IS_DEBUGGABLE ? contents : censoredTerminalResponse(contents)));
+                        + (TelephonyUtils.IS_DEBUGGABLE
+                            ? contents : censoredTerminalResponse(contents)));
             }
 
             try {
@@ -3034,6 +3205,36 @@
     }
 
     @Override
+    public void sendCdmaSMSExpectMore(byte[] pdu, Message result) {
+        if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+            IRadio radioProxy = getRadioProxy(result);
+            // IRadio V1.5
+            android.hardware.radio.V1_5.IRadio radioProxy15 =
+                    (android.hardware.radio.V1_5.IRadio) radioProxy;
+            if (radioProxy15 != null) {
+                RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE, result,
+                    mRILDefaultWorkSource);
+
+                // Do not log function arg for privacy
+                if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+                CdmaSmsMessage msg = new CdmaSmsMessage();
+                constructCdmaSendSmsRilRequest(msg, pdu);
+
+                try {
+                    radioProxy15.sendCdmaSmsExpectMore(rr.mSerial, msg);
+                    mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_CDMA,
+                        SmsSession.Event.Format.SMS_FORMAT_3GPP2);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "sendCdmaSMSExpectMore", e);
+                }
+            }
+        } else {
+            sendCdmaSms(pdu, result);
+        }
+    }
+
+    @Override
     public void sendCdmaSms(byte[] pdu, Message result) {
         IRadio radioProxy = getRadioProxy(result);
         if (radioProxy != null) {
@@ -3510,7 +3711,13 @@
             }
 
             try {
-                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
+                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                    // v1.5
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+                    radioProxy15.setInitialAttachApn_1_5(rr.mSerial,
+                            convertToHalDataProfile15(dataProfile));
+                } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
                     // v1.4
                     android.hardware.radio.V1_4.IRadio radioProxy14 =
                             (android.hardware.radio.V1_4.IRadio) radioProxy;
@@ -3626,7 +3833,7 @@
                     mRILDefaultWorkSource);
 
             if (RILJ_LOGD) {
-                if (Build.IS_DEBUGGABLE) {
+                if (TelephonyUtils.IS_DEBUGGABLE) {
                     riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                             + String.format(" cla = 0x%02X ins = 0x%02X", cla, instruction)
                             + String.format(" p1 = 0x%02X p2 = 0x%02X p3 = 0x%02X", p1, p2, p3)
@@ -3653,7 +3860,7 @@
                     mRILDefaultWorkSource);
 
             if (RILJ_LOGD) {
-                if (Build.IS_DEBUGGABLE) {
+                if (TelephonyUtils.IS_DEBUGGABLE) {
                     riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid
                             + " p2 = " + p2);
                 } else {
@@ -3704,7 +3911,7 @@
                     mRILDefaultWorkSource);
 
             if (RILJ_LOGD) {
-                if (Build.IS_DEBUGGABLE) {
+                if (TelephonyUtils.IS_DEBUGGABLE) {
                     riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                             + String.format(" channel = %d", channel)
                             + String.format(" cla = 0x%02X ins = 0x%02X", cla, instruction)
@@ -3913,7 +4120,29 @@
 
             RILRequest rr = null;
             try {
-                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
+                if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                    // V1.5
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+
+                    rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result,
+                            mRILDefaultWorkSource);
+
+                    ArrayList<android.hardware.radio.V1_5.DataProfileInfo> dpis = new ArrayList<>();
+                    for (DataProfile dp : dps) {
+                        dpis.add(convertToHalDataProfile15(dp));
+                    }
+
+                    if (RILJ_LOGD) {
+                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                + " with data profiles : ");
+                        for (DataProfile profile : dps) {
+                            riljLog(profile.toString());
+                        }
+                    }
+
+                    radioProxy15.setDataProfile_1_5(rr.mSerial, dpis);
+                } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) {
                     // V1.4
                     android.hardware.radio.V1_4.IRadio radioProxy14 =
                             (android.hardware.radio.V1_4.IRadio) radioProxy;
@@ -4355,8 +4584,8 @@
     }
 
     @Override
-    public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb,
-            int[] thresholdsDbm, int ran, Message result) {
+    public void setSignalStrengthReportingCriteria(SignalThresholdInfo signalThresholdInfo,
+            int ran, Message result) {
         IRadio radioProxy = getRadioProxy(result);
         if (radioProxy != null) {
             if (mRadioVersion.less(RADIO_HAL_VERSION_1_2)) {
@@ -4364,26 +4593,58 @@
                         + "than 1.2");
                 return;
             }
-
-            RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
-                    result, mRILDefaultWorkSource);
-
-            if (RILJ_LOGD) {
-                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-            }
-
-            try {
-                android.hardware.radio.V1_2.IRadio radioProxy12 =
+            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)
+                    && mRadioVersion.less(RADIO_HAL_VERSION_1_5)) {
+                RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
+                        result, mRILDefaultWorkSource);
+                if (RILJ_LOGD) {
+                    riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+                }
+                try {
+                    android.hardware.radio.V1_2.IRadio radioProxy12 =
                         (android.hardware.radio.V1_2.IRadio) radioProxy;
-                radioProxy12.setSignalStrengthReportingCriteria(rr.mSerial, hysteresisMs,
-                        hysteresisDb, primitiveArrayToArrayList(thresholdsDbm),
-                        convertRanToHalRan(ran));
-            } catch (RemoteException | RuntimeException e) {
-                handleRadioProxyExceptionForRR(rr, "setSignalStrengthReportingCriteria", e);
+                    radioProxy12.setSignalStrengthReportingCriteria(rr.mSerial,
+                            signalThresholdInfo.getHysteresisMs(),
+                            signalThresholdInfo.getHysteresisDb(),
+                            primitiveArrayToArrayList(signalThresholdInfo.getThresholds()),
+                            convertRanToHalRan(ran));
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "setSignalStrengthReportingCriteria", e);
+                }
+            }
+            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
+                        result, mRILDefaultWorkSource);
+                if (RILJ_LOGD) {
+                    riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+                }
+                try {
+                    android.hardware.radio.V1_5.IRadio radioProxy15 =
+                            (android.hardware.radio.V1_5.IRadio) radioProxy;
+                    radioProxy15.setSignalStrengthReportingCriteria_1_5(rr.mSerial,
+                            convertToHalSignalThresholdInfo(signalThresholdInfo),
+                            convertRanToHalRan(ran));
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(
+                            rr, "setSignalStrengthReportingCriteria_1_5", e);
+                }
             }
         }
     }
 
+    private static android.hardware.radio.V1_5.SignalThresholdInfo convertToHalSignalThresholdInfo(
+            SignalThresholdInfo signalThresholdInfo) {
+        android.hardware.radio.V1_5.SignalThresholdInfo signalThresholdInfoHal =
+                new android.hardware.radio.V1_5.SignalThresholdInfo();
+        signalThresholdInfoHal.signalMeasurement = signalThresholdInfo.getSignalMeasurement();
+        signalThresholdInfoHal.hysteresisMs = signalThresholdInfo.getHysteresisMs();
+        signalThresholdInfoHal.hysteresisDb = signalThresholdInfo.getHysteresisDb();
+        signalThresholdInfoHal.thresholds = primitiveArrayToArrayList(
+                signalThresholdInfo.getThresholds());
+        signalThresholdInfoHal.isEnabled = signalThresholdInfo.isEnabled();
+        return signalThresholdInfoHal;
+    }
+
     @Override
     public void setLinkCapacityReportingCriteria(int hysteresisMs, int hysteresisDlKbps,
             int hysteresisUlKbps, int[] thresholdsDlKbps, int[] thresholdsUlKbps, int ran,
@@ -4428,12 +4689,31 @@
                 return AccessNetwork.CDMA2000;
             case AccessNetworkType.IWLAN:
                 return AccessNetwork.IWLAN;
+            case AccessNetworkType.NGRAN:
+                return AccessNetwork.NGRAN;
             case AccessNetworkType.UNKNOWN:
             default:
                 return 0;
         }
     }
 
+    private static int convertRanToAnt(int radioAccessNetwork) {
+        switch(radioAccessNetwork) {
+            case RadioAccessNetworks.GERAN:
+                return AccessNetworkType.GERAN;
+            case RadioAccessNetworks.UTRAN:
+                return AccessNetworkType.UTRAN;
+            case RadioAccessNetworks.EUTRAN:
+                return AccessNetworkType.EUTRAN;
+            case RadioAccessNetworks.NGRAN:
+                return AccessNetworkType.NGRAN;
+            case RadioAccessNetworks.CDMA2000:
+                return AccessNetworkType.CDMA2000;
+            default:
+                return AccessNetworkType.UNKNOWN;
+        }
+    }
+
     @Override
     public void setSimCardPower(int state, Message result, WorkSource workSource) {
         workSource = getDeafultWorkSourceIfInvalid(workSource);
@@ -4639,6 +4919,98 @@
     }
 
     /**
+     * Enable or disable uicc applications on the SIM.
+     *
+     * @param enable whether to enable or disable uicc applications.
+     * @param onCompleteMessage a Message to return to the requester
+     */
+    @Override
+    public void enableUiccApplications(boolean enable, Message onCompleteMessage) {
+        IRadio radioProxy = getRadioProxy(onCompleteMessage);
+        if (radioProxy == null) {
+            Rlog.e(RIL.RILJ_LOG_TAG, "Radio Proxy object is null!");
+            if (onCompleteMessage != null) {
+                AsyncResult.forMessage(onCompleteMessage, null,
+                        CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
+                onCompleteMessage.sendToTarget();
+            }
+        }
+
+        if (mRadioVersion.less(RADIO_HAL_VERSION_1_5)) {
+            if (onCompleteMessage != null) {
+                AsyncResult.forMessage(onCompleteMessage, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                onCompleteMessage.sendToTarget();
+            }
+            return;
+        }
+
+        android.hardware.radio.V1_5.IRadio radioProxy15 =
+                (android.hardware.radio.V1_5.IRadio) radioProxy;
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_ENABLE_UICC_APPLICATIONS,
+                onCompleteMessage, mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        try {
+            radioProxy15.enableUiccApplications(rr.mSerial, enable);
+        } catch (RemoteException | RuntimeException e) {
+            handleRadioProxyExceptionForRR(rr, "enableUiccApplications", e);
+        }
+    }
+
+    /**
+     * Whether uicc applications are enabled or not.
+     *
+     * @param onCompleteMessage a Message to return to the requester
+     */
+    @Override
+    public void areUiccApplicationsEnabled(Message onCompleteMessage) {
+        IRadio radioProxy = getRadioProxy(onCompleteMessage);
+        if (radioProxy == null) {
+            Rlog.e(RIL.RILJ_LOG_TAG, "Radio Proxy object is null!");
+            if (onCompleteMessage != null) {
+                AsyncResult.forMessage(onCompleteMessage, null,
+                        CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
+                onCompleteMessage.sendToTarget();
+            }
+        }
+
+        if (mRadioVersion.less(RADIO_HAL_VERSION_1_5)) {
+            if (onCompleteMessage != null) {
+                AsyncResult.forMessage(onCompleteMessage, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                onCompleteMessage.sendToTarget();
+            }
+            return;
+        }
+
+        android.hardware.radio.V1_5.IRadio radioProxy15 =
+                (android.hardware.radio.V1_5.IRadio) radioProxy;
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT,
+                onCompleteMessage, mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        try {
+            radioProxy15.areUiccApplicationsEnabled(rr.mSerial);
+        } catch (RemoteException | RuntimeException e) {
+            handleRadioProxyExceptionForRR(rr, "areUiccApplicationsEnabled", e);
+        }
+    }
+
+    /**
+     * Whether {@link #enableUiccApplications} is supported, which is supported in 1.5 version.
+     */
+    @Override
+    public boolean canToggleUiccApplicationsEnablement() {
+        return getRadioProxy(null) != null && mRadioVersion
+                .greaterOrEqual(RADIO_HAL_VERSION_1_5);
+    }
+
+    /**
      *  Translates EF_SMS status bits to a status value compatible with
      *  SMS AT commands.  See TS 27.005 3.1.
      */
@@ -5560,6 +5932,12 @@
                 return "RIL_REQUEST_ENABLE_MODEM";
             case RIL_REQUEST_GET_MODEM_STATUS:
                 return "RIL_REQUEST_GET_MODEM_STATUS";
+            case RIL_REQUEST_ENABLE_UICC_APPLICATIONS:
+                return "RIL_REQUEST_ENABLE_UICC_APPLICATIONS";
+            case RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT:
+                return "RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT";
+            case RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE:
+                return "RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE";
             default: return "<unknown request>";
         }
     }
@@ -5671,6 +6049,12 @@
                 return "RIL_UNSOL_KEEPALIVE_STATUS";
             case RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG:
                 return "RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG";
+            case RIL_UNSOL_EMERGENCY_NUMBER_LIST:
+                return "RIL_UNSOL_EMERGENCY_NUMBER_LIST";
+            case RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED:
+                return "RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED";
+            case RIL_UNSOL_REGISTRATION_FAILED:
+                return "RIL_UNSOL_REGISTRATION_FAILED";
             default:
                 return "<unknown response>";
         }
@@ -5971,7 +6355,7 @@
     }
 
     /**
-     * Convert SetupDataCallResult defined in 1.0 or 1.4/types.hal into DataCallResponse
+     * Convert SetupDataCallResult defined in 1.0, 1.4, or 1.5 types.hal into DataCallResponse
      * @param dcResult setup data call result
      * @return converted DataCallResponse object
      */
@@ -5979,13 +6363,17 @@
     public static DataCallResponse convertDataCallResult(Object dcResult) {
         if (dcResult == null) return null;
 
-        int cause, suggestedRetryTime, cid, active, mtu;
+        int cause, suggestedRetryTime, cid, active, mtu, mtuV4, mtuV6;
         String ifname;
         int protocolType;
         String[] addresses = null;
         String[] dnses = null;
         String[] gateways = null;
         String[] pcscfs = null;
+
+        List<LinkAddress> laList = new ArrayList<>();
+        int version;
+
         if (dcResult instanceof android.hardware.radio.V1_0.SetupDataCallResult) {
             final android.hardware.radio.V1_0.SetupDataCallResult result =
                     (android.hardware.radio.V1_0.SetupDataCallResult) dcResult;
@@ -6008,6 +6396,8 @@
                 pcscfs = result.pcscf.split("\\s+");
             }
             mtu = result.mtu;
+            mtuV4 = mtuV6 = 0;
+            version = 0;
         } else if (dcResult instanceof android.hardware.radio.V1_4.SetupDataCallResult) {
             final android.hardware.radio.V1_4.SetupDataCallResult result =
                     (android.hardware.radio.V1_4.SetupDataCallResult) dcResult;
@@ -6022,32 +6412,55 @@
             gateways = result.gateways.stream().toArray(String[]::new);
             pcscfs = result.pcscf.stream().toArray(String[]::new);
             mtu = result.mtu;
+            mtuV4 = mtuV6 = 0;
+            version = 4;
+        } else if (dcResult instanceof android.hardware.radio.V1_5.SetupDataCallResult) {
+            final android.hardware.radio.V1_5.SetupDataCallResult result =
+                    (android.hardware.radio.V1_5.SetupDataCallResult) dcResult;
+            cause = result.cause;
+            suggestedRetryTime = result.suggestedRetryTime;
+            cid = result.cid;
+            active = result.active;
+            protocolType = result.type;
+            ifname = result.ifname;
+            laList = result.addresses.stream().map(a -> new LinkAddress(
+                    InetAddresses.parseNumericAddress(a.address), 0, a.properties, 0,
+                    a.deprecationTime, a.expirationTime)).collect(Collectors.toList());
+
+            dnses = result.dnses.stream().toArray(String[]::new);
+            gateways = result.gateways.stream().toArray(String[]::new);
+            pcscfs = result.pcscf.stream().toArray(String[]::new);
+            mtu = 0;
+            mtuV4 = result.mtuV4;
+            mtuV6 = result.mtuV6;
+            version = 5;
         } else {
             Rlog.e(RILJ_LOG_TAG, "Unsupported SetupDataCallResult " + dcResult);
             return null;
         }
 
-        // Process address
-        List<LinkAddress> laList = new ArrayList<>();
-        if (addresses != null) {
-            for (String address : addresses) {
-                address = address.trim();
-                if (address.isEmpty()) continue;
+        if (version < 5) {
+            // Process address
+            if (addresses != null) {
+                for (String address : addresses) {
+                    address = address.trim();
+                    if (address.isEmpty()) continue;
 
-                try {
-                    LinkAddress la;
-                    // Check if the address contains prefix length. If yes, LinkAddress
-                    // can parse that.
-                    if (address.split("/").length == 2) {
-                        la = new LinkAddress(address);
-                    } else {
-                        InetAddress ia = NetworkUtils.numericToInetAddress(address);
-                        la = new LinkAddress(ia, (ia instanceof Inet4Address) ? 32 : 128);
+                    try {
+                        LinkAddress la;
+                        // Check if the address contains prefix length. If yes, LinkAddress
+                        // can parse that.
+                        if (address.split("/").length == 2) {
+                            la = new LinkAddress(address);
+                        } else {
+                            InetAddress ia = InetAddresses.parseNumericAddress(address);
+                            la = new LinkAddress(ia, (ia instanceof Inet4Address) ? 32 : 128);
+                        }
+
+                        laList.add(la);
+                    } catch (IllegalArgumentException e) {
+                        Rlog.e(RILJ_LOG_TAG, "Unknown address: " + address, e);
                     }
-
-                    laList.add(la);
-                } catch (IllegalArgumentException e) {
-                    Rlog.e(RILJ_LOG_TAG, "Unknown address: " + address, e);
                 }
             }
         }
@@ -6059,7 +6472,7 @@
                 dns = dns.trim();
                 InetAddress ia;
                 try {
-                    ia = NetworkUtils.numericToInetAddress(dns);
+                    ia = InetAddresses.parseNumericAddress(dns);
                     dnsList.add(ia);
                 } catch (IllegalArgumentException e) {
                     Rlog.e(RILJ_LOG_TAG, "Unknown dns: " + dns, e);
@@ -6074,7 +6487,7 @@
                 gateway = gateway.trim();
                 InetAddress ia;
                 try {
-                    ia = NetworkUtils.numericToInetAddress(gateway);
+                    ia = InetAddresses.parseNumericAddress(gateway);
                     gatewayList.add(ia);
                 } catch (IllegalArgumentException e) {
                     Rlog.e(RILJ_LOG_TAG, "Unknown gateway: " + gateway, e);
@@ -6089,7 +6502,7 @@
                 pcscf = pcscf.trim();
                 InetAddress ia;
                 try {
-                    ia = NetworkUtils.numericToInetAddress(pcscf);
+                    ia = InetAddresses.parseNumericAddress(pcscf);
                     pcscfList.add(ia);
                 } catch (IllegalArgumentException e) {
                     Rlog.e(RILJ_LOG_TAG, "Unknown pcscf: " + pcscf, e);
@@ -6097,8 +6510,22 @@
             }
         }
 
-        return new DataCallResponse(cause, suggestedRetryTime, cid, active, protocolType, ifname,
-                laList, dnsList, gatewayList, pcscfList, mtu);
+        return new DataCallResponse.Builder()
+                .setCause(cause)
+                .setSuggestedRetryTime(suggestedRetryTime)
+                .setId(cid)
+                .setLinkStatus(active)
+                .setProtocolType(protocolType)
+                .setInterfaceName(ifname)
+                .setAddresses(laList)
+                .setDnsAddresses(dnsList)
+                .setGatewayAddresses(gatewayList)
+                .setPcscfAddresses(pcscfList)
+                .setMtu(mtu)
+                .setMtuV4(mtuV4)
+                .setMtuV6(mtuV6)
+                .setVersion(version)
+                .build();
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/RILRequest.java b/src/java/com/android/internal/telephony/RILRequest.java
index 2d8f952..0d5f8e7 100644
--- a/src/java/com/android/internal/telephony/RILRequest.java
+++ b/src/java/com/android/internal/telephony/RILRequest.java
@@ -16,13 +16,14 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.AsyncResult;
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.WorkSource;
 import android.os.WorkSource.WorkChain;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Random;
@@ -148,7 +149,7 @@
         final ArrayList<WorkChain> workChains = mWorkSource.getWorkChains();
         if (workChains != null && !workChains.isEmpty()) {
             final WorkChain workChain = workChains.get(0);
-            return workChain.getAttributionUid() + ":" + workChain.getTags()[0];
+            return workChain.toString();
         }
 
         return null;
diff --git a/src/java/com/android/internal/telephony/RadioCapability.java b/src/java/com/android/internal/telephony/RadioCapability.java
index 2b2615b..3475201 100644
--- a/src/java/com/android/internal/telephony/RadioCapability.java
+++ b/src/java/com/android/internal/telephony/RadioCapability.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.telephony.TelephonyManager;
 
 /**
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index a2d4e5b..24a7791 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -38,15 +38,19 @@
 import android.os.Registrant;
 import android.os.RemoteException;
 import android.os.WorkSource;
-import android.telephony.Rlog;
+import android.telephony.PhoneCapability;
+import android.telephony.SimSlotCapability;
 import android.util.SparseArray;
 
 import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
 
 /**
  * This class provides wrapper APIs for IRadioConfig interface.
@@ -64,6 +68,8 @@
 
     private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_1 = new HalVersion(1, 1);
 
+    private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_3 = new HalVersion(1, 3);
+
     private final boolean mIsMobileNetworkSupported;
     private volatile IRadioConfig mRadioConfigProxy = null;
     // IRadioConfig version
@@ -340,11 +346,20 @@
             logd(rr.serialString() + "> " + requestToString(rr.mRequest));
         }
 
-        try {
-            ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
-                    .getPhoneCapability(rr.mSerial);
-        } catch (RemoteException | RuntimeException e) {
-            resetProxyAndRequestList("getPhoneCapability", e);
+        if (mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_3)) {
+            try {
+                ((android.hardware.radio.config.V1_3.IRadioConfig) mRadioConfigProxy)
+                        .getPhoneCapability_1_3(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                resetProxyAndRequestList("getPhoneCapability_1_3", e);
+            }
+        } else {
+            try {
+                ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
+                        .getPhoneCapability(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                resetProxyAndRequestList("getPhoneCapability", e);
+            }
         }
     }
 
@@ -487,6 +502,49 @@
         return response;
     }
 
+    static PhoneCapability convertHalPhoneCapability(
+            android.hardware.radio.config.V1_1.PhoneCapability pc) {
+        long psDataConnectionLingerTimeMillis = pc.isInternetLingeringSupported ? 1 : 0;
+
+        List<String> logicalModemUuids = new ArrayList<>();
+        for (android.hardware.radio.config.V1_1.ModemInfo modemInfo : pc.logicalModemList) {
+            logicalModemUuids.add("com.xxxx.lm" + modemInfo.modemId);
+        }
+
+        List<List<Long>> features = new ArrayList<>();
+        for (int i = 0; i < pc.maxActiveData; i++) {
+            List<Long> feature = new ArrayList<>();
+            feature.add(PhoneCapability.MODEM_FEATURE_PS_VOICE_REG);
+            features.add(feature);
+        }
+
+        return new PhoneCapability(0, 0, 0, 0, psDataConnectionLingerTimeMillis, 0,
+                null, null, null, null, logicalModemUuids, null, features);
+    }
+
+    static PhoneCapability convertHalPhoneCapability_1_3(
+            android.hardware.radio.config.V1_3.PhoneCapability pc) {
+        List<SimSlotCapability> simSlotCapabilities = new ArrayList<>();
+        for (android.hardware.radio.config.V1_3.SimSlotCapability sc : pc.simSlotCapabilities) {
+            simSlotCapabilities.add(new SimSlotCapability(sc.physicalSlotId, sc.slotType));
+        }
+
+        List<List<Long>> features = new ArrayList<>();
+        for (android.hardware.radio.config.V1_3.ConcurrentModemFeatures cmf
+                : pc.concurrentFeatureSupport) {
+            features.add(cmf.modemFeatures
+                    .stream()
+                    .mapToLong(Integer::longValue)
+                    .boxed()
+                    .collect(Collectors.toList()));
+        }
+
+        return new PhoneCapability(pc.utranUeCategoryDl, pc.utranUeCategoryUl,
+                pc.eutranUeCategoryDl, pc.eutranUeCategoryUl, pc.psDataConnectionLingerTimeMillis,
+                pc.supportedRats, pc.geranBands, pc.utranBands, pc.eutranBands, pc.ngranBands,
+                pc.logicalModemUuids, simSlotCapabilities, features);
+    }
+
     private static void logd(String log) {
         Rlog.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndication.java b/src/java/com/android/internal/telephony/RadioConfigIndication.java
index 39af57b..639272c 100644
--- a/src/java/com/android/internal/telephony/RadioConfigIndication.java
+++ b/src/java/com/android/internal/telephony/RadioConfigIndication.java
@@ -18,9 +18,9 @@
 
 import android.hardware.radio.config.V1_2.IRadioConfigIndication;
 import android.os.AsyncResult;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponse.java b/src/java/com/android/internal/telephony/RadioConfigResponse.java
index 475f866..0f4a719 100644
--- a/src/java/com/android/internal/telephony/RadioConfigResponse.java
+++ b/src/java/com/android/internal/telephony/RadioConfigResponse.java
@@ -20,14 +20,12 @@
 import android.hardware.radio.V1_0.RadioResponseInfo;
 import android.hardware.radio.config.V1_1.ModemsConfig;
 import android.hardware.radio.config.V1_2.IRadioConfigResponse;
-import android.telephony.ModemInfo;
 import android.telephony.PhoneCapability;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
-import java.util.List;
 
 /**
  * This class is the implementation of IRadioConfigResponse interface.
@@ -115,23 +113,6 @@
         }
     }
 
-    private PhoneCapability convertHalPhoneCapability(
-            android.hardware.radio.config.V1_1.PhoneCapability phoneCapability) {
-        // TODO b/121394331: clean up V1_1.PhoneCapability fields.
-        int maxActiveVoiceCalls = 0;
-        int maxActiveData = phoneCapability.maxActiveData;
-        int max5G = 0;
-        boolean validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
-        List<ModemInfo> logicalModemList = new ArrayList();
-
-        for (android.hardware.radio.config.V1_1.ModemInfo
-                modemInfo : phoneCapability.logicalModemList) {
-            logicalModemList.add(new ModemInfo(modemInfo.modemId));
-        }
-
-        return new PhoneCapability(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList,
-                validationBeforeSwitchSupported);
-    }
     /**
      * Response function for IRadioConfig.getPhoneCapability().
      */
@@ -140,7 +121,7 @@
         RILRequest rr = mRadioConfig.processResponse(responseInfo);
 
         if (rr != null) {
-            PhoneCapability ret = convertHalPhoneCapability(phoneCapability);
+            PhoneCapability ret = RadioConfig.convertHalPhoneCapability(phoneCapability);
             if (responseInfo.error == RadioError.NONE) {
                 // send response
                 RadioResponse.sendMessageResponse(rr.mResult, ret);
@@ -158,6 +139,31 @@
     }
 
     /**
+     * Response function for IRadioConfig.getPhoneCapability_1_3().
+     */
+    public void getPhoneCapabilityResponse_1_3(RadioResponseInfo responseInfo,
+            android.hardware.radio.config.V1_3.PhoneCapability phoneCapability) {
+        RILRequest rr = mRadioConfig.processResponse(responseInfo);
+
+        if (rr != null) {
+            PhoneCapability ret = RadioConfig.convertHalPhoneCapability_1_3(phoneCapability);
+            if (responseInfo.error == RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                Rlog.d(TAG, rr.serialString() + "< "
+                        + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(responseInfo.error, ret);
+                Rlog.e(TAG, rr.serialString() + "< "
+                        + mRadioConfig.requestToString(rr.mRequest) + " error "
+                        + responseInfo.error);
+            }
+        } else {
+            Rlog.e(TAG, "getPhoneCapabilityResponse_1_3: Error " + responseInfo.toString());
+        }
+    }
+
+    /**
      * Response function for IRadioConfig.setPreferredDataModem().
      */
     public void setPreferredDataModemResponse(RadioResponseInfo responseInfo) {
diff --git a/src/java/com/android/internal/telephony/RadioIndication.java b/src/java/com/android/internal/telephony/RadioIndication.java
index 5d00690..ede5854 100644
--- a/src/java/com/android/internal/telephony/RadioIndication.java
+++ b/src/java/com/android/internal/telephony/RadioIndication.java
@@ -63,6 +63,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_PROACTIVE_COMMAND;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_SESSION_END;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SUPP_SVC_NOTIFICATION;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_VOICE_RADIO_TECH_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOl_CDMA_PRL_CHANGED;
@@ -84,11 +85,12 @@
 import android.hardware.radio.V1_0.SuppSvcNotification;
 import android.hardware.radio.V1_2.CellConnectionStatus;
 import android.hardware.radio.V1_4.IRadioIndication;
-import android.hardware.radio.V1_4.RadioFrequencyInfo.hidl_discriminator;
 import android.os.AsyncResult;
-import android.os.SystemProperties;
+import android.sysprop.TelephonyProperties;
 import android.telephony.Annotation.RadioPowerState;
+import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PcoData;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
@@ -211,8 +213,7 @@
         result[0] = nitzTime;
         result[1] = receivedTime;
 
-        boolean ignoreNitz = SystemProperties.getBoolean(
-                TelephonyProperties.PROPERTY_IGNORE_NITZ, false);
+        boolean ignoreNitz = TelephonyProperties.ignore_nitz().orElse(false);
 
         if (ignoreNitz) {
             if (RIL.RILJ_LOGD) mRil.riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED");
@@ -761,6 +762,17 @@
         mRil.mRilCellInfoListRegistrants.notifyRegistrants(new AsyncResult(null, response, null));
     }
 
+    /** Get unsolicited message for uicc applications enablement changes. */
+    public void uiccApplicationsEnablementChanged(int indicationType, boolean enabled) {
+        mRil.processIndication(indicationType);
+
+        if (RIL.RILJ_LOGD) {
+            mRil.unsljLogRet(RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED, enabled);
+        }
+
+        mRil.mUiccApplicationsEnablementRegistrants.notifyResult(enabled);
+    }
+
     /** Incremental network scan results */
     public void networkScanResult(int indicationType,
                                   android.hardware.radio.V1_1.NetworkScanResult result) {
@@ -962,6 +974,32 @@
     }
 
     /**
+     * Indicate that a registration failure has occurred.
+     *
+     * @param cellIdentity a CellIdentity the CellIdentity of the Cell
+     * @param chosenPlmn a 5 or 6 digit alphanumeric string indicating the PLMN on which
+     *        registration failed
+     * @param domain the domain of the failed procedure: CS, PS, or both
+     * @param causeCode the primary failure cause code of the procedure
+     * @param additionalCauseCode an additional cause code if applicable
+     */
+    public void registrationFailed(int indicationType,
+            android.hardware.radio.V1_5.CellIdentity cellIdentity, String chosenPlmn,
+            @NetworkRegistrationInfo.Domain int domain,
+            int causeCode, int additionalCauseCode) {
+        mRil.processIndication(indicationType);
+
+        CellIdentity ci = CellIdentity.create(cellIdentity);
+
+        mRil.mRegistrationFailedRegistrant.notifyRegistrant(
+                new AsyncResult(
+                        null,
+                        new RegistrationFailedEvent(ci, chosenPlmn, domain,
+                                causeCode, additionalCauseCode),
+                        null));
+    }
+
+    /**
      * @param stateInt
      * @return {@link RadioPowerState RadioPowerState}
      */
@@ -995,10 +1033,10 @@
             android.hardware.radio.V1_4.PhysicalChannelConfig config) {
 
         switch (config.rfInfo.getDiscriminator()) {
-            case hidl_discriminator.range:
+            case android.hardware.radio.V1_4.RadioFrequencyInfo.hidl_discriminator.range:
                 builder.setFrequencyRange(config.rfInfo.range());
                 break;
-            case hidl_discriminator.channelNumber:
+            case android.hardware.radio.V1_4.RadioFrequencyInfo.hidl_discriminator.channelNumber:
                 builder.setChannelNumber(config.rfInfo.channelNumber());
                 break;
             default:
diff --git a/src/java/com/android/internal/telephony/RadioResponse.java b/src/java/com/android/internal/telephony/RadioResponse.java
index a36b7a6..a5eab2c 100644
--- a/src/java/com/android/internal/telephony/RadioResponse.java
+++ b/src/java/com/android/internal/telephony/RadioResponse.java
@@ -919,6 +919,15 @@
     }
 
     /**
+     *
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     * @param sms Sms result struct as defined by SendSmsResult in types.hal
+     */
+    public void sendCdmaSMSExpectMoreResponse(RadioResponseInfo responseInfo, SendSmsResult sms) {
+        responseSms(responseInfo, sms);
+    }
+
+    /**
      * @param responseInfo Response info struct containing response type, serial no. and error
      */
     public void acknowledgeLastIncomingCdmaSmsResponse(RadioResponseInfo responseInfo) {
@@ -1452,6 +1461,13 @@
     /**
      * @param responseInfo Response info struct containing response type, serial no. and error
      */
+    public void setSignalStrengthReportingCriteriaResponse_1_5(RadioResponseInfo responseInfo) {
+        responseVoid(responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     */
     public void setLinkCapacityReportingCriteriaResponse(RadioResponseInfo responseInfo) {
         responseVoid(responseInfo);
     }
@@ -2186,10 +2202,10 @@
                 }
                 final int rxModeTimeMs = activityInfo.rxModeTimeMs;
                 ret = new ModemActivityInfo(SystemClock.elapsedRealtime(), sleepModeTimeMs,
-                        idleModeTimeMs, txModeTimeMs, rxModeTimeMs, 0);
+                        idleModeTimeMs, txModeTimeMs, rxModeTimeMs);
             } else {
                 ret = new ModemActivityInfo(0, 0, 0, new int [ModemActivityInfo.TX_POWER_LEVELS],
-                        0, 0);
+                        0);
                 responseInfo.error = RadioError.NONE;
             }
             sendMessageResponse(rr.mResult, ret);
@@ -2356,4 +2372,27 @@
     public void setSystemSelectionChannelsResponse(RadioResponseInfo responseInfo) {
         responseVoid(responseInfo);
     }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error.
+     */
+    public void enableUiccApplicationsResponse(RadioResponseInfo responseInfo) {
+        responseVoid(responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error.
+     * @param enabled whether Uicc applications are enabled.
+     */
+    public void areUiccApplicationsEnabledResponse(RadioResponseInfo responseInfo,
+            boolean enabled) {
+        RILRequest rr = mRil.processResponse(responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                sendMessageResponse(rr.mResult, enabled);
+            }
+            mRil.processResponseDone(rr, responseInfo, enabled);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/RatRatcheter.java b/src/java/com/android/internal/telephony/RatRatcheter.java
index 7b45c53..084223f 100644
--- a/src/java/com/android/internal/telephony/RatRatcheter.java
+++ b/src/java/com/android/internal/telephony/RatRatcheter.java
@@ -20,17 +20,19 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.CarrierConfigManager;
 import android.telephony.NetworkRegistrationInfo;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.telephony.Rlog;
+
 import java.util.Arrays;
 
 /**
@@ -83,8 +85,14 @@
 
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
-        phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL,
-                intentFilter, null, null);
+        try {
+            Context contextAsUser = phone.getContext().createPackageContextAsUser(
+                phone.getContext().getPackageName(), 0, UserHandle.ALL);
+            contextAsUser.registerReceiver(mConfigChangedReceiver,
+                intentFilter, null /* broadcastPermission */, null);
+        } catch (PackageManager.NameNotFoundException e) {
+            Rlog.e(LOG_TAG, "Package name not found: " + e.getMessage());
+        }
         resetRatFamilyMap();
     }
 
diff --git a/src/java/com/android/internal/telephony/RegistrationFailedEvent.java b/src/java/com/android/internal/telephony/RegistrationFailedEvent.java
new file mode 100644
index 0000000..35807ca
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RegistrationFailedEvent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.annotation.NonNull;
+import android.telephony.CellIdentity;
+import android.telephony.NetworkRegistrationInfo;
+
+/**
+ * Event fired to notify of a registration failure.
+ */
+public class RegistrationFailedEvent {
+    /** The Cell Identity of the cell on which registration failed */
+    public final CellIdentity cellIdentity;
+
+    /** The PLMN for that cell on which registration failed */
+    public final String chosenPlmn;
+
+    /** The registration domain(s) for this registration attempt */
+    @NetworkRegistrationInfo.Domain public final int domain;
+
+    /** The registration cause code */
+    public final int causeCode;
+
+    /** The additional cause code in case of a combined procedure */
+    public final int additionalCauseCode;
+
+    /** Constructor for this event */
+    public RegistrationFailedEvent(@NonNull CellIdentity cellIdentity,
+            @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
+        this.cellIdentity = cellIdentity;
+        this.chosenPlmn = chosenPlmn;
+        this.domain = domain;
+        this.causeCode = causeCode;
+        this.additionalCauseCode = additionalCauseCode;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("{CellIdentity=")
+                .append(cellIdentity)
+                .append(", chosenPlmn=")
+                .append(chosenPlmn)
+                .append(", domain=")
+                .append(domain)
+                .append(", causeCode=")
+                .append(causeCode)
+                .append(", additionalCauseCode=")
+                .append(additionalCauseCode)
+                .toString();
+    }
+}
diff --git a/src/java/com/android/internal/telephony/RetryManager.java b/src/java/com/android/internal/telephony/RetryManager.java
index 87d6cf5..62cde52 100644
--- a/src/java/com/android/internal/telephony/RetryManager.java
+++ b/src/java/com/android/internal/telephony/RetryManager.java
@@ -16,17 +16,18 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.os.Build;
 import android.os.PersistableBundle;
 import android.os.SystemProperties;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
 import android.util.Pair;
 
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
+
 import java.util.ArrayList;
 import java.util.Random;
 
@@ -332,7 +333,7 @@
         String otherConfigString = null;
 
         try {
-            if (Build.IS_DEBUGGABLE) {
+            if (TelephonyUtils.IS_DEBUGGABLE) {
                 // Using system properties is easier for testing from command line.
                 String config = SystemProperties.get("test.data_retry_config");
                 if (!TextUtils.isEmpty(config)) {
diff --git a/src/java/com/android/internal/telephony/RilWakelockInfo.java b/src/java/com/android/internal/telephony/RilWakelockInfo.java
index 5d9e54b..a5aea58 100644
--- a/src/java/com/android/internal/telephony/RilWakelockInfo.java
+++ b/src/java/com/android/internal/telephony/RilWakelockInfo.java
@@ -17,10 +17,10 @@
 package com.android.internal.telephony;
 
 import android.annotation.TargetApi;
-import android.os.Build;
-import android.telephony.Rlog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 @TargetApi(8)
 public class RilWakelockInfo {
@@ -57,7 +57,7 @@
 
     private int validateConcurrentRequests(int concurrentRequests) {
         if(concurrentRequests <= 0) {
-            if(Build.IS_DEBUGGABLE) {
+            if (TelephonyUtils.IS_DEBUGGABLE) {
                 IllegalArgumentException e = new IllegalArgumentException(
                     "concurrentRequests should always be greater than 0.");
                 Rlog.e(LOG_TAG, e.toString());
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 0f3d8aa..7ab55a1 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -30,13 +30,12 @@
 import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
 
-import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -64,7 +63,6 @@
 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
@@ -87,6 +85,7 @@
 import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.telephony.uicc.UiccCard;
 import com.android.internal.telephony.uicc.UiccController;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -383,13 +382,6 @@
         }
     }
 
-    private static int getSendSmsFlag(@Nullable PendingIntent deliveryIntent) {
-        if (deliveryIntent == null) {
-            return 0;
-        }
-        return CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS;
-    }
-
     /**
      * Use the carrier messaging service to send a text SMS.
      */
@@ -405,8 +397,13 @@
 
             if (text != null) {
                 try {
-                    sendTextSms(text, getSubId(),
-                            mTracker.mDestAddress, getSendSmsFlag(mTracker.mDeliveryIntent),
+                    sendTextSms(
+                            text,
+                            getSubId(),
+                            mTracker.mDestAddress,
+                            (mTracker.mDeliveryIntent != null)
+                                    ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+                                    : 0,
                             mSenderCallback);
                 } catch (RuntimeException e) {
                     Rlog.e(TAG, "Exception sending the SMS: " + e);
@@ -438,9 +435,15 @@
 
             if (data != null) {
                 try {
-                    sendDataSms(data, getSubId(),
-                            mTracker.mDestAddress, destPort,
-                            getSendSmsFlag(mTracker.mDeliveryIntent), mSenderCallback);
+                    sendDataSms(
+                            data,
+                            getSubId(),
+                            mTracker.mDestAddress,
+                            destPort,
+                            (mTracker.mDeliveryIntent != null)
+                                    ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+                                    : 0,
+                            mSenderCallback);
                 } catch (RuntimeException e) {
                     Rlog.e(TAG, "Exception sending the SMS: " + e);
                     mSenderCallback.onSendSmsComplete(
@@ -566,10 +569,23 @@
 
         @Override
         public void onServiceReady() {
+            boolean statusReportRequested = false;
+            for (SmsTracker tracker : mTrackers) {
+                if (tracker.mDeliveryIntent != null) {
+                    statusReportRequested = true;
+                    break;
+                }
+            }
+
             try {
                 sendMultipartTextSms(
-                        mParts, getSubId(), mTrackers[0].mDestAddress,
-                        getSendSmsFlag(mTrackers[0].mDeliveryIntent), mSenderCallback);
+                        mParts,
+                        getSubId(),
+                        mTrackers[0].mDestAddress,
+                        statusReportRequested
+                                ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+                                : 0,
+                        mSenderCallback);
             } catch (RuntimeException e) {
                 Rlog.e(TAG, "Exception sending the SMS: " + e);
                 mSenderCallback.onSendMultipartSmsComplete(
@@ -1223,15 +1239,15 @@
             }
 
             if (error == RESULT_ERROR_NONE) {
-                PackageManager pm = mContext.getPackageManager();
+                UserHandle userHandle = UserHandle.of(trackers[0].mUserId);
+                PackageManager pm = mContext.createContextAsUser(userHandle, 0).getPackageManager();
 
                 try {
                     // Get package info via packagemanager
                     appInfo =
-                            pm.getPackageInfoAsUser(
+                            pm.getPackageInfo(
                                     trackers[0].getAppPackageName(),
-                                    PackageManager.GET_SIGNATURES,
-                                    trackers[0].mUserId);
+                                    PackageManager.GET_SIGNATURES);
                 } catch (PackageManager.NameNotFoundException e) {
                     Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS");
                     error = RESULT_ERROR_GENERIC_FAILURE;
@@ -1824,15 +1840,14 @@
             AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
             SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText,
             boolean persistMessage, int priority, int validityPeriod, boolean isForVvm) {
-        // Get calling app package name via UID from Binder call
-        PackageManager pm = mContext.getPackageManager();
 
         // Get package info via packagemanager
-        final int userId = UserHandle.getUserHandleForUid(Binder.getCallingUid()).getIdentifier();
+        UserHandle callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid());
+        final int userId = callingUser.getIdentifier();
+        PackageManager pm = mContext.createContextAsUser(callingUser, 0).getPackageManager();
         PackageInfo appInfo = null;
         try {
-            appInfo = pm.getPackageInfoAsUser(
-                    callingPackage, PackageManager.GET_SIGNATURES, userId);
+            appInfo = pm.getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES);
         } catch (PackageManager.NameNotFoundException e) {
             // error will be logged in sendRawPdu
         }
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 30391ca..b8b4a8c 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.telephony;
 
-import static android.provider.Telephony.ServiceStateTable.getContentValuesForServiceState;
 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
 
 import static com.android.internal.telephony.CarrierActionAgent.CARRIER_ACTION_SET_RADIO_ENABLED;
@@ -26,13 +25,14 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -42,18 +42,20 @@
 import android.net.NetworkCapabilities;
 import android.os.AsyncResult;
 import android.os.BaseBundle;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
+import android.os.Parcel;
 import android.os.PersistableBundle;
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.TimestampedValue;
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
+import android.sysprop.TelephonyProperties;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.AccessNetworkConstants.TransportType;
@@ -65,21 +67,20 @@
 import android.telephony.CellIdentityTdscdma;
 import android.telephony.CellIdentityWcdma;
 import android.telephony.CellInfo;
-import android.telephony.CellLocation;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
 import android.telephony.DataSpecificRegistrationInfo;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhysicalChannelConfig;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.SignalStrength;
+import android.telephony.SignalThresholdInfo;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.telephony.VoiceSpecificRegistrationInfo;
-import android.telephony.cdma.CdmaCellLocation;
-import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.LocalLog;
@@ -87,7 +88,6 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.StatsLog;
-import android.util.TimestampedValue;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
@@ -108,9 +108,11 @@
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UiccProfile;
+import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.NotificationChannelController;
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -279,6 +281,16 @@
     protected static final int EVENT_PHYSICAL_CHANNEL_CONFIG           = 55;
     protected static final int EVENT_CELL_LOCATION_RESPONSE            = 56;
     protected static final int EVENT_CARRIER_CONFIG_CHANGED            = 57;
+    private static final int EVENT_POLL_STATE_REQUEST                  = 58;
+
+    /**
+     * The current service state.
+     *
+     * This is a column name in {@link android.provider.Telephony.ServiceStateTable}.
+     *
+     * Copied from packages/services/Telephony/src/com/android/phone/ServiceStateProvider.java
+     */
+    private static final String SERVICE_STATE = "service_state";
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"CARRIER_NAME_DISPLAY_BITMASK"},
@@ -386,9 +398,7 @@
                             com.android.internal.R.bool.skip_restoring_network_selection);
                     mPhone.sendSubscriptionSettings(restoreSelection);
 
-                    mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
-                            ServiceState.rilRadioTechnologyToString(
-                                    mSS.getRilDataRadioTechnology()));
+                    setDataNetworkTypeForPhone(mSS.getRilDataRadioTechnology());
 
                     if (mSpnUpdatePending) {
                         mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), mCurShowPlmn,
@@ -607,8 +617,9 @@
                 .makeEriManager(mPhone, EriManager.ERI_FROM_XML);
 
         mRatRatcheter = new RatRatcheter(mPhone);
-        mVoiceCapable = mPhone.getContext().getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable);
+        mVoiceCapable = ((TelephonyManager) mPhone.getContext()
+                .getSystemService(Context.TELEPHONY_SERVICE))
+                .isVoiceCapable();
         mUiccController = UiccController.getInstance();
 
         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
@@ -699,7 +710,7 @@
         }
 
         // If we are previously in service, we need to notify that we are out of service now.
-        if (mSS != null && mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+        if (mSS != null && mSS.getState() == ServiceState.STATE_IN_SERVICE) {
             mNetworkDetachedRegistrants.notifyRegistrants();
         }
 
@@ -728,7 +739,8 @@
         mMin = null;
         mPrlVersion = null;
         mIsMinInfoReady = false;
-        mNitzState.handleCountryUnavailable();
+        mLastNitzData = null;
+        mNitzState.handleNetworkUnavailable();
         mCellIdentity = null;
         mNewCellIdentity = null;
         mSignalStrengthUpdatedTime = System.currentTimeMillis();
@@ -765,8 +777,7 @@
         // on fields like mIsSubscriptionFromRuim (which is updated above)
         onUpdateIccAvailability();
 
-        mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
-                ServiceState.rilRadioTechnologyToString(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
+        setDataNetworkTypeForPhone(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
         // Query signal strength from the modem after service tracker is created (i.e. boot up,
         // switching between GSM and CDMA phone), because the unsolicited signal strength
         // information might come late or even never come. This will get the accurate signal
@@ -813,6 +824,10 @@
     }
     public boolean getPowerStateFromCarrier() { return !mRadioDisabledByCarrier; }
 
+    public List<PhysicalChannelConfig> getPhysicalChannelConfigList() {
+        return mLastPhysicalChannelConfigList;
+    }
+
     private SignalStrength mLastSignalStrength = null;
     @UnsupportedAppUsage
     protected boolean notifySignalStrength() {
@@ -837,7 +852,7 @@
      */
     protected void notifyVoiceRegStateRilRadioTechnologyChanged() {
         int rat = mSS.getRilVoiceRadioTechnology();
-        int vrs = mSS.getVoiceRegState();
+        int vrs = mSS.getState();
         if (DBG) log("notifyVoiceRegStateRilRadioTechnologyChanged: vrs=" + vrs + " rat=" + rat);
 
         mVoiceRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(vrs, rat));
@@ -864,8 +879,7 @@
                 registrantList.notifyResult(new Pair<>(drs, rat));
             }
         }
-        mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
-                ServiceState.rilRadioTechnologyToString(mSS.getRilDataRadioTechnology()));
+        setDataNetworkTypeForPhone(mSS.getRilDataRadioTechnology());
     }
 
     /**
@@ -876,11 +890,11 @@
     protected void useDataRegStateForDataOnlyDevices() {
         if (mVoiceCapable == false) {
             if (DBG) {
-                log("useDataRegStateForDataOnlyDevice: VoiceRegState=" + mNewSS.getVoiceRegState()
-                    + " DataRegState=" + mNewSS.getDataRegState());
+                log("useDataRegStateForDataOnlyDevice: VoiceRegState=" + mNewSS.getState()
+                        + " DataRegState=" + mNewSS.getDataRegistrationState());
             }
             // TODO: Consider not lying and instead have callers know the difference.
-            mNewSS.setVoiceRegState(mNewSS.getDataRegState());
+            mNewSS.setVoiceRegState(mNewSS.getDataRegistrationState());
         }
     }
 
@@ -889,8 +903,8 @@
         if (mPhone.getContext().getResources().
                 getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) {
             // If the phone is not registered on a network, no need to update.
-            boolean isRegistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE ||
-                    mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY;
+            boolean isRegistered = mSS.getState() == ServiceState.STATE_IN_SERVICE
+                    || mSS.getState() == ServiceState.STATE_EMERGENCY_ONLY;
             if (!isRegistered) {
                 log("updatePhoneObject: Ignore update");
                 return;
@@ -1138,20 +1152,24 @@
                         }
                     }
                 } else {
-                    // If we receive an empty message, it's probably a timeout; if there is no
-                    // pending request, drop it.
-                    if (!mIsPendingCellInfoRequest) break;
-                    // If there is a request pending, we still need to check whether it's a timeout
-                    // for the current request of whether it's leftover from a previous request.
-                    final long curTime = SystemClock.elapsedRealtime();
-                    if ((curTime - mLastCellInfoReqTime) <  CELL_INFO_LIST_QUERY_TIMEOUT) {
-                        break;
+                    synchronized (mPendingCellInfoRequests) {
+                        // If we receive an empty message, it's probably a timeout; if there is no
+                        // pending request, drop it.
+                        if (!mIsPendingCellInfoRequest) break;
+                        // If there is a request pending, we still need to check whether it's a
+                        // timeout for the current request of whether it's leftover from a
+                        // previous request.
+                        final long curTime = SystemClock.elapsedRealtime();
+                        if ((curTime - mLastCellInfoReqTime) <  CELL_INFO_LIST_QUERY_TIMEOUT) {
+                            break;
+                        }
+                        // We've received a legitimate timeout, so something has gone terribly
+                        // wrong.
+                        loge("Timeout waiting for CellInfo; (everybody panic)!");
+                        mLastCellInfoList = null;
+                        // Since the timeout is applicable, fall through and update all synchronous
+                        // callers with the failure.
                     }
-                    // We've received a legitimate timeout, so something has gone terribly wrong.
-                    loge("Timeout waiting for CellInfo; (everybody panic)!");
-                    mLastCellInfoList = null;
-                    // Since the timeout is applicable, fall through and update all synchronous
-                    // callers with the failure.
                 }
                 synchronized (mPendingCellInfoRequests) {
                     // If we have pending requests, then service them. Note that in case of a
@@ -1200,7 +1218,7 @@
                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
                 mPrevSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
                 mIsSimReady = true;
-                pollState();
+                pollStateInternal(false);
                 // Signal strength polling stops when radio is off
                 queueNextSignalStrengthPoll();
                 break;
@@ -1217,11 +1235,11 @@
                 // This will do nothing in the 'radio not available' case
                 setPowerStateToDesired();
                 // These events are modem triggered, so pollState() needs to be forced
-                modemTriggeredPollState();
+                pollStateInternal(true);
                 break;
 
             case EVENT_NETWORK_STATE_CHANGED:
-                modemTriggeredPollState();
+                pollStateInternal(true);
                 break;
 
             case EVENT_GET_SIGNAL_STRENGTH:
@@ -1245,7 +1263,7 @@
                             .getCellIdentity();
                     updateOperatorNameForCellIdentity(cellIdentity);
                     mCellIdentity = cellIdentity;
-                    mPhone.notifyLocationChanged(getCellLocation());
+                    mPhone.notifyLocationChanged(getCellIdentity());
                 }
 
                 // Release any temporary cell lock, which could have been
@@ -1358,7 +1376,7 @@
 
             case EVENT_CHECK_REPORT_GPRS:
                 if (mPhone.isPhoneTypeGsm() && mSS != null &&
-                        !isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
+                        !isGprsConsistent(mSS.getDataRegistrationState(), mSS.getState())) {
 
                     // Can't register data service while voice service is ok
                     // i.e. CREG is ok while CGREG is not
@@ -1427,7 +1445,7 @@
                 if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
                     // Subscription will be read from SIM I/O
                     if (DBG) log("Receive EVENT_RUIM_READY");
-                    pollState();
+                    pollStateInternal(false);
                 } else {
                     if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
                     getSubscriptionInfoAndStartPollingThreads();
@@ -1520,7 +1538,7 @@
                         // SID/NID/PRL is loaded. Poll service state
                         // again to update to the roaming state with
                         // the latest variables.
-                        pollState();
+                        pollStateInternal(false);
                     }
                 }
                 break;
@@ -1576,6 +1594,8 @@
                     // Notify NR frequency, NR connection status or bandwidths changed.
                     if (hasChanged) {
                         mPhone.notifyServiceStateChanged(mSS);
+                        TelephonyMetrics.getInstance().writeServiceStateChanged(
+                                mPhone.getPhoneId(), mSS);
                     }
                 }
                 break;
@@ -1583,15 +1603,15 @@
             case EVENT_CELL_LOCATION_RESPONSE:
                 ar = (AsyncResult) msg.obj;
                 if (ar == null) {
-                    loge("Invalid null response to getCellLocation!");
+                    loge("Invalid null response to getCellIdentity!");
                     break;
                 }
                 // This response means that the correct CellInfo is already cached; thus we
                 // can rely on the last cell info to already contain any cell info that is
                 // available, which means that we can return the result of the existing
-                // getCellLocation() function without any additional processing here.
+                // getCellIdentity() function without any additional processing here.
                 Message rspRspMsg = (Message) ar.userObj;
-                AsyncResult.forMessage(rspRspMsg, getCellLocation(), ar.exception);
+                AsyncResult.forMessage(rspRspMsg, getCellIdentity(), ar.exception);
                 rspRspMsg.sendToTarget();
                 break;
 
@@ -1599,6 +1619,10 @@
                 onCarrierConfigChanged();
                 break;
 
+            case EVENT_POLL_STATE_REQUEST:
+                pollStateInternal(false);
+                break;
+
             default:
                 log("Unhandled message with number: " + msg.what);
                 break;
@@ -1848,7 +1872,7 @@
                 final int dataRat = getRilDataRadioTechnologyForWwan(mNewSS);
                 if (ServiceState.isCdma(dataRat)) {
                     final boolean isVoiceInService =
-                            (mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
+                            (mNewSS.getState() == ServiceState.STATE_IN_SERVICE);
                     if (isVoiceInService) {
                         boolean isVoiceRoaming = mNewSS.getVoiceRoaming();
                         if (mNewSS.getDataRoaming() != isVoiceRoaming) {
@@ -1887,9 +1911,9 @@
                         // Use default
                         mNewSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator);
                     } else if (namMatch && !mIsInPrl) {
-                        // TODO this will be removed when we handle roaming on LTE on CDMA+LTE phones
-                        if (ServiceState.isLte(mNewSS.getRilVoiceRadioTechnology())) {
-                            log("Turn off roaming indicator as voice is LTE");
+                        // TODO: remove when we handle roaming on LTE/NR on CDMA+LTE phones
+                        if (ServiceState.isPsOnlyTech(mNewSS.getRilVoiceRadioTechnology())) {
+                            log("Turn off roaming indicator as voice is LTE or NR");
                             mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
                         } else {
                             mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
@@ -2077,9 +2101,6 @@
 
                     mGsmRoaming = regCodeIsRoaming(registrationState);
                     mNewRejectCode = reasonForDenial;
-
-                    boolean isVoiceCapable = mPhone.getContext().getResources()
-                            .getBoolean(com.android.internal.R.bool.config_voice_capable);
                 } else {
                     int roamingIndicator = voiceSpecificStates.roamingIndicator;
 
@@ -2150,6 +2171,7 @@
                 int serviceState = regCodeToServiceState(registrationState);
                 int newDataRat = ServiceState.networkTypeToRilRadioTechnology(
                         networkRegState.getAccessNetworkTechnology());
+                boolean nrHasChanged = false;
 
                 if (DBG) {
                     log("handlePollStateResultMessage: PS cellular. " + networkRegState);
@@ -2160,11 +2182,17 @@
                 // (2 or more cells) to a new cell if they camp for emergency service only.
                 if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
                     mLastPhysicalChannelConfigList = null;
-                    updateNrFrequencyRangeFromPhysicalChannelConfigs(null, mNewSS);
+                    nrHasChanged |= updateNrFrequencyRangeFromPhysicalChannelConfigs(null, mNewSS);
                 }
-                updateNrStateFromPhysicalChannelConfigs(mLastPhysicalChannelConfigList, mNewSS);
+                nrHasChanged |= updateNrStateFromPhysicalChannelConfigs(
+                        mLastPhysicalChannelConfigList, mNewSS);
                 setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
 
+                if (nrHasChanged) {
+                    TelephonyMetrics.getInstance().writeServiceStateChanged(
+                            mPhone.getPhoneId(), mSS);
+                }
+
                 if (mPhone.isPhoneTypeGsm()) {
 
                     mNewReasonDataDenied = networkRegState.getRejectCause();
@@ -2177,16 +2205,17 @@
                 } else {
 
                     // If the unsolicited signal strength comes just before data RAT family changes
-                    // (i.e. from UNKNOWN to LTE, CDMA to LTE, LTE to CDMA), the signal bar might
-                    // display the wrong information until the next unsolicited signal strength
-                    // information coming from the modem, which might take a long time to come or
-                    // even not come at all.  In order to provide the best user experience, we
-                    // query the latest signal information so it will show up on the UI on time.
+                    // (i.e. from UNKNOWN to LTE/NR, CDMA to LTE/NR, LTE/NR to CDMA), the signal bar
+                    // might display the wrong information until the next unsolicited signal
+                    // strength information coming from the modem, which might take a long time to
+                    // come or even not come at all.  In order to provide the best user experience,
+                    // we query the latest signal information so it will show up on the UI on time.
                     int oldDataRAT = getRilDataRadioTechnologyForWwan(mSS);
                     if (((oldDataRAT == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)
                             && (newDataRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))
-                            || (ServiceState.isCdma(oldDataRAT) && ServiceState.isLte(newDataRat))
-                            || (ServiceState.isLte(oldDataRAT)
+                            || (ServiceState.isCdma(oldDataRAT)
+                            && ServiceState.isPsOnlyTech(newDataRat))
+                            || (ServiceState.isPsOnlyTech(oldDataRAT)
                             && ServiceState.isCdma(newDataRat))) {
                         mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
                     }
@@ -2202,8 +2231,6 @@
             }
 
             case EVENT_POLL_STATE_OPERATOR: {
-                String brandOverride = getOperatorBrandOverride();
-                mCdnr.updateEfForBrandOverride(brandOverride);
                 if (mPhone.isPhoneTypeGsm()) {
                     String opNames[] = (String[]) ar.result;
 
@@ -2211,6 +2238,8 @@
                         mNewSS.setOperatorAlphaLongRaw(opNames[0]);
                         mNewSS.setOperatorAlphaShortRaw(opNames[1]);
                         // FIXME: Giving brandOverride higher precedence, is this desired?
+                        String brandOverride = getOperatorBrandOverride();
+                        mCdnr.updateEfForBrandOverride(brandOverride);
                         if (brandOverride != null) {
                             log("EVENT_POLL_STATE_OPERATOR: use brandOverride=" + brandOverride);
                             mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
@@ -2240,6 +2269,8 @@
                             // NV device (as opposed to CSIM)
                             mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
                         } else {
+                            String brandOverride = getOperatorBrandOverride();
+                            mCdnr.updateEfForBrandOverride(brandOverride);
                             if (brandOverride != null) {
                                 mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
                             } else {
@@ -2465,7 +2496,8 @@
                 setRoamingOn();
             }
 
-            if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
+            if (TelephonyUtils.IS_DEBUGGABLE
+                    && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
                 mNewSS.setVoiceRoaming(true);
                 mNewSS.setDataRoaming(true);
             }
@@ -2705,7 +2737,7 @@
                 // is satisfied or SPN override is enabled for this carrier.
 
                 // Handle Flight Mode
-                if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) {
+                if (mSS.getState() == ServiceState.STATE_POWER_OFF) {
                     wfcVoiceSpnFormat = wfcFlightSpnFormat;
                 }
 
@@ -2718,7 +2750,7 @@
                 // Show PLMN + Wi-Fi Calling if there is no valid SPN in the above case
                 String originalPlmn = plmn.trim();
                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
-            } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF
+            } else if (mSS.getState() == ServiceState.STATE_POWER_OFF
                     || (showPlmn && TextUtils.equals(spn, plmn))) {
                 // airplane mode or spn equals plmn, do not show spn
                 spn = null;
@@ -2920,7 +2952,7 @@
      */
     @UnsupportedAppUsage
     public int getCurrentDataConnectionState() {
-        return mSS.getDataRegState();
+        return mSS.getDataRegistrationState();
     }
 
     /**
@@ -2937,7 +2969,7 @@
             // There are cases where we we would setup data connection even data is not yet
             // attached. In these cases we check voice rat.
             if (radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
-                    && mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) {
+                    && mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE) {
                 radioTechnology = mSS.getRilVoiceRadioTechnology();
             }
             // Concurrent voice and data is not allowed for 2G technologies. It's allowed in other
@@ -2992,18 +3024,10 @@
      */
     @UnsupportedAppUsage
     public void pollState() {
-        pollState(false);
-    }
-    /**
-     * We insist on polling even if the radio says its off.
-     * Used when we get a network changed notification
-     * but the radio is off - part of iwlan hack
-     */
-    private void modemTriggeredPollState() {
-        pollState(true);
+        sendEmptyMessage(EVENT_POLL_STATE_REQUEST);
     }
 
-    public void pollState(boolean modemTriggered) {
+    private void pollStateInternal(boolean modemTriggered) {
         mPollingContext = new int[1];
         mPollingContext[0] = 0;
 
@@ -3014,7 +3038,8 @@
                 mNewSS.setStateOutOfService();
                 mNewCellIdentity = null;
                 setSignalStrengthDefaultValues();
-                mNitzState.handleCountryUnavailable();
+                mLastNitzData = null;
+                mNitzState.handleNetworkUnavailable();
                 pollStateDone();
                 break;
 
@@ -3022,7 +3047,8 @@
                 mNewSS.setStateOff();
                 mNewCellIdentity = null;
                 setSignalStrengthDefaultValues();
-                mNitzState.handleCountryUnavailable();
+                mLastNitzData = null;
+                mNitzState.handleNetworkUnavailable();
                 // don't poll when device is shutting down or the poll was not modemTrigged
                 // (they sent us new radio data) and current network is not IWLAN
                 if (mDeviceShuttingDown ||
@@ -3071,14 +3097,15 @@
             updateRoamingState();
         }
 
-        if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
+        if (TelephonyUtils.IS_DEBUGGABLE
+                && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
             mNewSS.setVoiceRoaming(true);
             mNewSS.setDataRoaming(true);
         }
         useDataRegStateForDataOnlyDevices();
         processIwlanRegistrationInfo();
 
-        if (Build.IS_DEBUGGABLE && mPhone.mTelephonyTester != null) {
+        if (TelephonyUtils.IS_DEBUGGABLE && mPhone.mTelephonyTester != null) {
             mPhone.mTelephonyTester.overrideServiceState(mNewSS);
         }
 
@@ -3088,20 +3115,21 @@
                     + " oldMaxDataCalls=" + mMaxDataCalls
                     + " mNewMaxDataCalls=" + mNewMaxDataCalls
                     + " oldReasonDataDenied=" + mReasonDataDenied
-                    + " mNewReasonDataDenied=" + mNewReasonDataDenied);
+                    + " mNewReasonDataDeni"
+                    + "ed=" + mNewReasonDataDenied);
         }
 
         boolean hasRegistered =
-                mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
-                        && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
+                mSS.getState() != ServiceState.STATE_IN_SERVICE
+                        && mNewSS.getState() == ServiceState.STATE_IN_SERVICE;
 
         boolean hasDeregistered =
-                mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
-                        && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
+                mSS.getState() == ServiceState.STATE_IN_SERVICE
+                        && mNewSS.getState() != ServiceState.STATE_IN_SERVICE;
 
         boolean hasAirplaneModeOnChanged =
-                mSS.getVoiceRegState() != ServiceState.STATE_POWER_OFF
-                        && mNewSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF;
+                mSS.getState() != ServiceState.STATE_POWER_OFF
+                        && mNewSS.getState() == ServiceState.STATE_POWER_OFF;
 
         SparseBooleanArray hasDataAttached = new SparseBooleanArray(
                 mTransportManager.getAvailableTransports().length);
@@ -3157,7 +3185,7 @@
                 && (mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology());
 
         boolean hasVoiceRegStateChanged =
-                mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
+                mSS.getState() != mNewSS.getState();
 
         boolean hasNrFrequencyRangeChanged =
                 mSS.getNrFrequencyRange() != mNewSS.getNrFrequencyRange();
@@ -3176,7 +3204,8 @@
 
         // ratchet the new tech up through its rat family but don't drop back down
         // until cell change or device is OOS
-        boolean isDataInService = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+        boolean isDataInService = mNewSS.getDataRegistrationState()
+                == ServiceState.STATE_IN_SERVICE;
         if (isDataInService) {
             mRatRatcheter.ratchet(mSS, mNewSS, hasLocationChanged);
         }
@@ -3204,17 +3233,15 @@
         if (mPhone.isPhoneTypeCdmaLte()) {
             final int wwanDataRat = getRilDataRadioTechnologyForWwan(mSS);
             final int newWwanDataRat = getRilDataRadioTechnologyForWwan(mNewSS);
-            has4gHandoff = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
-                    && ((ServiceState.isLte(wwanDataRat)
+            has4gHandoff = mNewSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE
+                    && ((ServiceState.isPsOnlyTech(wwanDataRat)
                     && (newWwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
-                    ||
-                    ((wwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)
-                    && ServiceState.isLte(newWwanDataRat)));
+                    || ((wwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)
+                    && ServiceState.isPsOnlyTech(newWwanDataRat)));
 
-            hasMultiApnSupport = ((ServiceState.isLte(newWwanDataRat)
+            hasMultiApnSupport = ((ServiceState.isPsOnlyTech(newWwanDataRat)
                     || (newWwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
-                    &&
-                    (!ServiceState.isLte(wwanDataRat)
+                    && (!ServiceState.isPsOnlyTech(wwanDataRat)
                     && (wwanDataRat != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
 
             hasLostMultiApnSupport = ((newWwanDataRat >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)
@@ -3250,8 +3277,8 @@
         if (hasVoiceRegStateChanged || anyDataRegChanged) {
             EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE :
                             EventLogTags.CDMA_SERVICE_STATE_CHANGE,
-                    mSS.getVoiceRegState(), mSS.getDataRegState(),
-                    mNewSS.getVoiceRegState(), mNewSS.getDataRegState());
+                    mSS.getState(), mSS.getDataRegistrationState(),
+                    mNewSS.getState(), mNewSS.getDataRegistrationState());
         }
 
         if (mPhone.isPhoneTypeGsm()) {
@@ -3278,7 +3305,7 @@
             }
 
             if (hasCssIndicatorChanged) {
-                mPhone.notifyDataConnection();
+                mPhone.notifyAllActiveDataConnections();
             }
 
             mReasonDataDenied = mNewReasonDataDenied;
@@ -3398,7 +3425,9 @@
             mPhone.getContext().getContentResolver()
                     .insert(getUriForSubscriptionId(mPhone.getSubId()),
                             getContentValuesForServiceState(mSS));
+        }
 
+        if (hasChanged || hasNrStateChanged) {
             TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS);
         }
 
@@ -3432,7 +3461,7 @@
                     // that ServiceState#getRilDataRadioTechnology has changed.
                     || hasDataTransportPreferenceChanged) {
                 notifyDataRegStateRilRadioTechnologyChanged(transport);
-                mPhone.notifyDataConnection();
+                mPhone.notifyAllActiveDataConnections();
             }
 
             if (hasDataAttached.get(transport)) {
@@ -3481,11 +3510,11 @@
         }
 
         if (hasLocationChanged) {
-            mPhone.notifyLocationChanged(getCellLocation());
+            mPhone.notifyLocationChanged(getCellIdentity());
         }
 
         if (mPhone.isPhoneTypeGsm()) {
-            if (!isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
+            if (!isGprsConsistent(mSS.getDataRegistrationState(), mSS.getState())) {
                 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
                     mStartedGprsRegCheck = true;
 
@@ -3508,7 +3537,7 @@
             if ((mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
                     && (!mIsSubscriptionFromRuim)) {
                 // Now the Phone sees the new ServiceState so it can get the new ERI text
-                if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+                if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
                     eriText = mPhone.getCdmaEriText();
                 } else {
                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for
@@ -3522,22 +3551,22 @@
                     mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null;
             if (!hasBrandOverride && (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
                     && (mEriManager.isEriFileLoaded())
-                    && (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology())
+                    && (!ServiceState.isPsOnlyTech(mSS.getRilVoiceRadioTechnology())
                     || mPhone.getContext().getResources().getBoolean(com.android.internal.R
                     .bool.config_LTE_eri_for_network_name))) {
                 // Only when CDMA is in service, ERI will take effect
                 eriText = mSS.getOperatorAlpha();
                 // Now the Phone sees the new ServiceState so it can get the new ERI text
-                if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+                if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
                     eriText = mPhone.getCdmaEriText();
-                } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) {
+                } else if (mSS.getState() == ServiceState.STATE_POWER_OFF) {
                     eriText = getServiceProviderName();
                     if (TextUtils.isEmpty(eriText)) {
                         // Sets operator alpha property by retrieving from
                         // build-time system property
                         eriText = SystemProperties.get("ro.cdma.home.operator.alpha");
                     }
-                } else if (mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) {
+                } else if (mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE) {
                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
                     // for mRegistrationState 0,2,3 and 4
                     eriText = mPhone.getContext()
@@ -3547,7 +3576,7 @@
 
             if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY &&
                     mIccRecords != null && getCombinedRegState(mSS) == ServiceState.STATE_IN_SERVICE
-                    && !ServiceState.isLte(mSS.getRilVoiceRadioTechnology())) {
+                    && !ServiceState.isPsOnlyTech(mSS.getRilVoiceRadioTechnology())) {
                 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
                 // one configured in SIM, use operator name from CSIM record. Note that ERI, SID,
                 // and NID are CDMA only, not applicable to LTE.
@@ -3686,16 +3715,19 @@
 
     @UnsupportedAppUsage
     protected void setOperatorIdd(String operatorNumeric) {
+        if (mPhone.getUnitTestMode()) {
+            return;
+        }
+
         // Retrieve the current country information
         // with the MCC got from opeatorNumeric.
         String idd = mHbpcdUtils.getIddByMcc(
                 Integer.parseInt(operatorNumeric.substring(0,3)));
         if (idd != null && !idd.isEmpty()) {
-            mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING,
-                    idd);
+            TelephonyProperties.operator_idp_string(idd);
         } else {
             // use default "+", since we don't know the current IDP
-            mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, "+");
+            TelephonyProperties.operator_idp_string("+");
         }
     }
 
@@ -3955,9 +3987,9 @@
     }
 
     /**
-     * Get CellLocation from the ServiceState if available or guess from cached CellInfo
+     * Get CellIdentity from the ServiceState if available or guess from cached
      *
-     * Get the CellLocation by first checking if ServiceState has a current CID. If so
+     * Get the CellIdentity by first checking if ServiceState has a current CID. If so
      * then return that info. Otherwise, check the latest List<CellInfo> and return the first GSM or
      * WCDMA result that appears. If no GSM or WCDMA results, then return an LTE result. The
      * behavior is kept consistent for backwards compatibility; (do not apply logic to determine
@@ -3965,18 +3997,19 @@
      *
      * @return the current cell location if known or a non-null "empty" cell location
      */
-    public CellLocation getCellLocation() {
-        if (mCellIdentity != null) return mCellIdentity.asCellLocation();
+    @NonNull
+    public CellIdentity getCellIdentity() {
+        if (mCellIdentity != null) return mCellIdentity;
 
-        CellLocation cl = getCellLocationFromCellInfo(getAllCellInfo());
-        if (cl != null) return cl;
+        CellIdentity ci = getCellIdentityFromCellInfo(getAllCellInfo());
+        if (ci != null) return ci;
 
         return mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
-                ? new CdmaCellLocation() : new GsmCellLocation();
+                ? new CellIdentityCdma() : new CellIdentityGsm();
     }
 
     /**
-     * Get CellLocation from the ServiceState if available or guess from CellInfo
+     * Get CellIdentity from the ServiceState if available or guess from CellInfo
      *
      * Get the CellLocation by first checking if ServiceState has a current CID. If so
      * then return that info. Otherwise, query AllCellInfo and return the first GSM or
@@ -3987,9 +4020,9 @@
      * @param workSource calling WorkSource
      * @param rspMsg the response message which must be non-null
      */
-    public void requestCellLocation(WorkSource workSource, Message rspMsg) {
+    public void requestCellIdentity(WorkSource workSource, Message rspMsg) {
         if (mCellIdentity != null) {
-            AsyncResult.forMessage(rspMsg, mCellIdentity.asCellLocation(), null);
+            AsyncResult.forMessage(rspMsg, mCellIdentity, null);
             rspMsg.sendToTarget();
             return;
         }
@@ -3998,16 +4031,16 @@
         requestAllCellInfo(workSource, cellLocRsp);
     }
 
-    /* Find and return a CellLocation from CellInfo
+    /* Find and return a CellIdentity from CellInfo
      *
      * This method returns the first GSM or WCDMA result that appears in List<CellInfo>. If no GSM
      * or  WCDMA results are found, then it returns an LTE result. The behavior is kept consistent
      * for backwards compatibility; (do not apply logic to determine why the behavior is this way).
      *
-     * @return the current cell location from CellInfo or null
+     * @return the current CellIdentity from CellInfo or null
      */
-    private static CellLocation getCellLocationFromCellInfo(List<CellInfo> info) {
-        CellLocation cl = null;
+    private static CellIdentity getCellIdentityFromCellInfo(List<CellInfo> info) {
+        CellIdentity cl = null;
         if (info != null && info.size() > 0) {
             CellIdentity fallbackLteCid = null; // We prefer not to use LTE
             for (CellInfo ci : info) {
@@ -4017,12 +4050,12 @@
                     continue;
                 }
                 if (getCidFromCellIdentity(c) != -1) {
-                    cl = c.asCellLocation();
+                    cl = c;
                     break;
                 }
             }
             if (cl == null && fallbackLteCid != null) {
-                cl = fallbackLteCid.asCellLocation();
+                cl = fallbackLteCid;
             }
         }
         return cl;
@@ -4087,7 +4120,8 @@
         Context context = mPhone.getContext();
 
         SubscriptionInfo info = mSubscriptionController
-                .getActiveSubscriptionInfo(mPhone.getSubId(), context.getOpPackageName());
+                .getActiveSubscriptionInfo(mPhone.getSubId(), context.getOpPackageName(),
+                        null);
 
         //if subscription is part of a group and non-primary, suppress all notifications
         if (info == null || (info.isOpportunistic() && info.getGroupUuid() != null)) {
@@ -4446,7 +4480,7 @@
         Registrant r = new Registrant(h, what, obj);
 
         mNetworkAttachedRegistrants.add(r);
-        if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+        if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
             r.notifyRegistrant();
         }
     }
@@ -4465,7 +4499,7 @@
         Registrant r = new Registrant(h, what, obj);
 
         mNetworkDetachedRegistrants.add(r);
-        if (mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
+        if (mSS.getState() != ServiceState.STATE_IN_SERVICE) {
             r.notifyRegistrant();
         }
     }
@@ -4696,7 +4730,7 @@
         // Sometimes the network registration information comes before carrier config is ready.
         // For some cases like roaming/non-roaming overriding, we need carrier config. So it's
         // important to poll state again when carrier config is ready.
-        pollState();
+        pollStateInternal(false);
     }
 
     private void updateLteEarfcnLists(PersistableBundle config) {
@@ -4710,12 +4744,44 @@
     }
 
     private void updateReportingCriteria(PersistableBundle config) {
-        mPhone.setSignalStrengthReportingCriteria(
+        int lteMeasurementEnabled = config.getInt(CarrierConfigManager
+                .KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT, CellSignalStrengthLte.USE_RSRP);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRP,
                 config.getIntArray(CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY),
-                AccessNetworkType.EUTRAN);
-        mPhone.setSignalStrengthReportingCriteria(
+                AccessNetworkType.EUTRAN,
+                (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSRP) != 0);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSCP,
                 config.getIntArray(CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY),
-                AccessNetworkType.UTRAN);
+                AccessNetworkType.UTRAN, true);
+        mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSI,
+                config.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY),
+                AccessNetworkType.GERAN, true);
+
+        if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSRQ,
+                    config.getIntArray(CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY),
+                    AccessNetworkType.EUTRAN,
+                    (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSRQ) != 0);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_RSSNR,
+                    config.getIntArray(CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY),
+                    AccessNetworkType.EUTRAN,
+                    (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSSNR) != 0);
+
+            int measurementEnabled = config.getInt(CarrierConfigManager
+                    .KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, CellSignalStrengthNr.USE_SSRSRP);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRP,
+                    config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY),
+                    AccessNetworkType.NGRAN,
+                    (measurementEnabled & CellSignalStrengthNr.USE_SSRSRP) != 0);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSRSRQ,
+                    config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY),
+                    AccessNetworkType.NGRAN,
+                    (measurementEnabled & CellSignalStrengthNr.USE_SSRSRQ) != 0);
+            mPhone.setSignalStrengthReportingCriteria(SignalThresholdInfo.SIGNAL_SSSINR,
+                    config.getIntArray(CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY),
+                    AccessNetworkType.NGRAN,
+                    (measurementEnabled & CellSignalStrengthNr.USE_SSSINR) != 0);
+        }
     }
 
     private void updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn) {
@@ -4899,7 +4965,8 @@
         if (!isStale) return false;
 
         List<SubscriptionInfo> subInfoList = SubscriptionController.getInstance()
-                .getActiveSubscriptionInfoList(mPhone.getContext().getOpPackageName());
+                .getActiveSubscriptionInfoList(mPhone.getContext().getOpPackageName(),
+                        null);
         for (SubscriptionInfo info : subInfoList) {
             // If we have an active opportunistic subscription whose data is IN_SERVICE, we needs
             // to get signal strength to decide data switching threshold. In this case, we poll
@@ -4908,7 +4975,7 @@
                 TelephonyManager tm = TelephonyManager.from(mPhone.getContext())
                         .createForSubscriptionId(info.getSubscriptionId());
                 ServiceState ss = tm.getServiceState();
-                if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+                if (ss != null && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
                     return true;
                 }
             }
@@ -4953,7 +5020,7 @@
         mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
 
         // Get Registration Information
-        pollState();
+        pollStateInternal(false);
     }
 
     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
@@ -5179,12 +5246,12 @@
     @UnsupportedAppUsage
     protected void setRoamingType(ServiceState currentServiceState) {
         final boolean isVoiceInService =
-                (currentServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
+                (currentServiceState.getState() == ServiceState.STATE_IN_SERVICE);
         if (isVoiceInService) {
             if (currentServiceState.getVoiceRoaming()) {
                 if (mPhone.isPhoneTypeGsm()) {
                     // check roaming type by MCC
-                    if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) {
+                    if (inSameCountry(currentServiceState.getOperatorNumeric())) {
                         currentServiceState.setVoiceRoamingType(
                                 ServiceState.ROAMING_TYPE_DOMESTIC);
                     } else {
@@ -5208,7 +5275,7 @@
                         }
                     } else {
                         // check roaming type by MCC
-                        if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) {
+                        if (inSameCountry(currentServiceState.getOperatorNumeric())) {
                             currentServiceState.setVoiceRoamingType(
                                     ServiceState.ROAMING_TYPE_DOMESTIC);
                         } else {
@@ -5222,7 +5289,7 @@
             }
         }
         final boolean isDataInService =
-                (currentServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE);
+                (currentServiceState.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE);
         final int dataRegType = getRilDataRadioTechnologyForWwan(currentServiceState);
         if (isDataInService) {
             if (!currentServiceState.getDataRoaming()) {
@@ -5255,7 +5322,7 @@
                         }
                     } else {
                         // take it as 3GPP roaming
-                        if (inSameCountry(currentServiceState.getDataOperatorNumeric())) {
+                        if (inSameCountry(currentServiceState.getOperatorNumeric())) {
                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC);
                         } else {
                             currentServiceState.setDataRoamingType(
@@ -5423,8 +5490,8 @@
      * @param ss service state.
      */
     protected int getCombinedRegState(ServiceState ss) {
-        int regState = ss.getVoiceRegState();
-        int dataRegState = ss.getDataRegState();
+        int regState = ss.getState();
+        int dataRegState = ss.getDataRegistrationState();
         if ((regState == ServiceState.STATE_OUT_OF_SERVICE
                 || regState == ServiceState.STATE_POWER_OFF)
                 && (dataRegState == ServiceState.STATE_IN_SERVICE)) {
@@ -5591,4 +5658,31 @@
 
         return idSet;
     }
+
+    private void setDataNetworkTypeForPhone(int type) {
+        if (mPhone.getUnitTestMode()) {
+            return;
+        }
+        TelephonyManager tm = (TelephonyManager) mPhone.getContext().getSystemService(
+                Context.TELEPHONY_SERVICE);
+        tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), type);
+    }
+
+    /**
+     * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance.
+     *
+     * Copied from packages/services/Telephony/src/com/android/phone/ServiceStateProvider.java
+     *
+     * @param state the ServiceState to convert into ContentValues
+     * @return the convertedContentValues instance
+     */
+    private ContentValues getContentValuesForServiceState(ServiceState state) {
+        ContentValues values = new ContentValues();
+        final Parcel p = Parcel.obtain();
+        state.writeToParcel(p, 0);
+        // Turn the parcel to byte array. Safe to do this because the content values were never
+        // written into a persistent storage. ServiceStateProvider keeps values in the memory.
+        values.put(SERVICE_STATE, p.marshall());
+        return values;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/SettingsObserver.java b/src/java/com/android/internal/telephony/SettingsObserver.java
index 2253c36..e480b05 100644
--- a/src/java/com/android/internal/telephony/SettingsObserver.java
+++ b/src/java/com/android/internal/telephony/SettingsObserver.java
@@ -21,7 +21,8 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/src/java/com/android/internal/telephony/SimActivationTracker.java b/src/java/com/android/internal/telephony/SimActivationTracker.java
index 8fd6eed..2daf858 100644
--- a/src/java/com/android/internal/telephony/SimActivationTracker.java
+++ b/src/java/com/android/internal/telephony/SimActivationTracker.java
@@ -15,25 +15,24 @@
  */
 package com.android.internal.telephony;
 
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATED;
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATING;
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED;
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_RESTRICTED;
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.telephony.Rlog;
 import android.util.LocalLog;
 import android.util.Log;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.security.InvalidParameterException;
-
-import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATED;
-import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED;
-import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
-import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_RESTRICTED;
-import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATING;
 
 public class SimActivationTracker {
     /**
diff --git a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index a1d8faa..445b0ef 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -27,12 +27,12 @@
 import android.os.PersistableBundle;
 import android.os.UserManager;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 
 import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
 import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.HashSet;
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 0fce4d2..6c71690 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -18,28 +18,28 @@
 
 package com.android.internal.telephony;
 
-import static com.android.internal.util.DumpUtils.checkDumpPermission;
+import static com.android.internal.telephony.util.TelephonyUtils.checkDumpPermission;
 
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
-import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.net.Uri;
+import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.ServiceManager;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.IFinancialSmsCallback;
-import android.telephony.Rlog;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SmsManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -80,6 +80,9 @@
     @Override
     public boolean updateMessageOnIccEfForSubscriber(int subId, String callingPackage, int index,
             int status, byte[] pdu) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             return iccSmsIntMgr.updateMessageOnIccEf(callingPackage, index, status, pdu);
@@ -94,6 +97,9 @@
     @Override
     public boolean copyMessageToIccEfForSubscriber(int subId, String callingPackage, int status,
             byte[] pdu, byte[] smsc) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             return iccSmsIntMgr.copyMessageToIccEf(callingPackage, status, pdu, smsc);
@@ -107,6 +113,9 @@
     @UnsupportedAppUsage
     @Override
     public List<SmsRawData> getAllMessagesFromIccEfForSubscriber(int subId, String callingPackage) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             return iccSmsIntMgr.getAllMessagesFromIccEf(callingPackage);
@@ -122,6 +131,9 @@
     public void sendDataForSubscriber(int subId, String callingPackage, String destAddr,
             String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
             PendingIntent deliveryIntent) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             iccSmsIntMgr.sendData(callingPackage, destAddr, scAddr, destPort, data,
@@ -156,10 +168,17 @@
         }
     }
 
+    private String getCallingPackage() {
+        return mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
+    }
+
     @Override
     public void sendTextForSubscriber(int subId, String callingPackage, String destAddr,
             String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
             boolean persistMessageForNonDefaultSmsApp) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         if (!getSmsPermissions(subId).checkCallingCanSendText(persistMessageForNonDefaultSmsApp,
                 callingPackage, "Sending SMS message")) {
             sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
@@ -189,7 +208,7 @@
     private void sendBluetoothText(SubscriptionInfo info, String destAddr,
             String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
         BtSmsInterfaceManager btSmsInterfaceManager = new BtSmsInterfaceManager();
-        btSmsInterfaceManager.sendText(destAddr, text, sentIntent, deliveryIntent, info);
+        btSmsInterfaceManager.sendText(mContext, destAddr, text, sentIntent, deliveryIntent, info);
     }
 
     private void sendIccText(int subId, String callingPackage, String destAddr,
@@ -233,6 +252,9 @@
             String destAddr, String scAddr, String parts, PendingIntent sentIntent,
             PendingIntent deliveryIntent, boolean persistMessage, int priority,
             boolean expectMore, int validityPeriod) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             iccSmsIntMgr.sendTextWithOptions(callingPackage, destAddr, scAddr, parts, sentIntent,
@@ -248,6 +270,11 @@
     public void sendMultipartTextForSubscriber(int subId, String callingPackage, String destAddr,
             String scAddr, List<String> parts, List<PendingIntent> sentIntents,
             List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp) {
+        // This is different from the checking of other method. It prefers the package name
+        // returned by getCallPackage() for backward-compatibility.
+        if (getCallingPackage() != null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             iccSmsIntMgr.sendMultipartText(callingPackage, destAddr, scAddr, parts, sentIntents,
@@ -264,6 +291,9 @@
             String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents,
             List<PendingIntent> deliveryIntents, boolean persistMessage, int priority,
             boolean expectMore, int validityPeriod) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             iccSmsIntMgr.sendMultipartTextWithOptions(callingPackage, destAddr, scAddr, parts,
@@ -367,7 +397,7 @@
 
     @Override
     public boolean isSmsSimPickActivityNeeded(int subId) {
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
+        final Context context = mContext.getApplicationContext();
         ActivityManager am = context.getSystemService(ActivityManager.class);
         // Don't show the SMS SIM Pick activity if it is not foreground.
         boolean isCallingProcessForeground = am != null
@@ -502,29 +532,155 @@
     }
 
     @Override
+    public Bundle getCarrierConfigValuesForSubscriber(int subId) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final CarrierConfigManager configManager =
+                    (CarrierConfigManager)
+                            mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            return getMmsConfig(configManager.getConfigForSubId(subId));
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Filters a bundle to only contain MMS config variables.
+     *
+     * This is for use with bundles returned by CarrierConfigManager which contain MMS config and
+     * unrelated config. It is assumed that all MMS_CONFIG_* keys are present in the supplied
+     * bundle.
+     *
+     * @param config a Bundle that contains MMS config variables and possibly more.
+     * @return a new Bundle that only contains the MMS_CONFIG_* keys defined in SmsManager.
+     */
+    private static Bundle getMmsConfig(BaseBundle config) {
+        Bundle filtered = new Bundle();
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_APPEND_TRANSACTION_ID,
+                config.getBoolean(SmsManager.MMS_CONFIG_APPEND_TRANSACTION_ID));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_MMS_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_MMS_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_ALIAS_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_ALIAS_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_ALLOW_ATTACH_AUDIO,
+                config.getBoolean(SmsManager.MMS_CONFIG_ALLOW_ATTACH_AUDIO));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_MULTIPART_SMS_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_MULTIPART_SMS_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
+                config.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
+                config.getBoolean(SmsManager.MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_MMS_READ_REPORT_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_MMS_READ_REPORT_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED,
+                config.getBoolean(SmsManager.MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_CLOSE_CONNECTION,
+                config.getBoolean(SmsManager.MMS_CONFIG_CLOSE_CONNECTION));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE,
+                config.getInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_MAX_IMAGE_WIDTH,
+                config.getInt(SmsManager.MMS_CONFIG_MAX_IMAGE_WIDTH));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_MAX_IMAGE_HEIGHT,
+                config.getInt(SmsManager.MMS_CONFIG_MAX_IMAGE_HEIGHT));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_RECIPIENT_LIMIT,
+                config.getInt(SmsManager.MMS_CONFIG_RECIPIENT_LIMIT));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_ALIAS_MIN_CHARS,
+                config.getInt(SmsManager.MMS_CONFIG_ALIAS_MIN_CHARS));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_ALIAS_MAX_CHARS,
+                config.getInt(SmsManager.MMS_CONFIG_ALIAS_MAX_CHARS));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD,
+                config.getInt(SmsManager.MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
+                config.getInt(SmsManager.MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE,
+                config.getInt(SmsManager.MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_SUBJECT_MAX_LENGTH,
+                config.getInt(SmsManager.MMS_CONFIG_SUBJECT_MAX_LENGTH));
+        filtered.putInt(
+                SmsManager.MMS_CONFIG_HTTP_SOCKET_TIMEOUT,
+                config.getInt(SmsManager.MMS_CONFIG_HTTP_SOCKET_TIMEOUT));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_UA_PROF_TAG_NAME,
+                config.getString(SmsManager.MMS_CONFIG_UA_PROF_TAG_NAME));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_USER_AGENT,
+                config.getString(SmsManager.MMS_CONFIG_USER_AGENT));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_UA_PROF_URL,
+                config.getString(SmsManager.MMS_CONFIG_UA_PROF_URL));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_HTTP_PARAMS,
+                config.getString(SmsManager.MMS_CONFIG_HTTP_PARAMS));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_EMAIL_GATEWAY_NUMBER,
+                config.getString(SmsManager.MMS_CONFIG_EMAIL_GATEWAY_NUMBER));
+        filtered.putString(
+                SmsManager.MMS_CONFIG_NAI_SUFFIX,
+                config.getString(SmsManager.MMS_CONFIG_NAI_SUFFIX));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS,
+                config.getBoolean(SmsManager.MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS));
+        filtered.putBoolean(
+                SmsManager.MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
+                config.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER));
+        return filtered;
+    }
+
+    @Override
     public String createAppSpecificSmsTokenWithPackageInfo(
             int subId, String callingPkg, String prefixes, PendingIntent intent) {
+        if (callingPkg == null) {
+            callingPkg = getCallingPackage();
+        }
         return getPhone(subId).getAppSmsManager().createAppSpecificSmsTokenWithPackageInfo(
                 subId, callingPkg, prefixes, intent);
     }
 
     @Override
     public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
+        if (callingPkg == null) {
+            callingPkg = getCallingPackage();
+        }
         return getPhone(subId).getAppSmsManager().createAppSpecificSmsToken(callingPkg, intent);
     }
 
     @Override
-    public void getSmsMessagesForFinancialApp(
-            int subId, String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-        getPhone(subId).getAppSmsManager().getSmsMessagesForFinancialApp(
-                callingPkg, params, callback);
-    }
-
-    @Override
-    public int checkSmsShortCodeDestination(
-            int subId, String callingPackage, String destAddress, String countryIso) {
+    public int checkSmsShortCodeDestination(int subId, String callingPackage,
+            String callingFeatureId, String destAddress, String countryIso) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(getPhone(subId).getContext(),
-                subId, callingPackage, "checkSmsShortCodeDestination")) {
+                subId, callingPackage, callingFeatureId, "checkSmsShortCodeDestination")) {
             return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
         }
         final long identity = Binder.clearCallingIdentity();
@@ -551,11 +707,11 @@
         }
     }
 
-    /**
-     * Triggered by `adb shell dumpsys isms`
-     */
     @Override
     public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             return iccSmsIntMgr.getSmscAddressFromIccEf(callingPackage);
@@ -569,6 +725,9 @@
     @Override
     public boolean setSmscAddressOnIccEfForSubscriber(
             String smsc, int subId, String callingPackage) {
+        if (callingPackage == null) {
+            callingPackage = getCallingPackage();
+        }
         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
         if (iccSmsIntMgr != null) {
             return iccSmsIntMgr.setSmscAddressOnIccEf(callingPackage, smsc);
@@ -579,6 +738,9 @@
         }
     }
 
+    /**
+     * Triggered by `adb shell dumpsys isms`
+     */
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!checkDumpPermission(mContext, LOG_TAG, pw)) {
@@ -635,4 +797,19 @@
                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         return manager.getActiveSubscriptionInfo(subId);
     }
+
+    /**
+     * Get the capacity count of sms on Icc card.
+     */
+    @Override
+    public int getSmsCapacityOnIccForSubscriber(int subId) {
+        IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
+
+        if (iccSmsIntMgr != null ) {
+            return iccSmsIntMgr.getSmsCapacityOnIcc();
+        } else {
+            Rlog.e(LOG_TAG, "iccSmsIntMgr is null for " + " subId: " + subId);
+            return 0;
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 6b7c8a3..e9ea3d9 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -36,7 +36,6 @@
 import android.os.UserManager;
 import android.provider.Telephony.Sms;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -47,6 +46,7 @@
 import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
 import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
 import com.android.internal.telephony.gsm.GsmSMSDispatcher;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -432,82 +432,81 @@
      */
     public void sendRetrySms(SMSDispatcher.SmsTracker tracker) {
         String oldFormat = tracker.mFormat;
+        boolean retryUsingImsService = false;
 
-        // newFormat will be based on voice technology
+        if (!tracker.mUsesImsServiceForIms && mImsSmsDispatcher.isAvailable()) {
+            // If this tracker has not been handled by ImsSmsDispatcher yet and IMS Service is
+            // available now, retry this failed tracker using IMS Service.
+            retryUsingImsService = true;
+        }
+
+        // If retryUsingImsService is true, newFormat will be IMS SMS format. Otherwise, newFormat
+        // will be based on voice technology.
         String newFormat =
-                (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType())
-                        ? mCdmaDispatcher.getFormat() : mGsmDispatcher.getFormat();
+                retryUsingImsService
+                        ? mImsSmsDispatcher.getFormat()
+                        : (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType())
+                                ? mCdmaDispatcher.getFormat()
+                                : mGsmDispatcher.getFormat();
 
-        // was previously sent sms format match with voice tech?
-        if (oldFormat.equals(newFormat)) {
-            if (isCdmaFormat(newFormat)) {
-                Rlog.d(TAG, "old format matched new format (cdma)");
-                mCdmaDispatcher.sendSms(tracker);
-                return;
-            } else {
-                Rlog.d(TAG, "old format matched new format (gsm)");
-                mGsmDispatcher.sendSms(tracker);
+        Rlog.d(TAG, "old format(" + oldFormat + ") ==> new format (" + newFormat + ")");
+        if (!oldFormat.equals(newFormat)) {
+            // format didn't match, need to re-encode.
+            HashMap map = tracker.getData();
+
+            // to re-encode, fields needed are: scAddr, destAddr and text if originally sent as
+            // sendText or data and destPort if originally sent as sendData.
+            if (!(map.containsKey("scAddr") && map.containsKey("destAddr")
+                    && (map.containsKey("text")
+                    || (map.containsKey("data") && map.containsKey("destPort"))))) {
+                // should never come here...
+                Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
+                tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
                 return;
             }
-        }
+            String scAddr = (String) map.get("scAddr");
+            String destAddr = (String) map.get("destAddr");
 
-        // format didn't match, need to re-encode.
-        HashMap map = tracker.getData();
+            SmsMessageBase.SubmitPduBase pdu = null;
+            // figure out from tracker if this was sendText/Data
+            if (map.containsKey("text")) {
+                Rlog.d(TAG, "sms failed was text");
+                String text = (String) map.get("text");
 
-        // to re-encode, fields needed are:  scAddr, destAddr, and
-        //   text if originally sent as sendText or
-        //   data and destPort if originally sent as sendData.
-        if (!(map.containsKey("scAddr") && map.containsKey("destAddr")
-                && (map.containsKey("text")
-                || (map.containsKey("data") && map.containsKey("destPort"))))) {
-            // should never come here...
-            Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
-            tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
-            return;
-        }
-        String scAddr = (String) map.get("scAddr");
-        String destAddr = (String) map.get("destAddr");
+                if (isCdmaFormat(newFormat)) {
+                    pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+                            scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+                } else {
+                    pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
+                            scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+                }
+            } else if (map.containsKey("data")) {
+                Rlog.d(TAG, "sms failed was data");
+                byte[] data = (byte[]) map.get("data");
+                Integer destPort = (Integer) map.get("destPort");
 
-        SmsMessageBase.SubmitPduBase pdu = null;
-        //    figure out from tracker if this was sendText/Data
-        if (map.containsKey("text")) {
-            Rlog.d(TAG, "sms failed was text");
-            String text = (String) map.get("text");
-
-            if (isCdmaFormat(newFormat)) {
-                Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
-                pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
-                        scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
-            } else {
-                Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
-                pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
-                        scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
-            }
-        } else if (map.containsKey("data")) {
-            Rlog.d(TAG, "sms failed was data");
-            byte[] data = (byte[]) map.get("data");
-            Integer destPort = (Integer) map.get("destPort");
-
-            if (isCdmaFormat(newFormat)) {
-                Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
-                pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+                if (isCdmaFormat(newFormat)) {
+                    pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(