Merge changes from topic "140070796"

* changes:
  Use carrier config to define network validation cache ttl.
  For validation off case, do NOT switch data until new conn is up.
  Skip network validation if validated recently upon switching
  Do not set a sub as default data sub unless it's active.
diff --git a/proto/src/telephony.proto b/proto/src/telephony.proto
index 7e823b5..020aba6 100644
--- a/proto/src/telephony.proto
+++ b/proto/src/telephony.proto
@@ -766,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
@@ -1750,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
@@ -2205,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 {
diff --git a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
index fd6ccd4..34fae4a 100644
--- a/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
+++ b/src/java/com/android/internal/telephony/AsyncEmergencyContactNotifier.java
@@ -19,7 +19,8 @@
 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
diff --git a/src/java/com/android/internal/telephony/BlockChecker.java b/src/java/com/android/internal/telephony/BlockChecker.java
index 19981eb..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}
diff --git a/src/java/com/android/internal/telephony/Call.java b/src/java/com/android/internal/telephony/Call.java
index 4e9f105..d3cb584 100644
--- a/src/java/com/android/internal/telephony/Call.java
+++ b/src/java/com/android/internal/telephony/Call.java
@@ -17,9 +17,9 @@
 package com.android.internal.telephony;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
 
 import com.android.ims.internal.ConferenceParticipant;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
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 1f8b536..2a8319b 100644
--- a/src/java/com/android/internal/telephony/CallForwardInfo.java
+++ b/src/java/com/android/internal/telephony/CallForwardInfo.java
@@ -17,7 +17,8 @@
 package com.android.internal.telephony;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+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 35abbd1..151a4bf 100644
--- a/src/java/com/android/internal/telephony/CallManager.java
+++ b/src/java/com/android/internal/telephony/CallManager.java
@@ -25,18 +25,16 @@
 import android.os.RegistrantList;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 
 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/CarrierActionAgent.java b/src/java/com/android/internal/telephony/CarrierActionAgent.java
index 568d40c..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;
@@ -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/CarrierResolver.java b/src/java/com/android/internal/telephony/CarrierResolver.java
index 959522f..ea31a4b1 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 e67f24d..0b9cae1 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -69,6 +69,9 @@
     public SparseArray<String> mLastSimState = new SparseArray<>();
     private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
 
+    // whether we have successfully bound to the service
+    private boolean mServiceBound = false;
+
     private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -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;
@@ -277,6 +282,7 @@
                                 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                                 (r) -> mHandler.post(r),
                                 connection)) {
+                    mServiceBound = true;
                     return;
                 }
 
@@ -331,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;
         }
@@ -370,6 +381,18 @@
         }
 
         @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 + "]";
         }
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index de3cdcb..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.
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 e9c3a73..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.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 05e92ba..0000000
--- a/src/java/com/android/internal/telephony/CellBroadcastHandler.java
+++ /dev/null
@@ -1,459 +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.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.pm.PackageManager;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Telephony;
-import android.provider.Telephony.CellBroadcasts;
-import android.telephony.CbGeoUtils;
-import android.telephony.CbGeoUtils.Geometry;
-import android.telephony.CbGeoUtils.LatLng;
-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.metrics.TelephonyMetrics;
-import com.android.internal.telephony.util.TelephonyUtils;
-
-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.getMaximumWaitingDuration());
-        } 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;
-        String 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.ACTION_SMS_EMERGENCY_CB_RECEIVED);
-            //Emergency alerts need to be delivered with high priority
-            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            receiverPermission = Manifest.permission.RECEIVE_EMERGENCY_BROADCAST;
-            appOp = AppOpsManager.OPSTR_RECEIVE_EMERGENCY_BROADCAST;
-
-            intent.putExtra(EXTRA_MESSAGE, message);
-            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
-
-            if (TelephonyUtils.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);
-                    try {
-                        mContext.createPackageContextAsUser(
-                                mContext.getPackageName(), 0, UserHandle.ALL)
-                                .sendOrderedBroadcast(additionalIntent, receiverPermission, appOp,
-                                        null /* resultReceiver */, getHandler(), Activity.RESULT_OK,
-                                        null /* initialData */, null /* initialExtras */);
-                    } catch (PackageManager.NameNotFoundException ignored) {
-                    }
-                }
-            }
-
-            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);
-                try {
-                    mContext.createPackageContextAsUser(
-                            mContext.getPackageName(), 0, UserHandle.ALL)
-                            .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
-                                    getHandler(), Activity.RESULT_OK, null /* initialData */,
-                                    null /* initialExtras */);
-                } catch (PackageManager.NameNotFoundException ignored) {
-                }
-            }
-        } 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.OPSTR_RECEIVE_SMS;
-
-            intent.putExtra(EXTRA_MESSAGE, message);
-            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
-
-            mReceiverCount.incrementAndGet();
-            try {
-                mContext.createPackageContextAsUser(mContext.getPackageName(), 0, UserHandle.ALL)
-                        .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
-                                getHandler(), Activity.RESULT_OK, null /* initialData */,
-                                null /* initialExtras */);
-            } catch (PackageManager.NameNotFoundException ignored) {
-            }
-        }
-
-        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 mContext.checkPermission(permission, Process.myPid(), Process.myUid())
-                    == PackageManager.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/CellularNetworkService.java b/src/java/com/android/internal/telephony/CellularNetworkService.java
index 46f34e7..4971643 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkService.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkService.java
@@ -30,11 +30,12 @@
 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;
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 5f8789d..ccd9251 100644
--- a/src/java/com/android/internal/telephony/CommandException.java
+++ b/src/java/com/android/internal/telephony/CommandException.java
@@ -17,7 +17,8 @@
 package com.android.internal.telephony;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 2906a79..f9241fb 100644
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -21,7 +21,6 @@
 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;
@@ -31,6 +30,7 @@
 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;
@@ -665,6 +665,17 @@
     public abstract void deflect(String number) throws CallStateException;
 
     /**
+     * Transfer individual Connection
+     */
+    public abstract void transfer(String number, boolean isConfirmationRequired)
+            throws CallStateException;
+
+    /**
+     * Transfer individual Connection for consultative transfer
+     */
+    public abstract void consultativeTransfer(Connection other) throws CallStateException;
+
+    /**
      * Hangup individual Connection
      */
     @UnsupportedAppUsage
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 c6109b3..e8aafe7 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -30,7 +30,6 @@
 import android.telephony.PhoneCapability;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyRegistryManager;
@@ -38,6 +37,7 @@
 import android.telephony.ims.ImsReasonInfo;
 
 import com.android.internal.telephony.PhoneInternalInterface.DataActivityState;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index d84d503..c94c4c3 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -36,7 +36,6 @@
 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;
@@ -45,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;
diff --git a/src/java/com/android/internal/telephony/DriverCall.java b/src/java/com/android/internal/telephony/DriverCall.java
index a47503f..a67de7a 100644
--- a/src/java/com/android/internal/telephony/DriverCall.java
+++ b/src/java/com/android/internal/telephony/DriverCall.java
@@ -18,7 +18,8 @@
 
 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/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 45511eb..2e86855 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -34,7 +34,6 @@
 import android.telephony.CellLocation;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
@@ -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;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index 7300893..0365064 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -27,7 +27,6 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.text.TextUtils;
 
@@ -37,6 +36,7 @@
 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}
@@ -366,6 +366,18 @@
     }
 
     @Override
+    public void transfer(String number, boolean isConfirmationRequired) throws CallStateException {
+        // Transfer is not supported.
+        throw new CallStateException("Transfer is not supported for CS");
+    }
+
+    @Override
+    public void consultativeTransfer(Connection other) throws CallStateException {
+        // Transfer is not supported.
+        throw new CallStateException("Transfer is not supported for CS");
+    }
+
+    @Override
     public void separate() throws CallStateException {
         if (!mDisconnected) {
             mOwner.separate(this);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index ad0b35d..18006710 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -66,7 +66,6 @@
 import android.telephony.NetworkScanRequest;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.PreciseDataConnectionState;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.SignalThresholdInfo;
@@ -105,6 +104,7 @@
 import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.telephony.uicc.UiccSlot;
 import com.android.internal.telephony.util.ArrayUtils;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -2020,12 +2020,20 @@
 
     @Override
     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
+        getCallForwardingOption(commandInterfaceCFReason,
+                CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
+    }
+
+    @Override
+    public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
+            Message onComplete) {
         if (isPhoneTypeGsm() || isImsUtEnabledOverCdma()) {
             Phone imsPhone = mImsPhone;
             if ((imsPhone != null)
                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
                     || imsPhone.isUtEnabled())) {
-                imsPhone.getCallForwardingOption(commandInterfaceCFReason, onComplete);
+                imsPhone.getCallForwardingOption(commandInterfaceCFReason, serviceClass,
+                        onComplete);
                 return;
             }
 
@@ -2037,8 +2045,7 @@
                 } else {
                     resp = onComplete;
                 }
-                mCi.queryCallForwardStatus(commandInterfaceCFReason,
-                        CommandsInterface.SERVICE_CLASS_VOICE, null, resp);
+                mCi.queryCallForwardStatus(commandInterfaceCFReason, serviceClass, null, resp);
             }
         } else {
             loge("getCallForwardingOption: not possible in CDMA without IMS");
@@ -2051,13 +2058,25 @@
             String dialingNumber,
             int timerSeconds,
             Message onComplete) {
+        setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason,
+                dialingNumber, CommandsInterface.SERVICE_CLASS_VOICE, timerSeconds, onComplete);
+    }
+
+    @Override
+    public void setCallForwardingOption(int commandInterfaceCFAction,
+            int commandInterfaceCFReason,
+            String dialingNumber,
+            int serviceClass,
+            int timerSeconds,
+            Message onComplete) {
         if (isPhoneTypeGsm() || isImsUtEnabledOverCdma()) {
             Phone imsPhone = mImsPhone;
             if ((imsPhone != null)
                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
                     || imsPhone.isUtEnabled())) {
                 imsPhone.setCallForwardingOption(commandInterfaceCFAction,
-                        commandInterfaceCFReason, dialingNumber, timerSeconds, onComplete);
+                        commandInterfaceCFReason, dialingNumber, serviceClass,
+                        timerSeconds, onComplete);
                 return;
             }
 
@@ -2074,7 +2093,7 @@
                 }
                 mCi.setCallForward(commandInterfaceCFAction,
                         commandInterfaceCFReason,
-                        CommandsInterface.SERVICE_CLASS_VOICE,
+                        serviceClass,
                         dialingNumber,
                         timerSeconds,
                         resp);
@@ -2797,9 +2816,8 @@
 
             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) {
@@ -3137,20 +3155,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;
                 }
             }
         }
@@ -3314,10 +3329,8 @@
             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();
@@ -3657,7 +3670,7 @@
                 cdmaApplication.getType() == AppType.APPTYPE_RUIM);
     }
 
-    private void phoneObjectUpdater(int newVoiceRadioTech) {
+    protected void phoneObjectUpdater(int newVoiceRadioTech) {
         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
 
         // Check for a voice over LTE/NR replacement
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/IccPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 66ed9ed..a290c73 100644
--- a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -22,7 +22,6 @@
 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 5c33f0e..76dc518 100644
--- a/src/java/com/android/internal/telephony/IccProvider.java
+++ b/src/java/com/android/internal/telephony/IccProvider.java
@@ -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 6c36c87..017cd95 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -36,11 +36,11 @@
 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.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.SmsCbMessage;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -58,6 +58,7 @@
 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;
@@ -199,13 +200,23 @@
                             if (mPhone.getPhoneId() == intent.getIntExtra(
                                     CarrierConfigManager.EXTRA_SLOT_INDEX,
                                     SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
-                                mCellBroadcastRangeManager.updateRanges();
+                                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) {
         if (messages == null) {
             return;
@@ -266,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;
@@ -325,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;
@@ -363,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>();
@@ -859,6 +873,7 @@
                 callingPackage, "getSmscAddressFromIccEf")) {
             return null;
         }
+        enforceNotOnHandlerThread("getSmscAddressFromIccEf");
         synchronized (mLock) {
             mSmsc = null;
             Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE);
@@ -1134,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);
 
@@ -1154,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);
 
@@ -1175,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);
 
@@ -1195,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);
 
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 58aac01..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());
                     }
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 2ff68e2..1c6cd4f 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -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;
@@ -68,6 +67,7 @@
 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;
@@ -225,9 +225,6 @@
     protected Phone mPhone;
 
     @UnsupportedAppUsage
-    protected CellBroadcastHandler mCellBroadcastHandler;
-
-    @UnsupportedAppUsage
     private UserManager mUserManager;
 
     protected TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
@@ -237,8 +234,6 @@
     @UnsupportedAppUsage
     IDeviceIdleController mDeviceIdleController;
 
-    protected static boolean sEnableCbModule = true;
-
     protected CellBroadcastServiceManager mCellBroadcastServiceManager;
 
     // Delete permanently from raw table
@@ -263,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);
 
@@ -1718,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);
         }
@@ -1807,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
@@ -1829,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/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index 21ca878..4c1d36e 100755
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -34,7 +34,6 @@
 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;
@@ -45,6 +44,7 @@
 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;
@@ -563,6 +563,10 @@
             timeZoneCountryIsoDebugInfo = countryIsoDebugInfo;
         }
 
+        if (mLastServiceState == ServiceState.STATE_POWER_OFF) {
+            countryIso = "";
+        }
+
         log("updateLocale: countryIso = " + countryIso
                 + ", countryIsoDebugInfo = " + countryIsoDebugInfo);
         if (!Objects.equals(countryIso, mCurrentCountryIso)) {
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index 05aa09d..1492402 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -25,7 +25,6 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.timezone.TelephonyLookup;
 import android.timezone.TelephonyNetwork;
@@ -34,6 +33,7 @@
 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.Collections;
diff --git a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
index bd90be6..716e7a2 100644
--- a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
+++ b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
@@ -38,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;
 
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/NitzStateMachineImpl.java b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
index f4c24fb..7a4a3b8 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
@@ -16,11 +16,10 @@
 
 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.os.TimestampedValue;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.timezone.CountryTimeZones.OffsetResult;
 import android.util.LocalLog;
@@ -29,6 +28,7 @@
 import com.android.internal.telephony.TimeZoneLookupHelper.CountryResult;
 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;
@@ -402,8 +402,8 @@
     }
 
     private void sendEmptyTimeSuggestion(String reason) {
-        PhoneTimeSuggestion timeSuggestion =
-                new PhoneTimeSuggestion.Builder(mPhone.getPhoneId()).build();
+        TelephonyTimeSuggestion timeSuggestion =
+                new TelephonyTimeSuggestion.Builder(mPhone.getPhoneId()).build();
         timeSuggestion.addDebugInfo("Empty suggestion, reason=" + reason);
         mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
     }
@@ -485,12 +485,12 @@
                 Rlog.d(LOG_TAG, logMsg);
             }
             mTimeLog.log(logMsg);
-            PhoneTimeSuggestion phoneTimeSuggestion =
-                    new PhoneTimeSuggestion.Builder(mPhone.getPhoneId())
+            TelephonyTimeSuggestion timeSuggestion =
+                    new TelephonyTimeSuggestion.Builder(mPhone.getPhoneId())
                             .setUtcTime(newNitzTime)
                             .addDebugInfo(logMsg)
                             .build();
-            mTimeServiceHelper.suggestDeviceTime(phoneTimeSuggestion);
+            mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
 
             TelephonyMetrics.getInstance().writeNITZEvent(
                     mPhone.getPhoneId(), newNitzTime.getValue());
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index f76de0a..b90b69d 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -25,7 +25,6 @@
 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.Handler;
@@ -53,7 +52,6 @@
 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;
@@ -87,6 +85,7 @@
 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;
@@ -1968,10 +1967,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();
     }
 
     /**
@@ -1985,7 +1985,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();
     }
 
     /**
@@ -1999,7 +2002,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();
@@ -2466,6 +2469,10 @@
         return mIsPhoneInEcmState;
     }
 
+    public boolean isInImsEcm() {
+        return false;
+    }
+
     public void setIsInEcm(boolean isInEcm) {
         if (!getUnitTestMode()) {
             TelephonyProperties.in_ecm_mode(isInEcm);
@@ -4069,18 +4076,6 @@
     }
 
     /**
-     * Get aggregated video call data usage since boot.
-     * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
-     *
-     * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
-     * @return Snapshot of video call data usage
-     */
-    public NetworkStats getVtDataUsage(boolean perUidStats) {
-        if (mImsPhone == null) return null;
-        return mImsPhone.getVtDataUsage(perUidStats);
-    }
-
-    /**
      * SIP URIs aliased to the current subscriber given by the IMS implementation.
      * Applicable only on IMS; used in absence of line1number.
      * @return array of SIP URIs aliased to the current subscriber
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index e5ba485..4304199 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -29,12 +29,12 @@
 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;
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 10cff81..5aa6237 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -34,7 +34,6 @@
 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;
@@ -50,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;
@@ -169,8 +169,9 @@
                 sUiccController = UiccController.make(context);
 
                 Rlog.i(LOG_TAG, "Creating SubscriptionController");
-                SubscriptionController sc = SubscriptionController.init(context);
-                MultiSimSettingController.init(context, sc);
+                TelephonyComponentFactory.getInstance().inject(SubscriptionController.class.
+                        getName()).initSubscriptionController(context);
+                MultiSimSettingController.init(context, SubscriptionController.getInstance());
 
                 if (context.getPackageManager().hasSystemFeature(
                         PackageManager.FEATURE_TELEPHONY_EUICC)) {
@@ -228,7 +229,9 @@
                 int maxActivePhones = sPhoneConfigurationManager
                         .getNumberOfModemsWithSimultaneousDataConnections();
 
-                sPhoneSwitcher = PhoneSwitcher.make(maxActivePhones, sContext, Looper.myLooper());
+                sPhoneSwitcher = TelephonyComponentFactory.getInstance().inject(
+                        PhoneSwitcher.class.getName()).
+                        makePhoneSwitcher(maxActivePhones, sContext, Looper.myLooper());
 
                 sProxyController = ProxyController.getInstance(context);
 
@@ -285,8 +288,10 @@
 
         // We always use PHONE_TYPE_CDMA_LTE now.
         if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
+        TelephonyComponentFactory injectedComponentFactory =
+                TelephonyComponentFactory.getInstance().inject(GsmCdmaPhone.class.getName());
 
-        return new GsmCdmaPhone(context,
+        return injectedComponentFactory.makePhone(context,
                 sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType,
                 TelephonyComponentFactory.getInstance());
     }
diff --git a/src/java/com/android/internal/telephony/PhoneInternalInterface.java b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
index 20976df..7e1fe0d 100644
--- a/src/java/com/android/internal/telephony/PhoneInternalInterface.java
+++ b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
@@ -193,9 +193,12 @@
     int CDMA_RM_ANY         = TelephonyManager.CDMA_ROAMING_MODE_ANY;
 
     // Used for CDMA subscription mode
-    static final int CDMA_SUBSCRIPTION_UNKNOWN  =-1; // Unknown
-    static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; // RUIM/SIM (default)
-    static final int CDMA_SUBSCRIPTION_NV       = 1; // NV -> non-volatile memory
+    // Unknown
+    static final int CDMA_SUBSCRIPTION_UNKNOWN  = TelephonyManager.CDMA_SUBSCRIPTION_UNKNOWN;
+    // RUIM/SIM (default)
+    static final int CDMA_SUBSCRIPTION_RUIM_SIM = TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM;
+    // NV -> non-volatile memory
+    static final int CDMA_SUBSCRIPTION_NV       = TelephonyManager.CDMA_SUBSCRIPTION_NV;
 
     static final int PREFERRED_CDMA_SUBSCRIPTION = CDMA_SUBSCRIPTION_RUIM_SIM;
 
@@ -577,7 +580,7 @@
 
     /**
      * getCallForwardingOptions
-     * gets a call forwarding option. The return value of
+     * gets a call forwarding option for SERVICE_CLASS_VOICE. The return value of
      * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo.
      *
      * @param commandInterfaceCFReason is one of the valid call forwarding
@@ -590,8 +593,24 @@
                                   Message onComplete);
 
     /**
+     * getCallForwardingOptions
+     * gets a call forwarding option. The return value of
+     * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo.
+     *
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface.</code>
+     * @param serviceClass is a sum of SERVICE_CLASS_* as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface.</code>
+     * @param onComplete a callback message when the action is completed.
+     *        @see com.android.internal.telephony.CallForwardInfo for details.
+     */
+    void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
+                                  Message onComplete);
+
+    /**
      * setCallForwardingOptions
-     * sets a call forwarding option.
+     * sets a call forwarding option for SERVICE_CLASS_VOICE.
      *
      * @param commandInterfaceCFAction is one of the valid call forwarding
      *        CF_ACTIONS, as defined in
@@ -611,6 +630,30 @@
                                  Message onComplete);
 
     /**
+     * setCallForwardingOptions
+     * sets a call forwarding option.
+     *
+     * @param commandInterfaceCFAction is one of the valid call forwarding
+     *        CF_ACTIONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface.</code>
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface.</code>
+     * @param dialingNumber is the target phone number to forward calls to
+     * @param serviceClass is a sum of SERVICE_CLASS_* as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface.</code>
+     * @param timerSeconds is used by CFNRy to indicate the timeout before
+     *        forwarding is attempted.
+     * @param onComplete a callback message when the action is completed.
+     */
+    void setCallForwardingOption(int commandInterfaceCFAction,
+                                 int commandInterfaceCFReason,
+                                 String dialingNumber,
+                                 int serviceClass,
+                                 int timerSeconds,
+                                 Message onComplete);
+
+    /**
      * Gets a call barring option. The return value of ((AsyncResult) onComplete.obj) will be an
      * Integer representing the sum of enabled serivice classes (sum of SERVICE_CLASS_*)
      *
diff --git a/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index 94b05ed..6d0b03c 100644
--- a/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/src/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -23,11 +23,12 @@
 import android.content.IntentFilter;
 import android.os.Handler;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 
+import com.android.telephony.Rlog;
+
 /**
  *
  *                            DO NOT USE THIS CLASS:
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 453b95c..35af1b4 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -32,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";
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index 6cc40bd..4248443 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -51,7 +51,6 @@
 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;
@@ -64,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;
@@ -353,7 +354,7 @@
         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);
diff --git a/src/java/com/android/internal/telephony/ProxyController.java b/src/java/com/android/internal/telephony/ProxyController.java
index e0fcbb6..d6ed87b 100644
--- a/src/java/com/android/internal/telephony/ProxyController.java
+++ b/src/java/com/android/internal/telephony/ProxyController.java
@@ -27,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.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.HashSet;
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index cea06e1..b812432 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -53,7 +53,6 @@
 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;
@@ -87,7 +86,6 @@
 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;
@@ -115,6 +113,7 @@
 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;
@@ -240,7 +239,7 @@
     /** Radio bug detector instance */
     private RadioBugDetector mRadioBugDetector = null;
 
-    boolean mIsMobileNetworkSupported;
+    boolean mIsCellularSupported;
     RadioResponse mRadioResponse;
     RadioIndication mRadioIndication;
     volatile IRadio mRadioProxy = null;
@@ -421,7 +420,7 @@
     @VisibleForTesting
     public synchronized IRadio getRadioProxy(Message result) {
         if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return null;
-        if (!mIsMobileNetworkSupported) {
+        if (!mIsCellularSupported) {
             if (RILJ_LOGV) riljLog("getRadioProxy: Not calling getService(): wifi-only");
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -535,7 +534,7 @@
     @VisibleForTesting
     public synchronized IOemHook getOemHookProxy(Message result) {
         if (!SubscriptionManager.isValidPhoneId((mPhoneId))) return null;
-        if (!mIsMobileNetworkSupported) {
+        if (!mIsCellularSupported) {
             if (RILJ_LOGV) riljLog("getOemHookProxy: Not calling getService(): wifi-only");
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -609,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);
diff --git a/src/java/com/android/internal/telephony/RILRequest.java b/src/java/com/android/internal/telephony/RILRequest.java
index 4c503f8..0d5f8e7 100644
--- a/src/java/com/android/internal/telephony/RILRequest.java
+++ b/src/java/com/android/internal/telephony/RILRequest.java
@@ -22,7 +22,8 @@
 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;
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index 24d79f2..24a7791 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -39,11 +39,11 @@
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.telephony.PhoneCapability;
-import android.telephony.Rlog;
 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;
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 7ab8d44..0f4a719 100644
--- a/src/java/com/android/internal/telephony/RadioConfigResponse.java
+++ b/src/java/com/android/internal/telephony/RadioConfigResponse.java
@@ -21,9 +21,9 @@
 import android.hardware.radio.config.V1_1.ModemsConfig;
 import android.hardware.radio.config.V1_2.IRadioConfigResponse;
 import android.telephony.PhoneCapability;
-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/RatRatcheter.java b/src/java/com/android/internal/telephony/RatRatcheter.java
index 6216200..084223f 100644
--- a/src/java/com/android/internal/telephony/RatRatcheter.java
+++ b/src/java/com/android/internal/telephony/RatRatcheter.java
@@ -27,11 +27,12 @@
 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;
 
 /**
diff --git a/src/java/com/android/internal/telephony/RetryManager.java b/src/java/com/android/internal/telephony/RetryManager.java
index 67bc3c0..62cde52 100644
--- a/src/java/com/android/internal/telephony/RetryManager.java
+++ b/src/java/com/android/internal/telephony/RetryManager.java
@@ -21,12 +21,12 @@
 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;
diff --git a/src/java/com/android/internal/telephony/RilWakelockInfo.java b/src/java/com/android/internal/telephony/RilWakelockInfo.java
index 28ccbc8..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.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 {
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index ee398f9..7ab55a1 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -63,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;
@@ -86,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;
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index c6c8274..b2ccb99 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -72,7 +72,6 @@
 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;
@@ -113,6 +112,7 @@
 import com.android.internal.telephony.util.NotificationChannelController;
 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;
@@ -281,6 +281,7 @@
     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.
@@ -445,7 +446,7 @@
 
     //Common
     @UnsupportedAppUsage
-    private final GsmCdmaPhone mPhone;
+    protected final GsmCdmaPhone mPhone;
 
     private CellIdentity mCellIdentity;
     private CellIdentity mNewCellIdentity;
@@ -1217,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;
@@ -1234,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:
@@ -1444,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();
@@ -1537,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;
@@ -1618,6 +1619,10 @@
                 onCarrierConfigChanged();
                 break;
 
+            case EVENT_POLL_STATE_REQUEST:
+                pollStateInternal(false);
+                break;
+
             default:
                 log("Unhandled message with number: " + msg.what);
                 break;
@@ -2071,7 +2076,7 @@
         }
     }
 
-    void handlePollStateResultMessage(int what, AsyncResult ar) {
+    protected void handlePollStateResultMessage(int what, AsyncResult ar) {
         int ints[];
         switch (what) {
             case EVENT_POLL_STATE_CS_CELLULAR_REGISTRATION: {
@@ -3019,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;
 
@@ -4733,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) {
@@ -5023,7 +5020,7 @@
         mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
 
         // Get Registration Information
-        pollState();
+        pollStateInternal(false);
     }
 
     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
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 6afc865..445b0ef 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -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 ef740c4..6c71690 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -33,13 +33,13 @@
 import android.os.ServiceManager;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 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;
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 66b8709..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;
diff --git a/src/java/com/android/internal/telephony/SmsPermissions.java b/src/java/com/android/internal/telephony/SmsPermissions.java
index 5590ce6..02ecdf4 100644
--- a/src/java/com/android/internal/telephony/SmsPermissions.java
+++ b/src/java/com/android/internal/telephony/SmsPermissions.java
@@ -24,9 +24,10 @@
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.service.carrier.CarrierMessagingService;
-import android.telephony.Rlog;
 import android.util.Log;
 
+import com.android.telephony.Rlog;
+
 /**
  * Permissions checks for SMS functionality
  */
diff --git a/src/java/com/android/internal/telephony/SmsStorageMonitor.java b/src/java/com/android/internal/telephony/SmsStorageMonitor.java
index fe06f63..9eb43da 100755
--- a/src/java/com/android/internal/telephony/SmsStorageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsStorageMonitor.java
@@ -26,9 +26,10 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 
+import com.android.telephony.Rlog;
+
 /**
  * Monitors the device and ICC storage, and sends the appropriate events.
  *
diff --git a/src/java/com/android/internal/telephony/SmsUsageMonitor.java b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
index 2a9d895..28e674b 100644
--- a/src/java/com/android/internal/telephony/SmsUsageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
@@ -29,13 +29,13 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.SmsManager;
 import android.util.AtomicFile;
 import android.util.Xml;
 
 import com.android.internal.telephony.util.XmlUtils;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.telephony.Rlog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index d699bbd..00690ef 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -43,7 +43,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.RadioAccessFamily;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.SimDisplayNameSource;
@@ -64,6 +63,7 @@
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -133,7 +133,7 @@
     protected final Object mLock = new Object();
 
     /** The singleton instance. */
-    private static SubscriptionController sInstance = null;
+    protected static SubscriptionController sInstance = null;
     @UnsupportedAppUsage
     protected Context mContext;
     protected TelephonyManager mTelephonyManager;
@@ -143,7 +143,7 @@
 
     // Each slot can have multiple subs.
     private static Map<Integer, ArrayList<Integer>> sSlotIndexToSubIds = new ConcurrentHashMap<>();
-    private static int mDefaultFallbackSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    protected static int mDefaultFallbackSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     @UnsupportedAppUsage
     private static int mDefaultPhoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
 
@@ -247,7 +247,7 @@
     }
 
     @UnsupportedAppUsage
-    private void enforceModifyPhoneState(String message) {
+    protected void enforceModifyPhoneState(String message) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MODIFY_PHONE_STATE, message);
     }
@@ -2150,7 +2150,7 @@
     }
 
     @UnsupportedAppUsage
-    private void logdl(String msg) {
+    protected void logdl(String msg) {
         logd(msg);
         mLocalLog.log(msg);
     }
@@ -2383,7 +2383,7 @@
      * the first sub is set as default subscription
      */
     @UnsupportedAppUsage
-    private void setDefaultFallbackSubId(int subId, int subscriptionType) {
+    protected void setDefaultFallbackSubId(int subId, int subscriptionType) {
         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
             throw new RuntimeException("setDefaultSubId called with DEFAULT_SUB_ID");
         }
@@ -3747,26 +3747,6 @@
         return true;
     }
 
-    // TODO: This method should belong to Telephony manager like other data enabled settings and
-    // override APIs. Remove this once TelephonyManager API is added.
-    @Override
-    public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
-        if (DBG) logd("[setAlwaysAllowMmsData]+ alwaysAllow:" + alwaysAllow + " subId:" + subId);
-
-        enforceModifyPhoneState("setAlwaysAllowMmsData");
-
-        // Now that all security checks passes, perform the operation as ourselves.
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            validateSubId(subId);
-            Phone phone = PhoneFactory.getPhone(getPhoneId(subId));
-            if (phone == null) return false;
-            return phone.getDataEnabledSettings().setAlwaysAllowMmsData(alwaysAllow);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     /**
      * Set allowing mobile data during voice call.
      *
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index 66f805b..f2f7ddc 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -17,7 +17,8 @@
 package com.android.internal.telephony;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * Utilities that check if the phone supports specified capabilities.
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index bd9b338..979f29c 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -30,7 +30,6 @@
 import android.system.OsConstants;
 import android.system.StructStatVfs;
 import android.telephony.AccessNetworkConstants.TransportType;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
@@ -46,6 +45,7 @@
 import com.android.internal.telephony.uicc.IccCardStatus;
 import com.android.internal.telephony.uicc.UiccCard;
 import com.android.internal.telephony.uicc.UiccProfile;
+import com.android.telephony.Rlog;
 
 import dalvik.system.PathClassLoader;
 
@@ -60,8 +60,6 @@
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
-
-
 /**
  * This class has one-line methods to instantiate objects only. The purpose is to make code
  * unit-test friendly and use this class as a way to do dependency injection. Instantiating objects
@@ -422,4 +420,20 @@
     public DataEnabledSettings makeDataEnabledSettings(Phone phone) {
         return new DataEnabledSettings(phone);
     }
+
+    public Phone makePhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+            int phoneId, int precisePhoneType,
+            TelephonyComponentFactory telephonyComponentFactory) {
+        return new GsmCdmaPhone(context, ci, notifier, phoneId, precisePhoneType,
+                telephonyComponentFactory);
+    }
+
+    public SubscriptionController initSubscriptionController(Context c) {
+        return SubscriptionController.init(c);
+    }
+
+    public PhoneSwitcher makePhoneSwitcher(int maxDataAttachModemCount, Context context,
+            Looper looper) {
+        return PhoneSwitcher.make(maxDataAttachModemCount, context, looper);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/TelephonyDevController.java b/src/java/com/android/internal/telephony/TelephonyDevController.java
index 3cda417..a467283 100644
--- a/src/java/com/android/internal/telephony/TelephonyDevController.java
+++ b/src/java/com/android/internal/telephony/TelephonyDevController.java
@@ -17,20 +17,14 @@
 package com.android.internal.telephony;
 
 import android.content.res.Resources;
-import com.android.internal.telephony.*;
-import android.telephony.TelephonyManager;
-
 import android.os.AsyncResult;
-import android.telephony.Rlog;
-import java.util.BitSet;
-import java.util.List;
-import java.util.ArrayList;
-import android.text.TextUtils;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.telephony.ServiceState;
+
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * TelephonyDevController - provides a unified view of the
diff --git a/src/java/com/android/internal/telephony/TelephonyTester.java b/src/java/com/android/internal/telephony/TelephonyTester.java
index 52e0149..b8288ae 100644
--- a/src/java/com/android/internal/telephony/TelephonyTester.java
+++ b/src/java/com/android/internal/telephony/TelephonyTester.java
@@ -24,7 +24,6 @@
 import android.os.BadParcelableException;
 import android.os.Bundle;
 import android.telephony.AccessNetworkConstants;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
@@ -39,6 +38,7 @@
 import com.android.internal.telephony.imsphone.ImsPhoneCall;
 import com.android.internal.telephony.test.TestConferenceEventPackageParser;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git a/src/java/com/android/internal/telephony/TimeServiceHelper.java b/src/java/com/android/internal/telephony/TimeServiceHelper.java
index 00bd3d2..d4ff9ad 100644
--- a/src/java/com/android/internal/telephony/TimeServiceHelper.java
+++ b/src/java/com/android/internal/telephony/TimeServiceHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.app.timedetector.TimeDetector;
 
 /**
@@ -62,8 +62,8 @@
     /**
      * Suggest the time to the {@link TimeDetector}.
      *
-     * @param phoneTimeSuggestion the suggested time
+     * @param timeSuggestion the suggested time
      */
-    void suggestDeviceTime(PhoneTimeSuggestion phoneTimeSuggestion);
+    void suggestDeviceTime(TelephonyTimeSuggestion timeSuggestion);
 
 }
diff --git a/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java b/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
index e5ffdad..10a96aa 100644
--- a/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
+++ b/src/java/com/android/internal/telephony/TimeServiceHelperImpl.java
@@ -17,7 +17,7 @@
 package com.android.internal.telephony;
 
 import android.app.AlarmManager;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.app.timedetector.TimeDetector;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -96,7 +96,7 @@
     }
 
     @Override
-    public void suggestDeviceTime(PhoneTimeSuggestion phoneTimeSuggestion) {
-        mTimeDetector.suggestPhoneTime(phoneTimeSuggestion);
+    public void suggestDeviceTime(TelephonyTimeSuggestion timeSuggestion) {
+        mTimeDetector.suggestTelephonyTime(timeSuggestion);
     }
 }
diff --git a/src/java/com/android/internal/telephony/TimeZoneLookupHelper.java b/src/java/com/android/internal/telephony/TimeZoneLookupHelper.java
index 79342dd..572b190 100644
--- a/src/java/com/android/internal/telephony/TimeZoneLookupHelper.java
+++ b/src/java/com/android/internal/telephony/TimeZoneLookupHelper.java
@@ -133,11 +133,18 @@
         // is DST (if known). NITZ is limited in only being able to express DST offsets in whole
         // hours and the DST info is optional.
         Integer dstAdjustmentMillis = nitzData.getDstAdjustmentMillis();
-        Boolean isDst = dstAdjustmentMillis == null ? null : dstAdjustmentMillis != 0;
-        Integer dstAdjustmentMillisToMatch = null; // Don't try to match the precise DST offset.
-        return countryTimeZones.lookupByOffsetWithBias(
-                nitzData.getLocalOffsetMillis(), isDst, dstAdjustmentMillisToMatch,
-                nitzData.getCurrentTimeInMillis(), bias);
+        if (dstAdjustmentMillis == null) {
+            return countryTimeZones.lookupByOffsetWithBias(
+                    nitzData.getCurrentTimeInMillis(), bias, nitzData.getLocalOffsetMillis());
+
+        } else {
+            // We don't try to match the exact DST offset given, we just use it to work out if
+            // the country is in DST.
+            boolean isDst = dstAdjustmentMillis != 0;
+            return countryTimeZones.lookupByOffsetWithBias(
+                    nitzData.getCurrentTimeInMillis(), bias,
+                    nitzData.getLocalOffsetMillis(), isDst);
+        }
     }
 
     /**
@@ -233,10 +240,6 @@
             }
 
             TimeZone timeZone = timeZoneMapping.getTimeZone();
-            if (timeZone == null) {
-                continue;
-            }
-
             int candidateOffset = timeZone.getOffset(whenMillis);
             if (countryDefaultOffset != candidateOffset) {
                 return true;
@@ -308,7 +311,7 @@
         // be strong consistency across calls.
         synchronized (this) {
             if (mLastCountryTimeZones != null) {
-                if (mLastCountryTimeZones.isForCountryCode(isoCountryCode)) {
+                if (mLastCountryTimeZones.matchesCountryCode(isoCountryCode)) {
                     return mLastCountryTimeZones;
                 }
             }
diff --git a/src/java/com/android/internal/telephony/UiccPhoneBookController.java b/src/java/com/android/internal/telephony/UiccPhoneBookController.java
index 482f340..733c445 100644
--- a/src/java/com/android/internal/telephony/UiccPhoneBookController.java
+++ b/src/java/com/android/internal/telephony/UiccPhoneBookController.java
@@ -20,10 +20,9 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.ServiceManager;
-import android.telephony.Rlog;
 
-import com.android.internal.telephony.IIccPhoneBook;
 import com.android.internal.telephony.uicc.AdnRecord;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 
diff --git a/src/java/com/android/internal/telephony/WakeLockStateMachine.java b/src/java/com/android/internal/telephony/WakeLockStateMachine.java
index 5cad743..eab9b8e 100644
--- a/src/java/com/android/internal/telephony/WakeLockStateMachine.java
+++ b/src/java/com/android/internal/telephony/WakeLockStateMachine.java
@@ -22,11 +22,11 @@
 import android.content.Intent;
 import android.os.Message;
 import android.os.PowerManager;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.telephony.Rlog;
 
 import java.util.concurrent.atomic.AtomicInteger;
 
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java
index bd3c442..3944f77 100755
--- a/src/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/src/java/com/android/internal/telephony/WapPushOverSms.java
@@ -47,13 +47,13 @@
 import android.os.UserManager;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.Rlog;
 import android.telephony.SmsManager;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.telephony.uicc.IccUtils;
+import com.android.telephony.Rlog;
 
 import com.google.android.mms.MmsException;
 import com.google.android.mms.pdu.DeliveryInd;
diff --git a/src/java/com/android/internal/telephony/cat/CatLog.java b/src/java/com/android/internal/telephony/cat/CatLog.java
index f41dc60..62bdf4e 100644
--- a/src/java/com/android/internal/telephony/cat/CatLog.java
+++ b/src/java/com/android/internal/telephony/cat/CatLog.java
@@ -17,7 +17,8 @@
 package com.android.internal.telephony.cat;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 public abstract class CatLog {
     static final boolean DEBUG = true;
diff --git a/src/java/com/android/internal/telephony/cat/ComprehensionTlv.java b/src/java/com/android/internal/telephony/cat/ComprehensionTlv.java
index 568c7c0..3651a40 100644
--- a/src/java/com/android/internal/telephony/cat/ComprehensionTlv.java
+++ b/src/java/com/android/internal/telephony/cat/ComprehensionTlv.java
@@ -17,12 +17,12 @@
 package com.android.internal.telephony.cat;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
 
-
 /**
  * Class for representing COMPREHENSION-TLV objects.
  *
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java b/src/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java
index b6ca02d..79c4d35 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaCallWaitingNotification.java
@@ -17,9 +17,9 @@
 package com.android.internal.telephony.cdma;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.PhoneConstants;
+import com.android.telephony.Rlog;
 
 /**
  * Represents a Supplementary Service Notification received from the network.
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
index b123f89..7a6d6f9 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
@@ -25,11 +25,8 @@
 import android.os.SystemProperties;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.SmsCbMessage;
-import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaSmsCbProgramResults;
 
-import com.android.internal.telephony.CellBroadcastHandler;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.InboundSmsHandler;
 import com.android.internal.telephony.InboundSmsTracker;
@@ -57,7 +54,6 @@
 public class CdmaInboundSmsHandler extends InboundSmsHandler {
 
     private final CdmaSMSDispatcher mSmsDispatcher;
-    private final CdmaServiceCategoryProgramHandler mServiceCategoryProgramHandler;
     private static CdmaCbTestBroadcastReceiver sTestBroadcastReceiver;
     private static CdmaScpTestBroadcastReceiver sTestScpBroadcastReceiver;
 
@@ -75,19 +71,14 @@
             + ".TEST_TRIGGER_CELL_BROADCAST";
     private static final String SCP_TEST_ACTION = "com.android.internal.telephony.cdma"
             + ".TEST_TRIGGER_SCP_MESSAGE";
-    private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.cdma"
-            + ".TOGGLE_CB_MODULE";
 
     /**
      * Create a new inbound SMS handler for CDMA.
      */
     private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
             Phone phone, CdmaSMSDispatcher smsDispatcher) {
-        super("CdmaInboundSmsHandler", context, storageMonitor, phone,
-                CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
+        super("CdmaInboundSmsHandler", context, storageMonitor, phone);
         mSmsDispatcher = smsDispatcher;
-        mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
-                phone.mCi, phone);
         mCheckForDuplicatePortsInOmadmWapPush = TelephonyResourceUtils
                 .getTelephonyResources(context).getBoolean(
                         com.android.telephony.resources.R.bool.config_duplicate_port_omadm_wappush);
@@ -152,7 +143,6 @@
                 sTestBroadcastReceiver = new CdmaCbTestBroadcastReceiver();
                 IntentFilter filter = new IntentFilter();
                 filter.addAction(TEST_ACTION);
-                filter.addAction(TOGGLE_CB_MODULE);
                 context.registerReceiver(sTestBroadcastReceiver, filter);
             }
             if (sTestScpBroadcastReceiver == null) {
@@ -170,7 +160,6 @@
     @Override
     protected void onQuitting() {
         mPhone.mCi.unSetOnNewCdmaSms(getHandler());
-        mCellBroadcastHandler.dispose();
 
         if (DBG) log("unregistered for 3GPP2 SMS");
         super.onQuitting();
@@ -211,11 +200,7 @@
         // Handle CMAS emergency broadcast messages.
         if (isBroadcastType) {
             log("Broadcast type message");
-            if (sEnableCbModule) {
-                mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms);
-            } else {
-                legacyDispatchSmsCbMessage(sms);
-            }
+            mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms);
             return Intents.RESULT_SMS_HANDLED;
         }
 
@@ -246,11 +231,7 @@
                 break;
 
             case SmsEnvelope.TELESERVICE_SCPT:
-                if (sEnableCbModule) {
-                    mCellBroadcastServiceManager.sendCdmaScpMessageToHandler(sms, mScpCallback);
-                } else {
-                    mServiceCategoryProgramHandler.dispatchSmsMessage(sms);
-                }
+                mCellBroadcastServiceManager.sendCdmaScpMessageToHandler(sms, mScpCallback);
                 return Intents.RESULT_SMS_HANDLED;
 
             case SmsEnvelope.TELESERVICE_FDEA_WAP:
@@ -285,20 +266,6 @@
         return dispatchNormalMessage(smsb);
     }
 
-    // dispatch an SMS message through the platform
-    private void legacyDispatchSmsCbMessage(SmsMessage sms) {
-        String plmn =
-                TelephonyManager.from(mContext).getNetworkOperatorForPhone(
-                        mPhone.getPhoneId());
-        SmsCbMessage cbMessage = sms.parseBroadcastSms(plmn, mPhone.getPhoneId(),
-                mPhone.getSubId());
-        if (cbMessage != null) {
-            mCellBroadcastHandler.dispatchSmsMessage(cbMessage);
-        } else {
-            loge("error trying to parse broadcast SMS");
-        }
-    }
-
     /**
      * Send an acknowledge message.
      *
@@ -487,16 +454,11 @@
      * 493925391C81193D48814D3D555120810D3D0D3D3925393C810D3D5539516480B481393D495120810D1539514 \
      * 9053081054925693D390481553951253080D0C4D481413481354D500 \
      * --ei phone_id 0 \
-     *
-     * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE
-     *
-     * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE \
-     * --ez enable true
      */
     private class CdmaCbTestBroadcastReceiver extends CbTestBroadcastReceiver {
 
         CdmaCbTestBroadcastReceiver() {
-            super(TEST_ACTION, TOGGLE_CB_MODULE);
+            super(TEST_ACTION);
         }
 
         @Override
@@ -524,23 +486,7 @@
             }
 
             SmsMessage sms = new SmsMessage(new CdmaSmsAddress(), envelope);
-            if (sEnableCbModule) {
                 mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms);
-            } else {
-                legacyDispatchSmsCbMessage(sms);
-            }
-        }
-
-        @Override
-        protected void handleToggleEnable() {
-            // sEnableCbModule is already toggled in super class
-            mCellBroadcastServiceManager.enable();
-        }
-
-        @Override
-        protected void handleToggleDisable(Context context) {
-            // sEnableCbModule is already toggled in super class
-            mCellBroadcastServiceManager.disable();
         }
     }
 
@@ -552,13 +498,11 @@
      * --es originating_address_string 1234567890 \
      * --es bearer_data_string 00031007B0122610880080B2091C5F1D3965DB95054D1CB2E1E883A6F41334E \
      * 6CA830EEC882872DFC32F2E9E40
-     *
-     * To toggle use the CDMA CB test broadcast receiver.
      */
     private class CdmaScpTestBroadcastReceiver extends CbTestBroadcastReceiver {
 
         CdmaScpTestBroadcastReceiver() {
-            super(SCP_TEST_ACTION, null);
+            super(SCP_TEST_ACTION);
         }
 
         @Override
@@ -587,21 +531,7 @@
             }
             SmsMessage sms = new SmsMessage(origAddr, envelope);
             sms.parseSms();
-            if (sEnableCbModule) {
-                mCellBroadcastServiceManager.sendCdmaScpMessageToHandler(sms, mScpCallback);
-            } else {
-                mServiceCategoryProgramHandler.dispatchSmsMessage(sms);
-            }
-        }
-
-        @Override
-        protected void handleToggleEnable() {
-            // noop
-        }
-
-        @Override
-        protected void handleToggleDisable(Context context) {
-            // noop
+            mCellBroadcastServiceManager.sendCdmaScpMessageToHandler(sms, mScpCallback);
         }
     }
 }
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java b/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
index e593115..7a42b00 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
@@ -22,7 +22,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.ResultReceiver;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.GsmCdmaPhone;
@@ -30,6 +29,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
 import com.android.internal.telephony.uicc.UiccCardApplication;
+import com.android.telephony.Rlog;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index ad46e54..3e60612 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -20,7 +20,6 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.Pair;
@@ -35,7 +34,7 @@
 import com.android.internal.telephony.SmsHeader;
 import com.android.internal.telephony.SmsMessageBase;
 import com.android.internal.telephony.util.SMSDispatcherUtil;
-
+import com.android.telephony.Rlog;
 
 public class CdmaSMSDispatcher extends SMSDispatcher {
     private static final String TAG = "CdmaSMSDispatcher";
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java
deleted file mode 100644
index 3dc728c..0000000
--- a/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java
+++ /dev/null
@@ -1,198 +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.cdma;
-
-import android.Manifest;
-import android.app.Activity;
-import android.app.AppOpsManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Message;
-import android.provider.Telephony.Sms.Intents;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.SubscriptionManager;
-import android.telephony.cdma.CdmaSmsCbProgramData;
-import android.telephony.cdma.CdmaSmsCbProgramResults;
-
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.WakeLockStateMachine;
-import com.android.internal.telephony.cdma.sms.BearerData;
-import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
-import com.android.internal.telephony.cdma.sms.SmsEnvelope;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * Handle CDMA Service Category Program Data requests and responses.
- */
-public final class CdmaServiceCategoryProgramHandler extends WakeLockStateMachine {
-
-    final CommandsInterface mCi;
-
-    /**
-     * Create a new CDMA inbound SMS handler.
-     */
-    CdmaServiceCategoryProgramHandler(Context context, CommandsInterface commandsInterface,
-            Phone phone) {
-        super("CdmaServiceCategoryProgramHandler", context, phone);
-        mContext = context;
-        mCi = commandsInterface;
-    }
-
-    /**
-     * Create a new State machine for SCPD requests.
-     * @param context the context to use
-     * @param commandsInterface the radio commands interface
-     * @return the new SCPD handler
-     */
-    static CdmaServiceCategoryProgramHandler makeScpHandler(Context context,
-            CommandsInterface commandsInterface, Phone phone) {
-        CdmaServiceCategoryProgramHandler handler = new CdmaServiceCategoryProgramHandler(
-                context, commandsInterface, 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 an ordered broadcast was sent; false on failure
-     */
-    @Override
-    protected boolean handleSmsMessage(Message message) {
-        if (message.obj instanceof SmsMessage) {
-            return handleServiceCategoryProgramData((SmsMessage) message.obj);
-        } else {
-            loge("handleMessage got object of type: " + message.obj.getClass().getName());
-            return false;
-        }
-    }
-
-
-    /**
-     * Send SCPD request to CellBroadcastReceiver as an ordered broadcast.
-     * @param sms the CDMA SmsMessage containing the SCPD request
-     * @return true if an ordered broadcast was sent; false on failure
-     */
-    private boolean handleServiceCategoryProgramData(SmsMessage sms) {
-        ArrayList<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData();
-        if (programDataList == null) {
-            loge("handleServiceCategoryProgramData: program data list is null!");
-            return false;
-        }
-
-        Intent intent = new Intent(Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION);
-        intent.putExtra("sender", sms.getOriginatingAddress());
-        intent.putParcelableArrayListExtra("program_data", programDataList);
-        SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
-
-        String[] pkgs = mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_defaultCellBroadcastReceiverPkgs);
-        mReceiverCount.addAndGet(pkgs.length);
-        for (String pkg : pkgs) {
-            intent.setPackage(pkg);
-            mContext.sendOrderedBroadcast(intent, Manifest.permission.RECEIVE_SMS,
-                    AppOpsManager.OP_RECEIVE_SMS, mScpResultsReceiver,
-                    getHandler(), Activity.RESULT_OK, null, null);
-        }
-        return true;
-    }
-
-    /**
-     * Broadcast receiver to handle results of ordered broadcast. Sends the SCPD results
-     * as a reply SMS, then sends a message to state machine to transition to idle.
-     */
-    private final BroadcastReceiver mScpResultsReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            sendScpResults();
-            if (DBG) log("mScpResultsReceiver finished");
-            if (mReceiverCount.decrementAndGet() == 0) {
-                sendMessage(EVENT_BROADCAST_COMPLETE);
-            }
-        }
-
-        private void sendScpResults() {
-            int resultCode = getResultCode();
-            if ((resultCode != Activity.RESULT_OK) && (resultCode != Intents.RESULT_SMS_HANDLED)) {
-                loge("SCP results error: result code = " + resultCode);
-                return;
-            }
-            Bundle extras = getResultExtras(false);
-            if (extras == null) {
-                loge("SCP results error: missing extras");
-                return;
-            }
-            String sender = extras.getString("sender");
-            if (sender == null) {
-                loge("SCP results error: missing sender extra.");
-                return;
-            }
-            ArrayList<CdmaSmsCbProgramResults> results
-                    = extras.getParcelableArrayList("results");
-            if (results == null) {
-                loge("SCP results error: missing results extra.");
-                return;
-            }
-
-            BearerData bData = new BearerData();
-            bData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
-            bData.messageId = SmsMessage.getNextMessageId();
-            bData.serviceCategoryProgramResults = results;
-            byte[] encodedBearerData = BearerData.encode(bData);
-
-            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
-            DataOutputStream dos = new DataOutputStream(baos);
-            try {
-                dos.writeInt(SmsEnvelope.TELESERVICE_SCPT);
-                dos.writeInt(0); //servicePresent
-                dos.writeInt(0); //serviceCategory
-                CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
-                        PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(sender));
-                dos.write(destAddr.digitMode);
-                dos.write(destAddr.numberMode);
-                dos.write(destAddr.ton); // number_type
-                dos.write(destAddr.numberPlan);
-                dos.write(destAddr.numberOfDigits);
-                dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
-                // Subaddress is not supported.
-                dos.write(0); //subaddressType
-                dos.write(0); //subaddr_odd
-                dos.write(0); //subaddr_nbr_of_digits
-                dos.write(encodedBearerData.length);
-                dos.write(encodedBearerData, 0, encodedBearerData.length);
-                // Ignore the RIL response. TODO: implement retry if SMS send fails.
-                mCi.sendCdmaSms(baos.toByteArray(), null);
-            } catch (IOException e) {
-                loge("exception creating SCP results PDU", e);
-            } finally {
-                try {
-                    dos.close();
-                } catch (IOException ignored) {
-                }
-            }
-        }
-    };
-}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java b/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
index 1380c58..b261dc5 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
@@ -24,10 +24,10 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.provider.Settings;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
+import com.android.telephony.Rlog;
 
 import java.util.concurrent.atomic.AtomicInteger;
 
diff --git a/src/java/com/android/internal/telephony/cdma/EriManager.java b/src/java/com/android/internal/telephony/cdma/EriManager.java
index 782c6b5..8c67149 100644
--- a/src/java/com/android/internal/telephony/cdma/EriManager.java
+++ b/src/java/com/android/internal/telephony/cdma/EriManager.java
@@ -22,11 +22,11 @@
 import android.content.res.XmlResourceParser;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.util.Xml;
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.util.XmlUtils;
+import com.android.telephony.Rlog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java b/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
index b17b492..faa5e1f 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
@@ -19,12 +19,12 @@
 import android.annotation.NonNull;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.IccRecords.OperatorPlmnInfo;
 import com.android.internal.telephony.uicc.IccRecords.PlmnNetworkName;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
index b475767..dad9985 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
@@ -32,7 +32,6 @@
 import android.content.res.Resources;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -49,6 +48,7 @@
 import com.android.internal.telephony.uicc.RuimRecords;
 import com.android.internal.telephony.uicc.SIMRecords;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 import java.util.Collections;
diff --git a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
index bdbf395..477e331 100644
--- a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
@@ -35,7 +35,6 @@
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.Annotation.ApnType;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.IQualifiedNetworksService;
 import android.telephony.data.IQualifiedNetworksServiceCallback;
@@ -45,6 +44,7 @@
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.util.ArrayList;
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index f345429..e614249 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -22,7 +22,6 @@
 import android.net.NetworkRequest;
 import android.os.Message;
 import android.telephony.Annotation.ApnType;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -35,6 +34,7 @@
 import com.android.internal.telephony.dataconnection.DcTracker.ReleaseNetworkType;
 import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType;
 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/dataconnection/ApnSettingUtils.java b/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
index 8403efa..d072a68 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
@@ -20,12 +20,12 @@
 import android.os.PersistableBundle;
 import android.telephony.Annotation.ApnType;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.uicc.IccRecords;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 import java.util.HashSet;
diff --git a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
index b7676b7..9392182 100644
--- a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
+++ b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
@@ -22,7 +22,6 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
@@ -31,6 +30,7 @@
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.List;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 079baa8..1be255b 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.dataconnection;
 
-import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
-import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
+import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED;
+import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
@@ -76,7 +76,6 @@
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.RetryManager;
 import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.dataconnection.DcTracker.ReleaseNetworkType;
 import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
@@ -1302,7 +1301,9 @@
                 result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
             }
 
-            result.maybeMarkCapabilitiesRestricted();
+            if (result.deduceRestrictedCapability()) {
+                result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+            }
         }
 
         if (mRestrictedNetworkOverride) {
@@ -1344,10 +1345,10 @@
         result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
 
         // Override values set above when requested by policy
-        if ((mSubscriptionOverride & OVERRIDE_UNMETERED) != 0) {
+        if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_UNMETERED) != 0) {
             result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         }
-        if ((mSubscriptionOverride & OVERRIDE_CONGESTED) != 0) {
+        if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_CONGESTED) != 0) {
             result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
         }
 
@@ -1477,7 +1478,7 @@
                 }
 
                 for (InetAddress gateway : response.getGatewayAddresses()) {
-                    int mtu = linkProperties.hasGlobalIPv6Address() ? response.getMtuV6()
+                    int mtu = linkProperties.hasGlobalIpv6Address() ? response.getMtuV6()
                             : response.getMtuV4();
                     // Allow 0.0.0.0 or :: as a gateway;
                     // this indicates a point-to-point interface.
@@ -1677,7 +1678,7 @@
                 case EVENT_KEEPALIVE_START_REQUEST:
                 case EVENT_KEEPALIVE_STOP_REQUEST:
                     if (mNetworkAgent != null) {
-                        mNetworkAgent.onSocketKeepaliveEvent(
+                        mNetworkAgent.sendSocketKeepaliveEvent(
                                 msg.arg1, SocketKeepalive.ERROR_INVALID_NETWORK);
                     }
                     break;
@@ -2058,7 +2059,7 @@
 
             final NetworkAgentConfig.Builder configBuilder = new NetworkAgentConfig.Builder();
             final CarrierSignalAgent carrierSignalAgent = mPhone.getCarrierSignalAgent();
-            if (carrierSignalAgent.hasRegisteredReceivers(TelephonyIntents
+            if (carrierSignalAgent.hasRegisteredReceivers(TelephonyManager
                     .ACTION_CARRIER_SIGNAL_REDIRECTED)) {
                 // carrierSignal Receivers will place the carrier-specific provisioning notification
                 configBuilder.disableProvisioningNotification();
@@ -2325,7 +2326,7 @@
                         // so that keepalive requests can be handled (if supported) by the
                         // underlying transport.
                         if (mNetworkAgent != null) {
-                            mNetworkAgent.onSocketKeepaliveEvent(
+                            mNetworkAgent.sendSocketKeepaliveEvent(
                                     msg.arg1, SocketKeepalive.ERROR_INVALID_NETWORK);
                         }
                     }
@@ -2337,7 +2338,8 @@
                     int handle = mNetworkAgent.keepaliveTracker.getHandleForSlot(slotId);
                     if (handle < 0) {
                         loge("No slot found for stopSocketKeepalive! " + slotId);
-                        mNetworkAgent.onSocketKeepaliveEvent(slotId, SocketKeepalive.NO_KEEPALIVE);
+                        mNetworkAgent.sendSocketKeepaliveEvent(
+                                slotId, SocketKeepalive.NO_KEEPALIVE);
                         retVal = HANDLED;
                         break;
                     } else {
@@ -2356,7 +2358,7 @@
                     if (ar.exception != null || ar.result == null) {
                         loge("EVENT_KEEPALIVE_STARTED: error starting keepalive, e="
                                 + ar.exception);
-                        mNetworkAgent.onSocketKeepaliveEvent(
+                        mNetworkAgent.sendSocketKeepaliveEvent(
                                 slot, SocketKeepalive.ERROR_HARDWARE_ERROR);
                     } else {
                         KeepaliveStatus ks = (KeepaliveStatus) ar.result;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataEnabledOverride.java b/src/java/com/android/internal/telephony/dataconnection/DataEnabledOverride.java
index ef5b0ca..a8145df 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataEnabledOverride.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataEnabledOverride.java
@@ -340,7 +340,10 @@
     }
 
     /**
-     * Set allowing mobile data during voice call.
+     * Set allowing mobile data during voice call. This is used for allowing data on the non-default
+     * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will
+     * not be able to use mobile data. By calling this API, data will be temporarily enabled on the
+     * non-default data SIM during the life cycle of the voice call.
      *
      * @param allow {@code true} if allowing using data during voice call, {@code false} if
      * disallowed.
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java b/src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java
index 16ec3d6..8549e33 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java
@@ -31,7 +31,6 @@
 import android.telephony.Annotation.CallState;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -43,6 +42,7 @@
 import com.android.internal.telephony.MultiSimSettingController;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.SubscriptionController;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -264,16 +264,23 @@
     }
 
     /**
-     * Set allowing mobile data during voice call.
+     * Set allowing mobile data during voice call. This is used for allowing data on the non-default
+     * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will
+     * not be able to use mobile data. By calling this API, data will be temporarily enabled on the
+     * non-default data SIM during the life cycle of the voice call.
      *
      * @param allow {@code true} if allowing using data during voice call, {@code false} if
      * disallowed
      *
-     * @return {@code false} if the setting is changed.
+     * @return {@code true} if operation is successful. otherwise {@code false}.
      */
     public synchronized boolean setAllowDataDuringVoiceCall(boolean allow) {
         localLog("setAllowDataDuringVoiceCall", allow);
+        if (allow == isDataAllowedInVoiceCall()) {
+            return true;
+        }
         mDataEnabledOverride.setDataAllowedInVoiceCall(allow);
+
         boolean changed = SubscriptionController.getInstance()
                 .setDataEnabledOverrideRules(mPhone.getSubId(), mDataEnabledOverride.getRules());
         if (changed) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
index 87854bc..a638e16 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
@@ -43,7 +43,6 @@
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.AnomalyReporter;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
@@ -56,6 +55,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.util.HashSet;
 import java.util.List;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index caaed64..abf9e7b 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -27,16 +27,17 @@
 import android.telephony.AccessNetworkConstants;
 import android.telephony.DataFailCause;
 import android.telephony.PhoneStateListener;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.telephony.data.DataCallResponse;
 
 import com.android.internal.telephony.DctConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
+import com.android.internal.telephony.util.HandlerExecutor;
 import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -95,7 +96,7 @@
         setInitialState(mDccDefaultState);
         log("X ctor");
 
-        mPhoneStateListener = new PhoneStateListener(handler.getLooper()) {
+        mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(handler)) {
             @Override
             public void onCarrierNetworkChange(boolean active) {
                 mExecutingCarrierChange = active;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java b/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java
index a68c7b4..420340d 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java
@@ -19,7 +19,8 @@
 import android.content.Intent;
 import android.telephony.Annotation.DataFailureCause;
 import android.telephony.DataFailCause;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * A package visible class for supporting testing failing bringUp commands. This
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java b/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java
index 361934a..f4b26b6 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java
@@ -21,10 +21,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Handler;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 /**
  * To bring down all DC's send the following intent:
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java b/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java
index 74f0e2b..ba07e12 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java
@@ -22,10 +22,10 @@
 import android.content.IntentFilter;
 import android.os.Handler;
 import android.telephony.DataFailCause;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 /**
  * A package level call that causes all DataConnection bringUp calls to fail a specific
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index eb8d56f..0251e90 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -19,6 +19,8 @@
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
+import static android.telephony.data.ApnSetting.PROTOCOL_IPV4V6;
+import static android.telephony.data.ApnSetting.TYPE_DEFAULT;
 
 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
@@ -41,7 +43,6 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.ConnectivityManager;
-import android.net.INetworkPolicyListener;
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
@@ -76,7 +77,6 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PcoData;
 import android.telephony.PreciseDataConnectionState;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.ServiceState.RilRadioTechnology;
 import android.telephony.SubscriptionManager;
@@ -105,7 +105,6 @@
 import com.android.internal.telephony.PhoneSwitcher;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.SettingsObserver;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataAllowedReasonType;
 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
 import com.android.internal.telephony.dataconnection.DataEnabledSettings.DataEnabledChangedReason;
@@ -115,6 +114,7 @@
 import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.AsyncChannel;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -133,6 +133,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
+
 /**
  * {@hide}
  */
@@ -445,8 +446,8 @@
     };
 
     private NetworkPolicyManager mNetworkPolicyManager;
-    private final INetworkPolicyListener mNetworkPolicyListener =
-            new NetworkPolicyManager.Listener() {
+    private final NetworkPolicyManager.SubscriptionCallback mSubscriptionCallback =
+            new NetworkPolicyManager.SubscriptionCallback() {
         @Override
         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
             if (mPhone == null || mPhone.getSubId() != subId) return;
@@ -585,9 +586,9 @@
     private RegistrantList mAllDataDisconnectedRegistrants = new RegistrantList();
 
     // member variables
-    private final Phone mPhone;
+    protected final Phone mPhone;
     private final UiccController mUiccController;
-    private final AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
+    protected final AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
     private DctConstants.Activity mActivity = DctConstants.Activity.NONE;
     private DctConstants.State mState = DctConstants.State.IDLE;
     private final Handler mDataConnectionTracker;
@@ -620,7 +621,7 @@
     private PendingIntent mReconnectIntent = null;
 
     // When false we will not auto attach and manually attaching is required.
-    private boolean mAutoAttachOnCreationConfig = false;
+    protected boolean mAutoAttachOnCreationConfig = false;
     private AtomicBoolean mAutoAttachEnabled = new AtomicBoolean(false);
 
     // State of screen
@@ -746,8 +747,9 @@
         mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
         mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
 
-        mNetworkPolicyManager = NetworkPolicyManager.from(mPhone.getContext());
-        mNetworkPolicyManager.registerListener(mNetworkPolicyListener);
+        mNetworkPolicyManager = (NetworkPolicyManager) mPhone.getContext()
+                .getSystemService(Context.NETWORK_POLICY_SERVICE);
+        mNetworkPolicyManager.registerSubscriptionCallback(mSubscriptionCallback);
 
         HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
         dcHandlerThread.start();
@@ -862,7 +864,7 @@
 
         mSubscriptionManager
                 .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
-        mNetworkPolicyManager.unregisterListener(mNetworkPolicyListener);
+        mNetworkPolicyManager.unregisterSubscriptionCallback(mSubscriptionCallback);
         mDcc.dispose();
         mDcTesterFailBringUpAll.dispose();
 
@@ -1398,7 +1400,7 @@
             reasons.add(DataDisallowedReasonType.ON_IWLAN);
         }
 
-        if (isEmergency()) {
+        if (shouldRestrictDataForEcbm() || mPhone.isInEmergencyCall()) {
             reasons.add(DataDisallowedReasonType.IN_ECBM);
         }
 
@@ -1493,7 +1495,7 @@
     }
 
     // arg for setupDataOnAllConnectableApns
-    private enum RetryFailures {
+    protected enum RetryFailures {
         // retry failed networks always (the old default)
         ALWAYS,
         // retry only when a substantial change has occurred.  Either:
@@ -1502,7 +1504,7 @@
         ONLY_ON_CHANGE
     };
 
-    private void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) {
+    protected void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) {
         if (VDBG) log("setupDataOnAllConnectableApns: " + reason);
 
         if (DBG && !VDBG) {
@@ -1544,10 +1546,11 @@
         }
     }
 
-    boolean isEmergency() {
-        final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall();
-        log("isEmergency: result=" + result);
-        return result;
+    private boolean shouldRestrictDataForEcbm() {
+        boolean isInEcm = mPhone.isInEcm();
+        boolean isInImsEcm = mPhone.getImsPhone() != null && mPhone.getImsPhone().isInImsEcm();
+        log("shouldRestrictDataForEcbm: isInEcm=" + isInEcm + " isInImsEcm=" + isInImsEcm);
+        return isInEcm && !isInImsEcm;
     }
 
     private boolean trySetupData(ApnContext apnContext, @RequestNetworkType int requestType) {
@@ -2053,7 +2056,7 @@
         return true;
     }
 
-    private void setInitialAttachApn() {
+    protected void setInitialAttachApn() {
         ApnSetting iaApnSetting = null;
         ApnSetting defaultApnSetting = null;
         ApnSetting firstNonEmergencyApnSetting = null;
@@ -2085,6 +2088,12 @@
             }
         }
 
+        if ((iaApnSetting == null) && (defaultApnSetting == null) &&
+                !allowInitialAttachForOperator()) {
+            log("Abort Initial attach");
+            return;
+        }
+
         // The priority of apn candidates from highest to lowest is:
         //   1) APN_TYPE_IA (Initial Attach)
         //   2) mPreferredApn, i.e. the current preferred apn
@@ -2117,6 +2126,10 @@
         }
     }
 
+    protected boolean allowInitialAttachForOperator() {
+        return true;
+    }
+
     /**
      * Handles changes to the APN database.
      */
@@ -2266,7 +2279,7 @@
         removeMessages(DctConstants.EVENT_DATA_RECONNECT, apnContext);
     }
 
-    private void onRecordsLoadedOrSubIdChanged() {
+    protected void onRecordsLoadedOrSubIdChanged() {
         if (DBG) log("onRecordsLoadedOrSubIdChanged: createAllApnList");
         if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
             // Auto attach is for cellular only.
@@ -2857,11 +2870,13 @@
                         final byte[] value = new byte[1];
                         value[0] = (byte) pcoVal;
                         final Intent intent =
-                                new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE);
-                        intent.putExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY, "default");
-                        intent.putExtra(TelephonyIntents.EXTRA_APN_PROTO_KEY, "IPV4V6");
-                        intent.putExtra(TelephonyIntents.EXTRA_PCO_ID_KEY, 0xFF00);
-                        intent.putExtra(TelephonyIntents.EXTRA_PCO_VALUE_KEY, value);
+                                new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE);
+                        intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, "default");
+                        intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT, TYPE_DEFAULT);
+                        intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, "IPV4V6");
+                        intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL_INT, PROTOCOL_IPV4V6);
+                        intent.putExtra(TelephonyManager.EXTRA_PCO_ID, 0xFF00);
+                        intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, value);
                         mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
                     }
                 }
@@ -2883,10 +2898,12 @@
                     apn != null ? apn.getApnName() : null, cause);
 
             // Compose broadcast intent send to the specific carrier signaling receivers
-            Intent intent = new Intent(TelephonyIntents
+            Intent intent = new Intent(TelephonyManager
                     .ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED);
-            intent.putExtra(TelephonyIntents.EXTRA_ERROR_CODE_KEY, cause);
-            intent.putExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY, apnContext.getApnType());
+            intent.putExtra(TelephonyManager.EXTRA_ERROR_CODE, cause);
+            intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnContext.getApnType());
+            intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT,
+                    ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType()));
             mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
 
             if (DataFailCause.isRadioRestartFailure(mPhone.getContext(), cause, mPhone.getSubId())
@@ -2946,8 +2963,8 @@
      */
     private void onNetworkStatusChanged(int status, int cid, String redirectUrl) {
         if (!TextUtils.isEmpty(redirectUrl)) {
-            Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
-            intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, redirectUrl);
+            Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED);
+            intent.putExtra(TelephonyManager.EXTRA_REDIRECTION_URL, redirectUrl);
             mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
             log("Notify carrier signal receivers with redirectUrl: " + redirectUrl);
         } else {
@@ -3097,7 +3114,7 @@
         return true;
     }
 
-    private void setDataProfilesAsNeeded() {
+    protected void setDataProfilesAsNeeded() {
         if (DBG) log("setDataProfilesAsNeeded");
 
         ArrayList<DataProfile> dataProfileList = new ArrayList<>();
@@ -3124,7 +3141,7 @@
      * Based on the sim operator numeric, create a list for all possible
      * Data Connections and setup the preferredApn.
      */
-    private void createAllApnList() {
+    protected void createAllApnList() {
         mAllApnSettings.clear();
         IccRecords r = mIccRecords.get();
         String operator = (r != null) ? r.getOperatorNumeric() : "";
@@ -4062,7 +4079,7 @@
                 || plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED);
     }
 
-    private void log(String s) {
+    protected void log(String s) {
         Rlog.d(mLogTag, s);
     }
 
@@ -4513,11 +4530,15 @@
             for (ApnContext apnContext : apnContextList) {
                 String apnType = apnContext.getApnType();
 
-                final Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE);
-                intent.putExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY, apnType);
-                intent.putExtra(TelephonyIntents.EXTRA_APN_PROTO_KEY, pcoData.bearerProto);
-                intent.putExtra(TelephonyIntents.EXTRA_PCO_ID_KEY, pcoData.pcoId);
-                intent.putExtra(TelephonyIntents.EXTRA_PCO_VALUE_KEY, pcoData.contents);
+                final Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE);
+                intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnType);
+                intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT,
+                        ApnSetting.getApnTypesBitmaskFromString(apnType));
+                intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, pcoData.bearerProto);
+                intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL_INT,
+                        ApnSetting.getProtocolIntFromString(pcoData.bearerProto));
+                intent.putExtra(TelephonyManager.EXTRA_PCO_ID, pcoData.pcoId);
+                intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, pcoData.contents);
                 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
             }
         }
diff --git a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
index 8b0ecad..0f80fce 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
@@ -29,7 +29,6 @@
 import android.os.Message;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.ApnType;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.data.ApnSetting;
 import android.util.LocalLog;
@@ -42,6 +41,7 @@
 import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType;
 import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams;
 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/dataconnection/TransportManager.java b/src/java/com/android/internal/telephony/dataconnection/TransportManager.java
index 6a2af7c..5635089 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TransportManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TransportManager.java
@@ -28,7 +28,6 @@
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.Annotation.ApnType;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.util.LocalLog;
 import android.util.SparseArray;
@@ -40,6 +39,7 @@
 import com.android.internal.telephony.dataconnection.AccessNetworksManager.QualifiedNetworks;
 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;
@@ -297,7 +297,7 @@
     }
 
     private static boolean areNetworksValid(QualifiedNetworks networks) {
-        if (networks.qualifiedNetworks == null) {
+        if (networks.qualifiedNetworks == null || networks.qualifiedNetworks.length == 0) {
             return false;
         }
         for (int network : networks.qualifiedNetworks) {
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 7440e1d..426d2a2 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -28,7 +28,7 @@
 import android.os.SystemProperties;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting;
@@ -48,6 +48,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.phone.ecc.nano.ProtobufEccData;
 import com.android.phone.ecc.nano.ProtobufEccData.EccInfo;
+import com.android.telephony.Rlog;
 
 import com.google.i18n.phonenumbers.ShortNumberInfo;
 
@@ -144,17 +145,27 @@
                             TelephonyManager.EXTRA_NETWORK_COUNTRY);
                     logd("ACTION_NETWORK_COUNTRY_CHANGED: PhoneId: " + phoneId + " CountryIso: "
                             + countryIso);
+
+                    boolean isInApm = false;
+                    ServiceStateTracker serviceStateTracker = mPhone.getServiceStateTracker();
+                    if (serviceStateTracker != null) {
+                        if (serviceStateTracker.getServiceState().getState()
+                                == ServiceState.STATE_POWER_OFF) {
+                            isInApm = true;
+                        }
+                    }
                     // Sometimes the country is updated as an empty string when the network signal
                     // is lost; though we may not call emergency when there is no signal, we want
                     // to keep the old country iso to provide country-related emergency numbers,
                     // because they think they are still in that country. We don't need to update
-                    // country change in this case.
-                    if (TextUtils.isEmpty(countryIso)) {
+                    // country change in this case. We will still need to update the empty string
+                    // if device is in APM.
+                    if (TextUtils.isEmpty(countryIso) && !isInApm) {
                         return;
                     }
 
                     // Update country iso change for available Phones
-                    updateEmergencyCountryIsoAllPhones(countryIso);
+                    updateEmergencyCountryIsoAllPhones(countryIso == null ? "" : countryIso);
                 }
                 return;
             }
@@ -1067,6 +1078,12 @@
         ipw.println(" Hal Version:" + mPhone.getHalVersion());
         ipw.println(" ========================================= ");
 
+        ipw.println(" Country Iso:" + getEmergencyCountryIso());
+        ipw.println(" ========================================= ");
+
+        ipw.println(" Database Version:" + getEmergencyNumberDbVersion());
+        ipw.println(" ========================================= ");
+
         ipw.println("mEmergencyNumberListDatabaseLocalLog:");
         ipw.increaseIndent();
         mEmergencyNumberListDatabaseLocalLog.dump(fd, pw, args);
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index 8b1bd33..5b2c3c6 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -46,6 +46,7 @@
 import android.service.euicc.IDownloadSubscriptionCallback;
 import android.service.euicc.IEraseSubscriptionsCallback;
 import android.service.euicc.IEuiccService;
+import android.service.euicc.IEuiccServiceDumpResultCallback;
 import android.service.euicc.IGetDefaultDownloadableSubscriptionListCallback;
 import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback;
 import android.service.euicc.IGetEidCallback;
@@ -95,7 +96,7 @@
      * true or onServiceDisconnected is called (and no package change has occurred which should
      * force us to reestablish the binding).
      */
-    private static final int BIND_TIMEOUT_MILLIS = 30000;
+    static final int BIND_TIMEOUT_MILLIS = 30000;
 
     /**
      * Maximum amount of idle time to hold the binding while in {@link ConnectedState}. After this,
@@ -147,6 +148,7 @@
     private static final int CMD_GET_OTA_STATUS = 111;
     private static final int CMD_START_OTA_IF_NECESSARY = 112;
     private static final int CMD_ERASE_SUBSCRIPTIONS_WITH_OPTIONS = 113;
+    private static final int CMD_DUMP_EUICC_SERVICE = 114;
 
     private static boolean isEuiccCommand(int what) {
         return what >= CMD_GET_EID;
@@ -154,7 +156,7 @@
 
     /** Flags to use when querying PackageManager for Euicc component implementations. */
     private static final int EUICC_QUERY_FLAGS =
-            PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
+            PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DIRECT_BOOT_AUTO
                     | PackageManager.GET_RESOLVED_FILTER;
 
     /**
@@ -322,6 +324,13 @@
         void onRetainSubscriptionsComplete(int result);
     }
 
+    /** Callback class for {@link #dumpEuiccService(DumpEuiccCommandCallback)}   }*/
+    @VisibleForTesting(visibility = PACKAGE)
+    public interface DumpEuiccServiceCommandCallback extends BaseEuiccCommandCallback {
+        /** Called when the retain command has completed (though it may have failed). */
+        void onDumpEuiccServiceComplete(String logs);
+    }
+
     private Context mContext;
     private PackageManager mPm;
     private TelephonyManager mTm;
@@ -521,6 +530,14 @@
         sendMessage(CMD_RETAIN_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback);
     }
 
+    /** Asynchronously calls the currently bound EuiccService implementation to dump its states */
+    @VisibleForTesting(visibility = PACKAGE)
+    public void dumpEuiccService(DumpEuiccServiceCommandCallback callback) {
+        sendMessage(CMD_DUMP_EUICC_SERVICE, TelephonyManager.UNSUPPORTED_CARD_ID /* ignored */,
+                0 /* arg2 */,
+                callback);
+    }
+
     /**
      * State in which no EuiccService is available.
      *
@@ -923,6 +940,20 @@
                                     });
                             break;
                         }
+                        case CMD_DUMP_EUICC_SERVICE: {
+                            mEuiccService.dump(new IEuiccServiceDumpResultCallback.Stub() {
+                                @Override
+                                public void onComplete(String logs)
+                                        throws RemoteException {
+                                    sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
+                                        ((DumpEuiccServiceCommandCallback) callback)
+                                                .onDumpEuiccServiceComplete(logs);
+                                        onCommandEnd(callback);
+                                    });
+                                }
+                            });
+                            break;
+                        }
                         default: {
                             Log.wtf(TAG, "Unimplemented eUICC command: " + message.what);
                             callback.onEuiccServiceUnavailable();
@@ -968,6 +999,7 @@
             case CMD_RETAIN_SUBSCRIPTIONS:
             case CMD_GET_OTA_STATUS:
             case CMD_START_OTA_IF_NECESSARY:
+            case CMD_DUMP_EUICC_SERVICE:
                 return (BaseEuiccCommandCallback) message.obj;
             case CMD_GET_DOWNLOADABLE_SUBSCRIPTION_METADATA:
                 return ((GetMetadataRequest) message.obj).mCallback;
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 694db12..fbca21b 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -15,8 +15,11 @@
  */
 package com.android.internal.telephony.euicc;
 
+import static com.android.internal.telephony.euicc.EuiccConnector.BIND_TIMEOUT_MILLIS;
+
 import android.Manifest;
 import android.Manifest.permission;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -53,8 +56,10 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
 /** Backing implementation of {@link android.telephony.euicc.EuiccManager}. */
@@ -83,6 +88,11 @@
     private final AppOpsManager mAppOpsManager;
     private final PackageManager mPackageManager;
 
+    // These values should be set or updated upon 1) system boot, 2) EuiccService/LPA is bound to
+    // the phone process, 3) values are updated remotely by server flags.
+    private List<String> mSupportedCountries;
+    private List<String> mUnsupportedCountries;
+
     /** Initialize the instance. Should only be called once. */
     public static EuiccController init(Context context) {
         synchronized (EuiccController.class) {
@@ -241,6 +251,89 @@
                 subscription, false /* forceDeactivateSim */, callingPackage, callbackIntent);
     }
 
+    /**
+     * Sets the supported or unsupported countries for eUICC.
+     *
+     * <p>If {@code isSupported} is true, the supported country list will be replaced by
+     * {@code countriesList}. Otherwise, unsupported country list will be replaced by
+     * {@code countriesList}. For how we determine whether a country is supported by checking
+     * supported and unsupported country list please check {@link EuiccManager#isSupportedCountry}.
+     *
+     * @param isSupported should be true if caller wants to set supported country list. If
+     * isSupported is false, un-supported country list will be updated.
+     * @param countriesList is a list of strings contains country ISO codes in uppercase.
+     */
+    @Override
+    public void setSupportedCountries(boolean isSupported, @NonNull List<String> countriesList) {
+        if (isSupported) {
+            mSupportedCountries = countriesList;
+        } else {
+            mUnsupportedCountries = countriesList;
+        }
+    }
+
+    /**
+     * Gets the supported or unsupported countries for eUICC.
+     *
+     * <p>If {@code isSupported} is true, the supported country list will be returned. Otherwise,
+     * unsupported country list will be returned.
+     *
+     * @param isSupported should be true if caller wants to get supported country list. If
+     * isSupported is false, unsupported country list will be returned.
+     * @return a list of strings contains country ISO codes in uppercase.
+     */
+    @Override
+    @NonNull
+    public List<String> getSupportedCountries(boolean isSupported) {
+        if (isSupported && mSupportedCountries != null) {
+            return mSupportedCountries;
+        } else if (!isSupported && mUnsupportedCountries != null) {
+            return mUnsupportedCountries;
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns whether the given country supports eUICC.
+     *
+     * <p>Supported country list has a higher prority than unsupported country list. If the
+     * supported country list is not empty, {@code countryIso} will be considered as supported when
+     * it exists in the supported country list. Otherwise {@code countryIso} is not supported. If
+     * the supported country list is empty, {@code countryIso} will be considered as supported if it
+     * does not exist in the unsupported country list. Otherwise {@code countryIso} is not
+     * supported. If both supported and unsupported country lists are empty, then all countries are
+     * consider be supported. For how to set supported and unsupported country list, please check
+     * {@link #setSupportedCountries}.
+     *
+     * @param countryIso should be the ISO-3166 country code is provided in uppercase 2 character
+     * format.
+     * @return whether the given country supports eUICC or not.
+     */
+    @Override
+    public boolean isSupportedCountry(@NonNull String countryIso) {
+        if (mSupportedCountries == null || mSupportedCountries.isEmpty()) {
+            Log.i(TAG, "Using blacklist unsupportedCountries=" + mUnsupportedCountries);
+            return !isEsimUnsupportedCountry(countryIso);
+        } else {
+            Log.i(TAG, "Using whitelist supportedCountries=" + mSupportedCountries);
+            return isEsimSupportedCountry(countryIso);
+        }
+    }
+
+    private boolean isEsimSupportedCountry(String countryIso) {
+        if (mSupportedCountries == null || TextUtils.isEmpty(countryIso)) {
+            return true;
+        }
+        return mSupportedCountries.contains(countryIso);
+    }
+
+    private boolean isEsimUnsupportedCountry(String countryIso) {
+        if (mUnsupportedCountries == null || TextUtils.isEmpty(countryIso)) {
+            return false;
+        }
+        return mUnsupportedCountries.contains(countryIso);
+    }
+
     void getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription,
             boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) {
         if (!callerCanWriteEmbeddedSubscriptions()) {
@@ -1110,12 +1203,37 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");
         final long token = Binder.clearCallingIdentity();
+        pw.println("===== BEGIN EUICC CLINIC =====");
         try {
+            pw.println("===== EUICC CONNECTOR =====");
             mConnector.dump(fd, pw, args);
+            final CountDownLatch countDownLatch = new CountDownLatch(1);
+            mConnector.dumpEuiccService(new EuiccConnector.DumpEuiccServiceCommandCallback() {
+                @Override
+                public void onDumpEuiccServiceComplete(String logs) {
+                    pw.println("===== EUICC SERVICE =====");
+                    pw.println(logs);
+                    countDownLatch.countDown();
+                }
+
+                @Override
+                public void onEuiccServiceUnavailable() {
+                    pw.println("===== EUICC SERVICE UNAVAILABLE =====");
+                    countDownLatch.countDown();
+                }
+            });
+
+            // Wait up to 30 seconds
+            if (!countDownLatch.await(BIND_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+                pw.println("===== EUICC SERVICE TIMEOUT =====");
+            }
+        } catch (InterruptedException e) {
+            pw.println("===== EUICC SERVICE INTERRUPTED =====");
         } finally {
+            pw.println("===== END EUICC CLINIC =====");
             Binder.restoreCallingIdentity(token);
         }
     }
diff --git a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java b/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
deleted file mode 100644
index e8297fc..0000000
--- a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
+++ /dev/null
@@ -1,380 +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.gsm;
-
-import static com.android.internal.telephony.gsm.SmsCbConstants.MESSAGE_ID_CMAS_GEO_FENCING_TRIGGER;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.AsyncResult;
-import android.os.Message;
-import android.provider.Telephony.CellBroadcasts;
-import android.telephony.CbGeoUtils.Geometry;
-import android.telephony.CellLocation;
-import android.telephony.SmsCbLocation;
-import android.telephony.SmsCbMessage;
-import android.telephony.TelephonyManager;
-import android.telephony.gsm.GsmCellLocation;
-import android.text.format.DateUtils;
-
-import com.android.internal.telephony.CellBroadcastHandler;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage;
-import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Handler for 3GPP format Cell Broadcasts. Parent class can also handle CDMA Cell Broadcasts.
- */
-public class GsmCellBroadcastHandler extends CellBroadcastHandler {
-    private static final boolean VDBG = false;  // log CB PDU data
-
-    /** Indicates that a message is not being broadcasted. */
-    private static final String MESSAGE_NOT_BROADCASTED = "0";
-
-    /** This map holds incomplete concatenated messages waiting for assembly. */
-    @UnsupportedAppUsage
-    private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap =
-            new HashMap<SmsCbConcatInfo, byte[][]>(4);
-
-    protected GsmCellBroadcastHandler(Context context, Phone phone) {
-        super("GsmCellBroadcastHandler", context, phone);
-        phone.mCi.setOnNewGsmBroadcastSms(getHandler(), EVENT_NEW_SMS_MESSAGE, null);
-    }
-
-    @Override
-    protected void onQuitting() {
-        mPhone.mCi.unSetOnNewGsmBroadcastSms(getHandler());
-        super.onQuitting();     // release wakelock
-    }
-
-    /**
-     * Create a new CellBroadcastHandler.
-     * @param context the context to use for dispatching Intents
-     * @return the new handler
-     */
-    public static GsmCellBroadcastHandler makeGsmCellBroadcastHandler(Context context,
-            Phone phone) {
-        GsmCellBroadcastHandler handler = new GsmCellBroadcastHandler(context, phone);
-        handler.start();
-        return handler;
-    }
-
-    /**
-     * Find the cell broadcast messages specify by the geo-fencing trigger message and perform a
-     * geo-fencing check for these messages.
-     * @param geoFencingTriggerMessage the trigger message
-     *
-     * @return {@code True} if geo-fencing is need for some cell broadcast message.
-     */
-    private boolean handleGeoFencingTriggerMessage(
-            GeoFencingTriggerMessage geoFencingTriggerMessage) {
-        final List<SmsCbMessage> cbMessages = new ArrayList<>();
-        final List<Uri> cbMessageUris = new ArrayList<>();
-
-        // Only consider the cell broadcast received within 24 hours.
-        long lastReceivedTime = System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS;
-
-        // Find the cell broadcast message identify by the message identifier and serial number
-        // and is not broadcasted.
-        String where = CellBroadcasts.SERVICE_CATEGORY + "=? AND "
-                + CellBroadcasts.SERIAL_NUMBER + "=? AND "
-                + CellBroadcasts.MESSAGE_BROADCASTED + "=? AND "
-                + CellBroadcasts.RECEIVED_TIME + ">?";
-
-        ContentResolver resolver = mContext.getContentResolver();
-        for (CellBroadcastIdentity identity : geoFencingTriggerMessage.cbIdentifiers) {
-            try (Cursor cursor = resolver.query(CELL_BROADCAST_URI,
-                    CellBroadcasts.QUERY_COLUMNS_FWK,
-                    where,
-                    new String[] { Integer.toString(identity.messageIdentifier),
-                            Integer.toString(identity.serialNumber), MESSAGE_NOT_BROADCASTED,
-                            Long.toString(lastReceivedTime) },
-                    null /* sortOrder */)) {
-                if (cursor != null) {
-                    while (cursor.moveToNext()) {
-                        cbMessages.add(SmsCbMessage.createFromCursor(cursor));
-                        cbMessageUris.add(ContentUris.withAppendedId(CELL_BROADCAST_URI,
-                                cursor.getInt(cursor.getColumnIndex(CellBroadcasts._ID))));
-                    }
-                }
-            }
-        }
-
-        List<Geometry> commonBroadcastArea = new ArrayList<>();
-        if (geoFencingTriggerMessage.shouldShareBroadcastArea()) {
-            for (SmsCbMessage msg : cbMessages) {
-                if (msg.getGeometries() != null) {
-                    commonBroadcastArea.addAll(msg.getGeometries());
-                }
-            }
-        }
-
-        // ATIS doesn't specify the geo fencing maximum wait time for the cell broadcasts specified
-        // in geo fencing trigger message. We will pick the largest maximum wait time among these
-        // cell broadcasts.
-        int maximumWaitTimeSec = 0;
-        for (SmsCbMessage msg : cbMessages) {
-            maximumWaitTimeSec = Math.max(maximumWaitTimeSec, msg.getMaximumWaitingDuration());
-        }
-
-        if (DBG) {
-            logd("Geo-fencing trigger message = " + geoFencingTriggerMessage);
-            for (SmsCbMessage msg : cbMessages) {
-                logd(msg.toString());
-            }
-        }
-
-        if (cbMessages.isEmpty()) {
-            if (DBG) logd("No CellBroadcast message need to be broadcasted");
-            return false;
-        }
-
-        requestLocationUpdate(location -> {
-            if (location == null) {
-                // If the location is not available, broadcast the messages directly.
-                broadcastMessage(cbMessages, cbMessageUris);
-            } else {
-                for (int i = 0; i < cbMessages.size(); i++) {
-                    List<Geometry> broadcastArea = !commonBroadcastArea.isEmpty()
-                            ? commonBroadcastArea : cbMessages.get(i).getGeometries();
-                    if (broadcastArea == null || broadcastArea.isEmpty()) {
-                        broadcastMessage(cbMessages.get(i), cbMessageUris.get(i));
-                    } else {
-                        performGeoFencing(cbMessages.get(i), cbMessageUris.get(i), broadcastArea,
-                                location);
-                    }
-                }
-            }
-        }, maximumWaitTimeSec);
-        return true;
-    }
-
-    /**
-     * Handle 3GPP-format Cell Broadcast messages sent from radio.
-     *
-     * @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 AsyncResult) {
-            SmsCbHeader header = createSmsCbHeader((AsyncResult) message.obj);
-            if (header == null) return false;
-
-            AsyncResult ar = (AsyncResult) message.obj;
-            byte[] pdu = (byte[]) ar.result;
-            if (header.getServiceCategory() == MESSAGE_ID_CMAS_GEO_FENCING_TRIGGER) {
-                GeoFencingTriggerMessage triggerMessage =
-                        GsmSmsCbMessage.createGeoFencingTriggerMessage(pdu);
-                if (triggerMessage != null) {
-                    return handleGeoFencingTriggerMessage(triggerMessage);
-                }
-            } else {
-                SmsCbMessage cbMessage = handleGsmBroadcastSms(header, ar);
-                if (cbMessage != null) {
-                    handleBroadcastSms(cbMessage);
-                    return true;
-                }
-                if (VDBG) log("Not handled GSM broadcasts.");
-            }
-        }
-        return super.handleSmsMessage(message);
-    }
-
-    /**
-     * Handle 3GPP format SMS-CB message.
-     * @param header the cellbroadcast header.
-     * @param ar the AsyncResult containing the received PDUs
-     */
-    private SmsCbMessage handleGsmBroadcastSms(SmsCbHeader header, AsyncResult ar) {
-        try {
-            byte[] receivedPdu = (byte[]) ar.result;
-
-            if (VDBG) {
-                int pduLength = receivedPdu.length;
-                for (int i = 0; i < pduLength; i += 8) {
-                    StringBuilder sb = new StringBuilder("SMS CB pdu data: ");
-                    for (int j = i; j < i + 8 && j < pduLength; j++) {
-                        int b = receivedPdu[j] & 0xff;
-                        if (b < 0x10) {
-                            sb.append('0');
-                        }
-                        sb.append(Integer.toHexString(b)).append(' ');
-                    }
-                    log(sb.toString());
-                }
-            }
-
-            if (VDBG) log("header=" + header);
-            String plmn = TelephonyManager.from(mContext).getNetworkOperatorForPhone(
-                    mPhone.getPhoneId());
-            int lac = -1;
-            int cid = -1;
-            CellLocation cl = mPhone.getCellIdentity().asCellLocation();
-            // Check if cell location is GsmCellLocation.  This is required to support
-            // dual-mode devices such as CDMA/LTE devices that require support for
-            // both 3GPP and 3GPP2 format messages
-            if (cl instanceof GsmCellLocation) {
-                GsmCellLocation cellLocation = (GsmCellLocation)cl;
-                lac = cellLocation.getLac();
-                cid = cellLocation.getCid();
-            }
-
-            SmsCbLocation location;
-            switch (header.getGeographicalScope()) {
-                case SmsCbMessage.GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE:
-                    location = new SmsCbLocation(plmn, lac, -1);
-                    break;
-
-                case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE:
-                case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE:
-                    location = new SmsCbLocation(plmn, lac, cid);
-                    break;
-
-                case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE:
-                default:
-                    location = new SmsCbLocation(plmn);
-                    break;
-            }
-
-            byte[][] pdus;
-            int pageCount = header.getNumberOfPages();
-            if (pageCount > 1) {
-                // Multi-page message
-                SmsCbConcatInfo concatInfo = new SmsCbConcatInfo(header, location);
-
-                // Try to find other pages of the same message
-                pdus = mSmsCbPageMap.get(concatInfo);
-
-                if (pdus == null) {
-                    // This is the first page of this message, make room for all
-                    // pages and keep until complete
-                    pdus = new byte[pageCount][];
-
-                    mSmsCbPageMap.put(concatInfo, pdus);
-                }
-
-                if (VDBG) log("pdus size=" + pdus.length);
-                // Page parameter is one-based
-                pdus[header.getPageIndex() - 1] = receivedPdu;
-
-                for (byte[] pdu : pdus) {
-                    if (pdu == null) {
-                        // Still missing pages, exit
-                        log("still missing pdu");
-                        return null;
-                    }
-                }
-
-                // Message complete, remove and dispatch
-                mSmsCbPageMap.remove(concatInfo);
-            } else {
-                // Single page message
-                pdus = new byte[1][];
-                pdus[0] = receivedPdu;
-            }
-
-            // Remove messages that are out of scope to prevent the map from
-            // growing indefinitely, containing incomplete messages that were
-            // never assembled
-            Iterator<SmsCbConcatInfo> iter = mSmsCbPageMap.keySet().iterator();
-
-            while (iter.hasNext()) {
-                SmsCbConcatInfo info = iter.next();
-
-                if (!info.matchesLocation(plmn, lac, cid)) {
-                    iter.remove();
-                }
-            }
-
-            return GsmSmsCbMessage.createSmsCbMessage(mContext, header, location, pdus,
-                mPhone.getPhoneId());
-
-        } catch (RuntimeException e) {
-            loge("Error in decoding SMS CB pdu", e);
-            return null;
-        }
-    }
-
-    private SmsCbHeader createSmsCbHeader(AsyncResult ar) {
-        try {
-            return new SmsCbHeader((byte[]) ar.result);
-        } catch (Exception ex) {
-            loge("Can't create SmsCbHeader, ex = " + ex.toString());
-            return null;
-        }
-    }
-
-    /**
-     * Holds all info about a message page needed to assemble a complete concatenated message.
-     */
-    private static final class SmsCbConcatInfo {
-
-        private final SmsCbHeader mHeader;
-        private final SmsCbLocation mLocation;
-
-        @UnsupportedAppUsage
-        SmsCbConcatInfo(SmsCbHeader header, SmsCbLocation location) {
-            mHeader = header;
-            mLocation = location;
-        }
-
-        @Override
-        public int hashCode() {
-            return (mHeader.getSerialNumber() * 31) + mLocation.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof SmsCbConcatInfo) {
-                SmsCbConcatInfo other = (SmsCbConcatInfo)obj;
-
-                // Two pages match if they have the same serial number (which includes the
-                // geographical scope and update number), and both pages belong to the same
-                // location (PLMN, plus LAC and CID if these are part of the geographical scope).
-                return mHeader.getSerialNumber() == other.mHeader.getSerialNumber()
-                        && mLocation.equals(other.mLocation);
-            }
-
-            return false;
-        }
-
-        /**
-         * Compare the location code for this message to the current location code. The match is
-         * relative to the geographical scope of the message, which determines whether the LAC
-         * and Cell ID are saved in mLocation or set to -1 to match all values.
-         *
-         * @param plmn the current PLMN
-         * @param lac the current Location Area (GSM) or Service Area (UMTS)
-         * @param cid the current Cell ID
-         * @return true if this message is valid for the current location; false otherwise
-         */
-        @UnsupportedAppUsage
-        public boolean matchesLocation(String plmn, int lac, int cid) {
-            return mLocation.isInLocationArea(plmn, lac, cid);
-        }
-    }
-}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
index 96d9752..47f75ca 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
@@ -51,30 +51,22 @@
     private static final boolean TEST_MODE = SystemProperties.getInt("ro.debuggable", 0) == 1;
     private static final String TEST_ACTION = "com.android.internal.telephony.gsm"
             + ".TEST_TRIGGER_CELL_BROADCAST";
-    private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.gsm"
-            + ".TOGGLE_CB_MODULE";
 
     /**
      * Create a new GSM inbound SMS handler.
      */
     private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
             Phone phone) {
-        super("GsmInboundSmsHandler", context, storageMonitor, phone, null);
+        super("GsmInboundSmsHandler", context, storageMonitor, phone);
         phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
         mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId());
-        if (sEnableCbModule) {
-            mCellBroadcastServiceManager.enable();
-        } else {
-            mCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context,
-                    phone);
-        }
+        mCellBroadcastServiceManager.enable();
 
         if (TEST_MODE) {
             if (sTestBroadcastReceiver == null) {
                 sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver();
                 IntentFilter filter = new IntentFilter();
                 filter.addAction(TEST_ACTION);
-                filter.addAction(TOGGLE_CB_MODULE);
                 context.registerReceiver(sTestBroadcastReceiver, filter);
             }
         }
@@ -94,16 +86,11 @@
      * --es pdu_string  0000110011010D0A5BAE57CE770C531790E85C716CBF3044573065B9306757309707767 \
      * A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09000000000000000 \
      * 0000000000000 --ei phone_id 0
-     *
-     * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE
-     *
-     * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE \
-     * --ez enable true
      */
     private class GsmCbTestBroadcastReceiver extends CbTestBroadcastReceiver {
 
         GsmCbTestBroadcastReceiver() {
-            super(TEST_ACTION, TOGGLE_CB_MODULE);
+            super(TEST_ACTION);
         }
 
         @Override
@@ -126,30 +113,7 @@
             }
             Message m = Message.obtain();
             AsyncResult.forMessage(m, smsPdu, null);
-            if (sEnableCbModule) {
-                mCellBroadcastServiceManager.sendGsmMessageToHandler(m);
-            } else {
-                m.what = GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE;
-                mCellBroadcastHandler.sendMessage(m);
-            }
-        }
-
-        @Override
-        protected void handleToggleEnable() {
-            mPhone.mCi.unSetOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler());
-            mCellBroadcastServiceManager.enable();
-        }
-
-        @Override
-        protected void handleToggleDisable(Context context) {
-            mCellBroadcastServiceManager.disable();
-            if (mCellBroadcastHandler == null) {
-                mCellBroadcastHandler =
-                        GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context,
-                                mPhone);
-            }
-            mPhone.mCi.setOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler(),
-                    GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE, null);
+            mCellBroadcastServiceManager.sendGsmMessageToHandler(m);
         }
     }
 
@@ -159,7 +123,6 @@
     @Override
     protected void onQuitting() {
         mPhone.mCi.unSetOnNewGsmSms(getHandler());
-        mCellBroadcastHandler.dispose();
 
         if (DBG) log("unregistered for 3GPP SMS");
         super.onQuitting();     // release wakelock
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 0949389..d8bc86c 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -37,7 +37,6 @@
 import android.os.ResultReceiver;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.text.BidiFormatter;
 import android.text.SpannableStringBuilder;
 import android.text.TextDirectionHeuristics;
@@ -55,6 +54,7 @@
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.util.ArrayUtils;
+import com.android.telephony.Rlog;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -380,12 +380,7 @@
                             isServiceClassVoiceorNone(ssData.serviceClass));
 
                     Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag cffEnabled: " + cffEnabled);
-                    if (mIccRecords != null) {
-                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, null);
-                        Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag done from SS Info.");
-                    } else {
-                        Rlog.e(LOG_TAG, "setVoiceCallForwardingFlag aborted. sim records is null.");
-                    }
+                    mPhone.setVoiceCallForwardingFlag(1, cffEnabled, null);
                 }
                 onSetComplete(null, new AsyncResult(null, ssData.cfInfo, ex));
                 break;
@@ -1209,9 +1204,7 @@
                 */
                 if ((ar.exception == null) && (msg.arg1 == 1)) {
                     boolean cffEnabled = (msg.arg2 == 1);
-                    if (mIccRecords != null) {
-                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
-                    }
+                    mPhone.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
                 }
 
                 onSetComplete(msg, ar);
@@ -1585,9 +1578,7 @@
                 (info.serviceClass & serviceClassMask)
                         == CommandsInterface.SERVICE_CLASS_VOICE) {
             boolean cffEnabled = (info.status == 1);
-            if (mIccRecords != null) {
-                mPhone.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
-            }
+            mPhone.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
         }
 
         return TextUtils.replace(template, sources, destinations);
@@ -1614,14 +1605,12 @@
 
             infos = (CallForwardInfo[]) ar.result;
 
-            if (infos.length == 0) {
+            if (infos == null || infos.length == 0) {
                 // Assume the default is not active
                 sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
 
                 // Set unconditional CFF in SIM to false
-                if (mIccRecords != null) {
-                    mPhone.setVoiceCallForwardingFlag(1, false, null);
-                }
+                mPhone.setVoiceCallForwardingFlag(1, false, null);
             } else {
 
                 SpannableStringBuilder tb = new SpannableStringBuilder();
diff --git a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index de7977b..e4044d2 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -22,7 +22,6 @@
 import android.os.AsyncResult;
 import android.os.Message;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.util.Pair;
 
@@ -39,6 +38,7 @@
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.util.SMSDispatcherUtil;
+import com.android.telephony.Rlog;
 
 import java.util.HashMap;
 import java.util.concurrent.atomic.AtomicReference;
diff --git a/src/java/com/android/internal/telephony/gsm/SsData.java b/src/java/com/android/internal/telephony/gsm/SsData.java
index a5f67d8..41fa45e 100644
--- a/src/java/com/android/internal/telephony/gsm/SsData.java
+++ b/src/java/com/android/internal/telephony/gsm/SsData.java
@@ -19,11 +19,9 @@
 
 package com.android.internal.telephony.gsm;
 
-import android.telephony.Rlog;
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.GsmCdmaPhone;
-
-import java.util.ArrayList;
+import com.android.telephony.Rlog;
 
 /**
  * See also RIL_StkCcUnsolSsResponse in include/telephony/ril.h
diff --git a/src/java/com/android/internal/telephony/gsm/UsimDataDownloadHandler.java b/src/java/com/android/internal/telephony/gsm/UsimDataDownloadHandler.java
index 91cbbf0..5d08846 100644
--- a/src/java/com/android/internal/telephony/gsm/UsimDataDownloadHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/UsimDataDownloadHandler.java
@@ -22,7 +22,6 @@
 import android.os.Message;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.SmsManager;
 
 import com.android.internal.telephony.CommandsInterface;
@@ -31,6 +30,7 @@
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.UsimServiceTable;
+import com.android.telephony.Rlog;
 
 /**
  * Handler for SMS-PP data download messages.
diff --git a/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index 7594d3b..f6fc069 100755
--- a/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -20,7 +20,6 @@
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
@@ -29,6 +28,7 @@
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccFileHandler;
 import com.android.internal.telephony.uicc.IccUtils;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsExternalConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsExternalConnection.java
index b29acdb..414cbf8 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsExternalConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsExternalConnection.java
@@ -133,6 +133,18 @@
     }
 
     @Override
+    public void transfer(String number, boolean isConfirmationRequired) throws CallStateException {
+        // Transfer is not supported for external calls.
+        throw new CallStateException("Transfer is not supported for external calls");
+    }
+
+    @Override
+    public void consultativeTransfer(Connection other) throws CallStateException {
+        // Transfer is not supported for external calls.
+        throw new CallStateException("Transfer is not supported for external calls");
+    }
+
+    @Override
     public void separate() throws CallStateException {
         // No-op - Separate is not supported for external calls.
     }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 275b428..1942653 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -50,8 +50,6 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.NetworkStats;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Bundle;
@@ -69,7 +67,6 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -80,18 +77,15 @@
 import android.telephony.ims.ImsSsData;
 import android.telephony.ims.ImsSsInfo;
 import android.telephony.ims.RegistrationManager;
-import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.stub.ImsUtImplBase;
 import android.text.TextUtils;
 import android.util.LocalLog;
 
-import com.android.ims.FeatureConnector;
 import com.android.ims.ImsEcbm;
 import com.android.ims.ImsEcbmStateListener;
 import com.android.ims.ImsException;
 import com.android.ims.ImsManager;
 import com.android.ims.ImsUtInterface;
-import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallForwardInfo;
@@ -117,6 +111,7 @@
 import com.android.internal.telephony.uicc.IccRecords;
 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;
@@ -212,13 +207,6 @@
     @UnsupportedAppUsage
     private ServiceState mSS = new ServiceState();
 
-    private RcsFeatureManager mRcsManager;
-    @VisibleForTesting
-    public FeatureConnector<RcsFeatureManager> mRcsManagerConnector;
-    @VisibleForTesting
-    public FeatureConnector.Listener<RcsFeatureManager> mRcsFeatureConnectorListener;
-    public ImsRcsStatusListener mRcsStatusListener;
-
     // To redial silently through GSM or CDMA when dialing through IMS fails
     private String mLastDialString;
 
@@ -233,12 +221,13 @@
     private final LocalLog mRegLocalLog = new LocalLog(100);
     private TelephonyMetrics mMetrics;
 
-    // The helper class to receive and store the MmTel and RCS registration status updated.
+    // The helper class to receive and store the MmTel registration status updated.
     private ImsRegistrationCallbackHelper mImsMmTelRegistrationHelper;
-    private ImsRegistrationCallbackHelper mImsRcsRegistrationHelper;
 
     private boolean mRoaming = false;
 
+    private boolean mIsInImsEcm = false;
+
     // List of Registrants to send supplementary service notifications to.
     private RegistrantList mSsnRegistrants = new RegistrantList();
 
@@ -335,7 +324,8 @@
 
         mMetrics = TelephonyMetrics.getInstance();
 
-        initImsRegistration();
+        mImsMmTelRegistrationHelper = new ImsRegistrationCallbackHelper(mMmTelRegistrationUpdate,
+                context.getMainExecutor());
 
         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
@@ -357,10 +347,6 @@
         mDefaultPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
         // Force initial roaming state update later, on EVENT_CARRIER_CONFIG_CHANGED.
         // Settings provider or CarrierConfig may not be loaded now.
-
-        // Listen to the carrier config changed to initialize RcsFeatureManager
-        IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
-        mContext.registerReceiver(mCarrierConfigChangedReceiver, filter);
     }
 
     //todo: get rid of this function. It is not needed since parentPhone obj never changes
@@ -383,106 +369,6 @@
             }
             mDefaultPhone.unregisterForServiceStateChanged(this);
         }
-
-        mContext.unregisterReceiver(mCarrierConfigChangedReceiver);
-
-        if (mRcsManagerConnector != null) {
-            mRcsManagerConnector.disconnect();
-            mRcsManagerConnector = null;
-        }
-
-        if (mRcsManager != null) {
-            mRcsManager.release();
-            mRcsManager = null;
-        }
-    }
-
-    private BroadcastReceiver mCarrierConfigChangedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent == null) {
-                return;
-            }
-            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
-                Bundle bundle = intent.getExtras();
-                if (bundle == null) {
-                    return;
-                }
-                int phoneId = bundle.getInt(CarrierConfigManager.EXTRA_SLOT_INDEX);
-                if (phoneId == mPhoneId) {
-                    sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
-                }
-            }
-        }
-    };
-
-    /**
-     * Create RcsManagerConnector to initialize RcsFeatureManager
-     */
-    @VisibleForTesting
-    public void initRcsFeatureManager() {
-        if (mRcsManagerConnector != null) {
-            mRcsManagerConnector.disconnect();
-            mRcsManagerConnector = null;
-        }
-
-        logd("initRcsFeatureManager");
-        mRcsFeatureConnectorListener = new FeatureConnector.Listener<>() {
-            @Override
-            public boolean isSupported() {
-                // Check if Telephony IMS is supported or not
-                if (!ImsManager.isImsSupportedOnDevice(mContext)) {
-                    return false;
-                }
-                return true;
-            }
-
-            @Override
-            public RcsFeatureManager getFeatureManager() {
-                logd("Create RcsFeatureManager instance");
-                return new RcsFeatureManager(mContext, mPhoneId);
-            }
-
-            @Override
-            public void connectionReady(RcsFeatureManager manager) throws ImsException {
-                logi("RcsFeatureManager is ready");
-                mRcsManager = manager;
-
-                // Listen to the IMS RCS registration status changed
-                mRcsManager.registerImsRegistrationCallback(
-                        mImsRcsRegistrationHelper.getCallbackBinder());
-
-                if (mRcsStatusListener != null) {
-                    mRcsStatusListener.onRcsConnected(getPhoneId(), mRcsManager);
-                }
-            }
-
-            @Override
-            public void connectionUnavailable() {
-                logi("RcsFeatureManager is unavailable");
-                resetImsRegistrationState(ImsFeature.FEATURE_RCS);
-                if (mRcsManager != null) {
-                    mRcsManager.release();
-                }
-                mRcsManager = null;
-
-                if (mRcsStatusListener != null) {
-                    mRcsStatusListener.onRcsDisconnected(getPhoneId());
-                }
-            }
-        };
-
-        mRcsManagerConnector = new FeatureConnector<>(mContext, mPhoneId,
-                mRcsFeatureConnectorListener, mContext.getMainExecutor(), LOG_TAG);
-        mRcsManagerConnector.connect();
-    }
-
-    public RcsFeatureManager getRcsManager() {
-        return mRcsManager;
-    }
-
-    public void setRcsStatusListener(ImsRcsStatusListener listener) {
-        mRcsStatusListener = listener;
     }
 
     @UnsupportedAppUsage
@@ -846,12 +732,18 @@
     }
 
     @Override
+    public boolean isInImsEcm() {
+        return mIsInImsEcm;
+    }
+
+    @Override
     public boolean isInEcm() {
         return mDefaultPhone.isInEcm();
     }
 
     @Override
     public void setIsInEcm(boolean isInEcm){
+        mIsInImsEcm = isInEcm;
         mDefaultPhone.setIsInEcm(isInEcm);
     }
 
@@ -1130,6 +1022,13 @@
     @Override
     public void getCallForwardingOption(int commandInterfaceCFReason,
             Message onComplete) {
+        getCallForwardingOption(commandInterfaceCFReason,
+                SERVICE_CLASS_VOICE, onComplete);
+    }
+
+    @Override
+    public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
+            Message onComplete) {
         if (DBG) logd("getCallForwardingOption reason=" + commandInterfaceCFReason);
         if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
             if (DBG) logd("requesting call forwarding query.");
@@ -1158,6 +1057,7 @@
     }
 
     @UnsupportedAppUsage
+    @Override
     public void setCallForwardingOption(int commandInterfaceCFAction,
             int commandInterfaceCFReason,
             String dialingNumber,
@@ -1259,7 +1159,7 @@
     }
 
     public void getCallBarring(String facility, Message onComplete) {
-        getCallBarring(facility, onComplete, CommandsInterface.SERVICE_CLASS_NONE);
+        getCallBarring(facility, onComplete, CommandsInterface.SERVICE_CLASS_VOICE);
     }
 
     public void getCallBarring(String facility, Message onComplete, int serviceClass) {
@@ -1285,7 +1185,7 @@
     public void setCallBarring(String facility, boolean lockState, String password,
             Message onComplete) {
         setCallBarring(facility, lockState, password, onComplete,
-                CommandsInterface.SERVICE_CLASS_NONE);
+                CommandsInterface.SERVICE_CLASS_VOICE);
     }
 
     @Override
@@ -1561,20 +1461,15 @@
             cfInfos = new CallForwardInfo[infos.length];
         }
 
-        IccRecords r = mDefaultPhone.getIccRecords();
         if (infos == null || infos.length == 0) {
-            if (r != null) {
-                // Assume the default is not active
-                // Set unconditional CFF in SIM to false
-                setVoiceCallForwardingFlag(r, 1, false, null);
-            }
+            // Assume the default is not active
+            // Set unconditional CFF in SIM to false
+            setVoiceCallForwardingFlag(getIccRecords(), 1, false, null);
         } else {
             for (int i = 0, s = infos.length; i < s; i++) {
                 if (infos[i].getCondition() == ImsUtInterface.CDIV_CF_UNCONDITIONAL) {
-                    if (r != null) {
-                        setVoiceCallForwardingFlag(r, 1, (infos[i].getStatus() == 1),
-                                infos[i].getNumber());
-                    }
+                    setVoiceCallForwardingFlag(getIccRecords(), 1, (infos[i].getStatus() == 1),
+                        infos[i].getNumber());
                 }
                 cfInfos[i] = getCallForwardInfo(infos[i]);
             }
@@ -1641,10 +1536,9 @@
         if (DBG) logd("handleMessage what=" + msg.what);
         switch (msg.what) {
             case EVENT_SET_CALL_FORWARD_DONE:
-                IccRecords r = mDefaultPhone.getIccRecords();
                 Cf cf = (Cf) ar.userObj;
-                if (cf.mIsCfu && ar.exception == null && r != null) {
-                    setVoiceCallForwardingFlag(r, 1, msg.arg1 == 1, cf.mSetCfNumber);
+                if (cf.mIsCfu && ar.exception == null) {
+                    setVoiceCallForwardingFlag(getIccRecords(), 1, msg.arg1 == 1, cf.mSetCfNumber);
                 }
                 sendResponse(cf.mOnComplete, null, ar.exception);
                 break;
@@ -1712,14 +1606,6 @@
                     updateRoamingState(sst.mSS);
                 }
                 break;
-            case EVENT_CARRIER_CONFIG_CHANGED:
-                if (DBG) logd("EVENT_CARRIER_CONFIG_CHANGED");
-                if (mRcsManager == null) {
-                    initRcsFeatureManager();
-                } else {
-                    mRcsManager.updateCapabilities();
-                }
-                break;
 
             default:
                 super.handleMessage(msg);
@@ -1895,25 +1781,11 @@
         mCT.getImsRegistrationTech(callback);
     }
 
-    /**
-     * Get the IMS RCS registration technology for this Phone.
-     */
-    public void getImsRcsRegistrationTech(Consumer<Integer> callback) {
-        mRcsManager.getImsRegistrationTech(callback);
-    }
-
     @Override
     public void getImsRegistrationState(Consumer<Integer> callback) {
         callback.accept(mImsMmTelRegistrationHelper.getImsRegistrationState());
     }
 
-    /**
-     * Retrieve the current RCS registration state.
-     */
-    public void getImsRcsRegistrationState(Consumer<Integer> callback) {
-        callback.accept(mImsRcsRegistrationHelper.getImsRegistrationState());
-    }
-
     @Override
     public Phone getDefaultPhone() {
         return mDefaultPhone;
@@ -2122,11 +1994,6 @@
         return mWakeLock;
     }
 
-    @Override
-    public NetworkStats getVtDataUsage(boolean perUidStats) {
-        return mCT.getVtDataUsage(perUidStats);
-    }
-
     /**
      * Update roaming state and WFC mode in the following situations:
      *     1) voice is in service.
@@ -2202,18 +2069,9 @@
     /**
      * Reset the IMS registration state.
      */
-    public void resetImsRegistrationState(int featureType) {
-        if (DBG) logd("resetImsRegistrationState: feature=" + featureType);
-        if (featureType == ImsFeature.FEATURE_MMTEL) {
-            mImsMmTelRegistrationHelper.reset();
-        } else if (featureType == ImsFeature.FEATURE_RCS) {
-            mImsRcsRegistrationHelper.reset();
-        }
-    }
-
-    private void initImsRegistration() {
-        mImsMmTelRegistrationHelper = new ImsRegistrationCallbackHelper(mMmTelRegistrationUpdate);
-        mImsRcsRegistrationHelper = new ImsRegistrationCallbackHelper(mRcsRegistrationUpdate);
+    public void resetImsRegistrationState() {
+        if (DBG) logd("resetImsRegistrationState");
+        mImsMmTelRegistrationHelper.reset();
     }
 
     private ImsRegistrationCallbackHelper.ImsRegistrationUpdate mMmTelRegistrationUpdate = new
@@ -2260,28 +2118,9 @@
         }
     };
 
-    private ImsRegistrationCallbackHelper.ImsRegistrationUpdate mRcsRegistrationUpdate = new
-            ImsRegistrationCallbackHelper.ImsRegistrationUpdate() {
-        @Override
-        public void handleImsRegistered(int imsRadioTech) {
-            if (DBG) logd("handle RCS registered");
-        }
-
-        @Override
-        public void handleImsRegistering(int imsRadioTech) {
-            if (DBG) logd("handle RCS registering");
-        }
-
-        @Override
-        public void handleImsUnregistered(ImsReasonInfo imsReasonInfo) {
-            if (DBG) logd("handle RCS unregistered");
-        }
-
-        @Override
-        public void handleImsSubscriberAssociatedUriChanged(Uri[] uris) {
-            if (DBG) logd("handle RCS SubscriberAssociatedUriChanged");
-        }
-    };
+    public IccRecords getIccRecords() {
+        return mDefaultPhone.getIccRecords();
+    }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
@@ -2301,8 +2140,6 @@
         pw.println("  mSilentRedialRegistrants = " + mSilentRedialRegistrants);
         pw.println("  mImsMmTelRegistrationState = "
                 + mImsMmTelRegistrationHelper.getImsRegistrationState());
-        pw.println("  mImsRcsRegistrationState = "
-                + mImsRcsRegistrationHelper.getImsRegistrationState());
         pw.println("  mRoaming = " + mRoaming);
         pw.println("  mSsnRegistrants = " + mSsnRegistrants);
         pw.println(" Registration Log:");
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
index d2da8d0..5b1d2e5 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
@@ -25,7 +25,6 @@
 import android.sysprop.TelephonyProperties;
 import android.telephony.CallQuality;
 import android.telephony.NetworkScanRequest;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.ims.ImsReasonInfo;
@@ -43,6 +42,7 @@
 import com.android.internal.telephony.PhoneNotifier;
 import com.android.internal.telephony.dataconnection.DataConnection;
 import com.android.internal.telephony.uicc.IccFileHandler;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -168,11 +168,6 @@
     }
 
     @Override
-    public boolean getCallForwardingIndicator() {
-        return false;
-    }
-
-    @Override
     public List<? extends MmiCode> getPendingMmiCodes() {
         return new ArrayList<MmiCode>(0);
     }
@@ -370,12 +365,23 @@
     }
 
     @Override
+    public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
+            Message onComplete) {
+    }
+
+    @Override
     public void setCallForwardingOption(int commandInterfaceCFAction,
             int commandInterfaceCFReason, String dialingNumber,
             int timerSeconds, Message onComplete) {
     }
 
     @Override
+    public void setCallForwardingOption(int commandInterfaceCFAction,
+            int commandInterfaceCFReason, String dialingNumber, int serviceClass,
+            int timerSeconds, Message onComplete) {
+    }
+
+    @Override
     public void getOutgoingCallerIdDisplay(Message onComplete) {
         // FIXME: what to reply?
         AsyncResult.forMessage(onComplete, null, null);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCall.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCall.java
index 1a72b7e..c9e5096 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCall.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCall.java
@@ -18,7 +18,6 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.telephony.DisconnectCause;
-import android.telephony.Rlog;
 import android.telephony.ims.ImsStreamMediaProfile;
 import android.util.Log;
 
@@ -30,6 +29,7 @@
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
old mode 100644
new mode 100755
index 20935ea..f400276
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -16,9 +16,11 @@
 
 package com.android.internal.telephony.imsphone;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
 import static com.android.internal.telephony.Phone.CS_FALLBACK;
 
 import android.annotation.NonNull;
+import android.app.usage.NetworkStatsManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -32,6 +34,8 @@
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkStats;
+import android.net.netstats.provider.AbstractNetworkStatsProvider;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
 import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
@@ -44,13 +48,13 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.sysprop.TelephonyProperties;
+import android.telecom.Connection.VideoProvider;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.CallQuality;
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -70,6 +74,7 @@
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Pair;
+import android.util.SparseIntArray;
 
 import com.android.ims.FeatureConnector;
 import com.android.ims.ImsCall;
@@ -88,6 +93,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallFailCause;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.CallTracker;
 import com.android.internal.telephony.CommandException;
@@ -109,6 +115,7 @@
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.ImsCommand;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.net.NetworkStatsService;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -253,6 +260,48 @@
         }
     }
 
+    /**
+     * A class implementing {@link AbstractNetworkStatsProvider} to report VT data usage to system.
+     */
+    // TODO: Directly reports diff in updateVtDataUsage.
+    @VisibleForTesting(visibility = PRIVATE)
+    public class VtDataUsageProvider extends AbstractNetworkStatsProvider {
+        private int mToken = 0;
+        private NetworkStats mIfaceSnapshot = new NetworkStats(0L, 0);
+        private NetworkStats mUidSnapshot = new NetworkStats(0L, 0);
+        @Override
+        public void requestStatsUpdate(int token) {
+            // If there is an ongoing VT call, request the latest VT usage from the modem. The
+            // latest usage will return asynchronously so it won't be counted in this round, but it
+            // will be eventually counted when next requestStatsUpdate is called.
+            if (mState != PhoneConstants.State.IDLE) {
+                for (ImsPhoneConnection conn : mConnections) {
+                    final VideoProvider videoProvider = conn.getVideoProvider();
+                    if (videoProvider != null) {
+                        videoProvider.onRequestConnectionDataUsage();
+                    }
+                }
+            }
+
+            final NetworkStats ifaceDiff = mVtDataUsageSnapshot.subtract(mIfaceSnapshot);
+            final NetworkStats uidDiff = mVtDataUsageUidSnapshot.subtract(mUidSnapshot);
+            mVtDataUsageProviderCb.onStatsUpdated(mToken, ifaceDiff, uidDiff);
+            mIfaceSnapshot = mIfaceSnapshot.add(ifaceDiff);
+            mUidSnapshot = mUidSnapshot.add(uidDiff);
+            mToken = token;
+        }
+
+        @Override
+        public void setLimit(String iface, long quotaBytes) {
+            // No-op
+        }
+
+        @Override
+        public void setAlert(long quotaBytes) {
+            // No-op
+        }
+    }
+
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -388,6 +437,7 @@
 
     private volatile NetworkStats mVtDataUsageSnapshot = null;
     private volatile NetworkStats mVtDataUsageUidSnapshot = null;
+    private final NetworkStatsProviderCallback mVtDataUsageProviderCb;
 
     private final AtomicInteger mDefaultDialerUid = new AtomicInteger(NetworkStats.UID_ALL);
 
@@ -420,6 +470,7 @@
 
     private boolean mIsInEmergencyCall = false;
     private boolean mIsDataEnabled = false;
+    private boolean mIsEcmTimerCanceled = false;
 
     private int pendingCallClirMode;
     private int mPendingCallVideoState;
@@ -485,6 +536,237 @@
     private boolean mSupportDowngradeVtToAudio = false;
 
     /**
+     * Stores the mapping of {@code ImsReasonInfo#CODE_*} to {@code CallFailCause#*}
+     */
+    private static final SparseIntArray PRECISE_CAUSE_MAP = new SparseIntArray();
+    static {
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT,
+                CallFailCause.LOCAL_ILLEGAL_ARGUMENT);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE,
+                CallFailCause.LOCAL_ILLEGAL_STATE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR,
+                CallFailCause.LOCAL_INTERNAL_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN,
+                CallFailCause.LOCAL_IMS_SERVICE_DOWN);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL,
+                CallFailCause.LOCAL_NO_PENDING_CALL);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE,
+                CallFailCause.NORMAL_CLEARING);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_POWER_OFF,
+                CallFailCause.LOCAL_POWER_OFF);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_LOW_BATTERY,
+                CallFailCause.LOCAL_LOW_BATTERY);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE,
+                CallFailCause.LOCAL_NETWORK_NO_SERVICE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE,
+                CallFailCause.LOCAL_NETWORK_NO_LTE_COVERAGE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING,
+                CallFailCause.LOCAL_NETWORK_ROAMING);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED,
+                CallFailCause.LOCAL_NETWORK_IP_CHANGED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE,
+                CallFailCause.LOCAL_SERVICE_UNAVAILABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
+                CallFailCause.LOCAL_NOT_REGISTERED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_EXCEEDED,
+                CallFailCause.LOCAL_MAX_CALL_EXCEEDED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_DECLINE,
+                CallFailCause.LOCAL_CALL_DECLINE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING,
+                CallFailCause.LOCAL_CALL_VCC_ON_PROGRESSING);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED,
+                CallFailCause.LOCAL_CALL_RESOURCE_RESERVATION_FAILED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED,
+                CallFailCause.LOCAL_CALL_CS_RETRY_REQUIRED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED,
+                CallFailCause.LOCAL_CALL_VOLTE_RETRY_REQUIRED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED,
+                CallFailCause.LOCAL_CALL_TERMINATED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
+                CallFailCause.LOCAL_HO_NOT_FEASIBLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING,
+                CallFailCause.TIMEOUT_1XX_WAITING);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER,
+                CallFailCause.TIMEOUT_NO_ANSWER);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE,
+                CallFailCause.TIMEOUT_NO_ANSWER_CALL_UPDATE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_FDN_BLOCKED,
+                CallFailCause.FDN_BLOCKED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REDIRECTED,
+                CallFailCause.SIP_REDIRECTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BAD_REQUEST,
+                CallFailCause.SIP_BAD_REQUEST);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_FORBIDDEN,
+                CallFailCause.SIP_FORBIDDEN);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_FOUND,
+                CallFailCause.SIP_NOT_FOUND);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_SUPPORTED,
+                CallFailCause.SIP_NOT_SUPPORTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT,
+                CallFailCause.SIP_REQUEST_TIMEOUT);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_TEMPRARILY_UNAVAILABLE,
+                CallFailCause.SIP_TEMPRARILY_UNAVAILABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BAD_ADDRESS,
+                CallFailCause.SIP_BAD_ADDRESS);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BUSY,
+                CallFailCause.SIP_BUSY);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REQUEST_CANCELLED,
+                CallFailCause.SIP_REQUEST_CANCELLED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE,
+                CallFailCause.SIP_NOT_ACCEPTABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_REACHABLE,
+                CallFailCause.SIP_NOT_REACHABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_CLIENT_ERROR,
+                CallFailCause.SIP_CLIENT_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_TRANSACTION_DOES_NOT_EXIST,
+                CallFailCause.SIP_TRANSACTION_DOES_NOT_EXIST);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_INTERNAL_ERROR,
+                CallFailCause.SIP_SERVER_INTERNAL_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE,
+                CallFailCause.SIP_SERVICE_UNAVAILABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_TIMEOUT,
+                CallFailCause.SIP_SERVER_TIMEOUT);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_ERROR,
+                CallFailCause.SIP_SERVER_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_USER_REJECTED,
+                CallFailCause.SIP_USER_REJECTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_GLOBAL_ERROR,
+                CallFailCause.SIP_GLOBAL_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE,
+                CallFailCause.IMS_EMERGENCY_TEMP_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE,
+                CallFailCause.IMS_EMERGENCY_PERM_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_INIT_FAILED,
+                CallFailCause.MEDIA_INIT_FAILED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_NO_DATA,
+                CallFailCause.MEDIA_NO_DATA);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_NOT_ACCEPTABLE,
+                CallFailCause.MEDIA_NOT_ACCEPTABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_UNSPECIFIED,
+                CallFailCause.MEDIA_UNSPECIFIED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_TERMINATED,
+                CallFailCause.USER_TERMINATED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_NOANSWER,
+                CallFailCause.USER_NOANSWER);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_IGNORE,
+                CallFailCause.USER_IGNORE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_DECLINE,
+                CallFailCause.USER_DECLINE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOW_BATTERY,
+                CallFailCause.LOW_BATTERY);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_BLACKLISTED_CALL_ID,
+                CallFailCause.BLACKLISTED_CALL_ID);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE,
+                CallFailCause.USER_TERMINATED_BY_REMOTE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_NOT_SUPPORTED,
+                CallFailCause.UT_NOT_SUPPORTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE,
+                CallFailCause.UT_SERVICE_UNAVAILABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_OPERATION_NOT_ALLOWED,
+                CallFailCause.UT_OPERATION_NOT_ALLOWED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_NETWORK_ERROR,
+                CallFailCause.UT_NETWORK_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_CB_PASSWORD_MISMATCH,
+                CallFailCause.UT_CB_PASSWORD_MISMATCH);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED,
+                CallFailCause.ECBM_NOT_SUPPORTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED,
+                CallFailCause.MULTIENDPOINT_NOT_SUPPORTED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE,
+                CallFailCause.CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ANSWERED_ELSEWHERE,
+                CallFailCause.ANSWERED_ELSEWHERE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_PULL_OUT_OF_SYNC,
+                CallFailCause.CALL_PULL_OUT_OF_SYNC);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_END_CAUSE_CALL_PULL,
+                CallFailCause.CALL_PULLED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_FAILED,
+                CallFailCause.SUPP_SVC_FAILED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_CANCELLED,
+                CallFailCause.SUPP_SVC_CANCELLED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_REINVITE_COLLISION,
+                CallFailCause.SUPP_SVC_REINVITE_COLLISION);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_IWLAN_DPD_FAILURE,
+                CallFailCause.IWLAN_DPD_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_ESTABLISH_FAILURE,
+                CallFailCause.EPDG_TUNNEL_ESTABLISH_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_REKEY_FAILURE,
+                CallFailCause.EPDG_TUNNEL_REKEY_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_LOST_CONNECTION,
+                CallFailCause.EPDG_TUNNEL_LOST_CONNECTION);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED,
+                CallFailCause.MAXIMUM_NUMBER_OF_CALLS_REACHED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE,
+                CallFailCause.REMOTE_CALL_DECLINE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_DATA_LIMIT_REACHED,
+                CallFailCause.DATA_LIMIT_REACHED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_DATA_DISABLED,
+                CallFailCause.DATA_DISABLED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_WIFI_LOST,
+                CallFailCause.WIFI_LOST);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_OFF,
+                CallFailCause.RADIO_OFF);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NO_VALID_SIM,
+                CallFailCause.NO_VALID_SIM);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_INTERNAL_ERROR,
+                CallFailCause.RADIO_INTERNAL_ERROR);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_RESP_TIMEOUT,
+                CallFailCause.NETWORK_RESP_TIMEOUT);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_REJECT,
+                CallFailCause.NETWORK_REJECT);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_ACCESS_FAILURE,
+                CallFailCause.RADIO_ACCESS_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_LINK_FAILURE,
+                CallFailCause.RADIO_LINK_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_LINK_LOST,
+                CallFailCause.RADIO_LINK_LOST);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_UPLINK_FAILURE,
+                CallFailCause.RADIO_UPLINK_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_SETUP_FAILURE,
+                CallFailCause.RADIO_SETUP_FAILURE);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_RELEASE_NORMAL,
+                CallFailCause.RADIO_RELEASE_NORMAL);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_RELEASE_ABNORMAL,
+                CallFailCause.RADIO_RELEASE_ABNORMAL);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ACCESS_CLASS_BLOCKED,
+                CallFailCause.ACCESS_CLASS_BLOCKED);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_DETACH,
+                CallFailCause.NETWORK_DETACH);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UNOBTAINABLE_NUMBER,
+                CallFailCause.UNOBTAINABLE_NUMBER);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_1,
+                CallFailCause.OEM_CAUSE_1);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_2,
+                CallFailCause.OEM_CAUSE_2);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_3,
+                CallFailCause.OEM_CAUSE_3);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_4,
+                CallFailCause.OEM_CAUSE_4);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_5,
+                CallFailCause.OEM_CAUSE_5);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_6,
+                CallFailCause.OEM_CAUSE_6);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_7,
+                CallFailCause.OEM_CAUSE_7);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_8,
+                CallFailCause.OEM_CAUSE_8);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_9,
+                CallFailCause.OEM_CAUSE_9);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_10,
+                CallFailCause.OEM_CAUSE_10);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_11,
+                CallFailCause.OEM_CAUSE_11);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_12,
+                CallFailCause.OEM_CAUSE_12);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_13,
+                CallFailCause.OEM_CAUSE_13);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_14,
+                CallFailCause.OEM_CAUSE_14);
+        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_15,
+                CallFailCause.OEM_CAUSE_15);
+    }
+
+    /**
      * Carrier configuration option which determines whether the carrier wants to inform the user
      * when a video call is handed over from WIFI to LTE.
      * See {@link CarrierConfigManager#KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL} for more
@@ -589,17 +871,17 @@
         long currentTime = SystemClock.elapsedRealtime();
         mVtDataUsageSnapshot = new NetworkStats(currentTime, 1);
         mVtDataUsageUidSnapshot = new NetworkStats(currentTime, 1);
+        final NetworkStatsManager statsManager =
+                (NetworkStatsManager) mPhone.getContext().getSystemService(
+                        Context.NETWORK_STATS_SERVICE);
+        mVtDataUsageProviderCb = statsManager.registerNetworkStatsProvider(LOG_TAG,
+                new VtDataUsageProvider());
 
         // Allow the executor to be specified for testing.
-        mImsManagerConnector = new FeatureConnector<ImsManager>(
+        mImsManagerConnector = new FeatureConnector<>(
                 phone.getContext(), phone.getPhoneId(),
                 new FeatureConnector.Listener<ImsManager>() {
                     @Override
-                    public boolean isSupported() {
-                        return ImsManager.isImsSupportedOnDevice(phone.getContext());
-                    }
-
-                    @Override
                     public ImsManager getFeatureManager() {
                         return ImsManager.getInstance(phone.getContext(), phone.getPhoneId());
                     }
@@ -743,6 +1025,10 @@
         mPhone.getContext().unregisterReceiver(mReceiver);
         mPhone.getDefaultPhone().getDataEnabledSettings().unregisterForDataEnabledChanged(this);
         mImsManagerConnector.disconnect();
+
+        if (mVtDataUsageProviderCb != null) {
+            mVtDataUsageProviderCb.unregister();
+        }
     }
 
     @Override
@@ -848,28 +1134,33 @@
         boolean holdBeforeDial = prepareForDialing(dialArgs);
 
         mClirMode = clirMode;
-
+        ImsPhoneConnection pendingConnection;
         synchronized (mSyncHold) {
             mLastDialArgs = dialArgs;
-            mPendingMO = new ImsPhoneConnection(mPhone,
+            pendingConnection = new ImsPhoneConnection(mPhone,
                     participantsToDial, this, mForegroundCall,
                     false);
-            mPendingMO.setVideoState(videoState);
+            // Don't rely on the mPendingMO in this method; if the modem calls back through
+            // onCallProgressing, we'll end up nulling out mPendingMO, which means that
+            // TelephonyConnectionService would treat this call as an MMI code, which it is not,
+            // which would mean that the MMI code dialog would crash.
+            mPendingMO = pendingConnection;
+            pendingConnection.setVideoState(videoState);
             if (dialArgs.rttTextStream != null) {
                 log("startConference: setting RTT stream on mPendingMO");
-                mPendingMO.setCurrentRttTextStream(dialArgs.rttTextStream);
+                pendingConnection.setCurrentRttTextStream(dialArgs.rttTextStream);
             }
         }
-        addConnection(mPendingMO);
+        addConnection(pendingConnection);
 
         if (!holdBeforeDial) {
-            dialInternal(mPendingMO, clirMode, videoState, dialArgs.intentExtras);
+            dialInternal(pendingConnection, clirMode, videoState, dialArgs.intentExtras);
         }
 
         updatePhoneState();
         mPhone.notifyPreciseCallStateChanged();
 
-        return mPendingMO;
+        return pendingConnection;
     }
 
     @UnsupportedAppUsage
@@ -1061,7 +1352,7 @@
                         CarrierConfigManager.KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL);
         mAllowHoldingVideoCall =
                 carrierConfig.getBoolean(
-                        CarrierConfigManager.KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL);
+                        CarrierConfigManager.KEY_ALLOW_HOLD_VIDEO_CALL_BOOL);
         mNotifyVtHandoverToWifiFail = carrierConfig.getBoolean(
                 CarrierConfigManager.KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL);
         mSupportDowngradeVtToAudio = carrierConfig.getBoolean(
@@ -1121,8 +1412,10 @@
         mPhone.handleTimerInEmergencyCallbackMode(action);
         switch (action) {
             case ImsPhone.CANCEL_ECM_TIMER:
+                mIsEcmTimerCanceled = true;
                 break;
             case ImsPhone.RESTART_ECM_TIMER:
+                mIsEcmTimerCanceled = false;
                 break;
             default:
                 log("handleEcmTimer, unsupported action " + action);
@@ -2007,6 +2300,9 @@
             }
 
             if (!isEmergencyCallInList) {
+                if (mIsEcmTimerCanceled) {
+                    handleEcmTimer(ImsPhone.RESTART_ECM_TIMER);
+                }
                 mIsInEmergencyCall = false;
                 mPhone.sendEmergencyCallStateChange(false);
             }
@@ -2322,6 +2618,11 @@
         return cause;
     }
 
+    private int getPreciseDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
+        return PRECISE_CAUSE_MAP.get(maybeRemapReasonCode(reasonInfo),
+                CallFailCause.ERROR_UNSPECIFIED);
+    }
+
     /**
      * @return true if the phone is in Emergency Callback mode, otherwise false
      */
@@ -2534,6 +2835,10 @@
             pruneCallQualityMetricsHistory();
             mPhone.notifyImsReason(reasonInfo);
 
+            if (conn != null) {
+                conn.setPreciseDisconnectCause(getPreciseDisconnectCauseFromReasonInfo(reasonInfo));
+            }
+
             if (reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL
                     && mAutoRetryFailedWifiEmergencyCall) {
                 Pair<ImsCall, ImsReasonInfo> callInfo = new Pair<>(imsCall, reasonInfo);
@@ -2934,10 +3239,16 @@
 
             // Start plumbing this even through Telecom so other components can take
             // appropriate action.
-            ImsPhoneConnection conn = findConnection(call);
-            if (conn != null) {
-                conn.onConferenceMergeFailed();
-                conn.handleMergeComplete();
+            ImsPhoneConnection foregroundConnection = mForegroundCall.getFirstConnection();
+            if (foregroundConnection != null) {
+                foregroundConnection.onConferenceMergeFailed();
+                foregroundConnection.handleMergeComplete();
+            }
+
+            ImsPhoneConnection backgroundConnection = mBackgroundCall.getFirstConnection();
+            if (backgroundConnection != null) {
+                backgroundConnection.onConferenceMergeFailed();
+                backgroundConnection.handleMergeComplete();
             }
         }
 
@@ -3151,6 +3462,16 @@
             }
         }
 
+        @Override
+        public void onCallSessionTransferred(ImsCall imsCall) {
+            if (DBG) log("onCallSessionTransferred success");
+        }
+
+        @Override
+        public void onCallSessionTransferFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
+            if (DBG) log("onCallSessionTransferFailed reasonInfo=" + reasonInfo);
+        }
+
         /**
          * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
          * {@link ImsPhoneConnection} of the change.
@@ -3336,6 +3657,12 @@
         }
 
         processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
+
+        if (conn != null) {
+            conn.setPreciseDisconnectCause(
+                    getPreciseDisconnectCauseFromReasonInfo(reasonInfo));
+        }
+
         mPhone.notifyImsReason(reasonInfo);
     }
 
@@ -3400,6 +3727,7 @@
 
     private void resetState() {
         mIsInEmergencyCall = false;
+        mIsEcmTimerCanceled = false;
     }
 
     //****** Overridden from Handler
@@ -3604,7 +3932,8 @@
      * @param call The IMS call
      * @param dataUsage The aggregated data usage for the call
      */
-    private void updateVtDataUsage(ImsCall call, long dataUsage) {
+    @VisibleForTesting(visibility = PRIVATE)
+    public void updateVtDataUsage(ImsCall call, long dataUsage) {
         long oldUsage = 0L;
         if (mVtDataUsageMap.containsKey(call.uniqueId)) {
             oldUsage = mVtDataUsageMap.get(call.uniqueId);
@@ -3752,6 +4081,7 @@
         pw.increaseIndent();
         mOperationLocalLog.dump(pw);
         pw.decreaseIndent();
+        pw.println(" mIsEcmTimerCanceled=" + mIsEcmTimerCanceled);
 
         pw.flush();
         pw.println("++++++++++++++++++++++++++++++++");
@@ -4024,29 +4354,6 @@
         return isActiveCallVideo && isActiveCallOnWifi && isIncomingCallAudio && !isVoWifiEnabled;
     }
 
-    /**
-     * Get aggregated video call data usage since boot.
-     *
-     * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
-     * @return Snapshot of video call data usage
-     */
-    public NetworkStats getVtDataUsage(boolean perUidStats) {
-
-        // If there is an ongoing VT call, request the latest VT usage from the modem. The latest
-        // usage will return asynchronously so it won't be counted in this round, but it will be
-        // eventually counted when next getVtDataUsage is called.
-        if (mState != PhoneConstants.State.IDLE) {
-            for (ImsPhoneConnection conn : mConnections) {
-                android.telecom.Connection.VideoProvider videoProvider = conn.getVideoProvider();
-                if (videoProvider != null) {
-                    videoProvider.onRequestConnectionDataUsage();
-                }
-            }
-        }
-
-        return perUidStats ? mVtDataUsageUidSnapshot : mVtDataUsageSnapshot;
-    }
-
     public void registerPhoneStateListener(PhoneStateListener listener) {
         mPhoneStateListeners.add(listener);
     }
@@ -4248,7 +4555,7 @@
         boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
         mMmTelCapabilities = new MmTelFeature.MmTelCapabilities();
         mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
-        mPhone.resetImsRegistrationState(ImsFeature.FEATURE_MMTEL);
+        mPhone.resetImsRegistrationState();
         mPhone.processDisconnectReason(new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN,
                 ImsReasonInfo.CODE_UNSPECIFIED));
         boolean isVideoEnabled = isVideoCallEnabled();
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
old mode 100644
new mode 100755
index 32f4b4d..5794c9b
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -33,7 +33,6 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
@@ -50,6 +49,7 @@
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.telephony.Rlog;
 
 import java.util.Objects;
 
@@ -414,6 +414,32 @@
     }
 
     @Override
+    public void transfer(String number, boolean isConfirmationRequired) throws CallStateException {
+        try {
+            if (mImsCall != null) {
+                mImsCall.transfer(number, isConfirmationRequired);
+            } else {
+                throw new CallStateException("no valid ims call to transfer");
+            }
+        } catch (ImsException e) {
+            throw new CallStateException("cannot transfer call");
+        }
+    }
+
+    @Override
+    public void consultativeTransfer(Connection other) throws CallStateException {
+        try {
+            if (mImsCall != null) {
+                mImsCall.consultativeTransfer(((ImsPhoneConnection) other).getImsCall());
+            } else {
+                throw new CallStateException("no valid ims call to transfer");
+            }
+        } catch (ImsException e) {
+            throw new CallStateException("cannot transfer call");
+        }
+    }
+
+    @Override
     public void hangup() throws CallStateException {
         if (!mDisconnected) {
             mOwner.hangup(this);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneFactory.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneFactory.java
index 9f81a69..8f82328 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneFactory.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneFactory.java
@@ -16,11 +16,11 @@
 
 package com.android.internal.telephony.imsphone;
 
+import android.content.Context;
+
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneNotifier;
-
-import android.content.Context;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 6d077c2..72f9df7 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -35,7 +35,6 @@
 import android.os.Message;
 import android.os.ResultReceiver;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ims.ImsCallForwardInfo;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ImsSsData;
@@ -53,6 +52,7 @@
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.uicc.IccRecords;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 import java.util.List;
@@ -818,7 +818,7 @@
                 int time = siToTime(mSic);
 
                 if (isInterrogate()) {
-                    mPhone.getCallForwardingOption(reason,
+                    mPhone.getCallForwardingOption(reason, serviceClass,
                             obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
                 } else {
                     int cfAction;
@@ -1415,9 +1415,7 @@
                 (info.serviceClass & serviceClassMask)
                         == CommandsInterface.SERVICE_CLASS_VOICE) {
             boolean cffEnabled = (info.status == 1);
-            if (mIccRecords != null) {
-                mPhone.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
-            }
+            mPhone.setVoiceCallForwardingFlag(mIccRecords, 1, cffEnabled, info.number);
         }
 
         return TextUtils.replace(template, sources, destinations);
@@ -1448,9 +1446,7 @@
                 sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
 
                 // Set unconditional CFF in SIM to false
-                if (mIccRecords != null) {
-                    mPhone.setVoiceCallForwardingFlag(1, false, null);
-                }
+                mPhone.setVoiceCallForwardingFlag(mIccRecords, 1, false, null);
             } else {
 
                 SpannableStringBuilder tb = new SpannableStringBuilder();
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelper.java b/src/java/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelper.java
index a1bee96..33c16e2 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelper.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelper.java
@@ -16,22 +16,20 @@
 
 package com.android.internal.telephony.imsphone;
 
+import android.annotation.AnyThread;
 import android.annotation.NonNull;
 import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.RegistrationManager;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.util.Log;
 
-import com.android.internal.telephony.util.HandlerExecutor;
-
 import java.util.concurrent.Executor;
 
 /**
  * A helper class to manager the ImsRegistrationCallback can notify the state changed to listener.
  */
+@AnyThread
 public class ImsRegistrationCallbackHelper {
     private static final String TAG = "ImsRegCallbackHelper";
 
@@ -63,6 +61,7 @@
 
     private ImsRegistrationUpdate mImsRegistrationUpdate;
     private int mRegistrationState = RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
+    private final Object mLock = new Object();
 
     private final RegistrationManager.RegistrationCallback mImsRegistrationCallback =
             new RegistrationManager.RegistrationCallback() {
@@ -90,8 +89,9 @@
                 }
             };
 
-    public ImsRegistrationCallbackHelper(@NonNull ImsRegistrationUpdate registrationUpdate) {
-        mImsRegistrationCallback.setExecutor(getThreadExecutor());
+    public ImsRegistrationCallbackHelper(@NonNull ImsRegistrationUpdate registrationUpdate,
+            Executor executor) {
+        mImsRegistrationCallback.setExecutor(executor);
         mImsRegistrationUpdate = registrationUpdate;
     }
 
@@ -108,17 +108,21 @@
      */
     public synchronized void updateRegistrationState(
             @RegistrationManager.ImsRegistrationState int newState) {
-        Log.d(TAG, "updateRegistrationState: registration state from " + mRegistrationState
-                + " to " + newState);
-        mRegistrationState = newState;
+        synchronized (mLock) {
+            Log.d(TAG, "updateRegistrationState: registration state from " + mRegistrationState
+                    + " to " + newState);
+            mRegistrationState = newState;
+        }
     }
 
     public int getImsRegistrationState() {
-        return mRegistrationState;
+        synchronized (mLock) {
+            return mRegistrationState;
+        }
     }
 
     public boolean isImsRegistered() {
-        return mRegistrationState == RegistrationManager.REGISTRATION_STATE_REGISTERED;
+        return getImsRegistrationState() == RegistrationManager.REGISTRATION_STATE_REGISTERED;
     }
 
     public RegistrationManager.RegistrationCallback getCallback() {
@@ -128,11 +132,4 @@
     public IImsRegistrationCallback getCallbackBinder() {
         return mImsRegistrationCallback.getBinder();
     }
-
-    private Executor getThreadExecutor() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        return new HandlerExecutor(new Handler(Looper.myLooper()));
-    }
 }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsRttTextHandler.java b/src/java/com/android/internal/telephony/imsphone/ImsRttTextHandler.java
index eff2499..3955ea7 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsRttTextHandler.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsRttTextHandler.java
@@ -20,9 +20,9 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telecom.Connection;
-import android.telephony.Rlog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.io.IOException;
 import java.nio.channels.ClosedByInterruptException;
diff --git a/src/java/com/android/internal/telephony/metrics/CallQualityMetrics.java b/src/java/com/android/internal/telephony/metrics/CallQualityMetrics.java
index 55ac225..cf98acb 100644
--- a/src/java/com/android/internal/telephony/metrics/CallQualityMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/CallQualityMetrics.java
@@ -21,7 +21,6 @@
 import android.telephony.CallQuality;
 import android.telephony.CellInfo;
 import android.telephony.CellSignalStrengthLte;
-import android.telephony.Rlog;
 import android.telephony.SignalStrength;
 import android.util.Pair;
 
@@ -29,6 +28,7 @@
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
index ae081a7..94457f0 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
@@ -44,7 +44,6 @@
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.CallQuality;
 import android.telephony.DisconnectCause;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -109,6 +108,7 @@
 import com.android.internal.telephony.protobuf.nano.MessageNano;
 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;
@@ -2079,6 +2079,9 @@
             cq.averageRelativeJitterMillis = callQuality.getAverageRelativeJitter();
             cq.maxRelativeJitterMillis = callQuality.getMaxRelativeJitter();
             cq.codecType = convertImsCodec(callQuality.getCodecType());
+            cq.rtpInactivityDetected = callQuality.isRtpInactivityDetected();
+            cq.rxSilenceDetected = callQuality.isIncomingSilenceDetected();
+            cq.txSilenceDetected = callQuality.isOutgoingSilenceDetected();
         }
         return cq;
     }
diff --git a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
index d2e5f55..b6b092c 100644
--- a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
@@ -18,11 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.content.Context;
 import android.os.TimestampedValue;
-import android.telephony.Rlog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.NitzData;
@@ -30,6 +29,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TimeZoneLookupHelper;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -83,15 +83,15 @@
     public interface TimeZoneSuggester {
 
         /**
-         * Generates a {@link PhoneTimeZoneSuggestion} given the information available. This method
-         * must always return a non-null {@link PhoneTimeZoneSuggestion} but that object does not
-         * have to contain a time zone if the available information is not sufficient to determine
-         * one. {@link PhoneTimeZoneSuggestion#getDebugInfo()} provides debugging / logging
-         * information explaining the choice.
+         * Generates a {@link TelephonyTimeZoneSuggestion} given the information available. This
+         * method must always return a non-null {@link TelephonyTimeZoneSuggestion} but that object
+         * does not have to contain a time zone if the available information is not sufficient to
+         * determine one. {@link TelephonyTimeZoneSuggestion#getDebugInfo()} provides debugging /
+         * logging information explaining the choice.
          */
         @NonNull
-        PhoneTimeZoneSuggestion getTimeZoneSuggestion(
-                int phoneId, @Nullable String countryIsoCode,
+        TelephonyTimeZoneSuggestion getTimeZoneSuggestion(
+                int slotIndex, @Nullable String countryIsoCode,
                 @Nullable TimestampedValue<NitzData> nitzSignal);
     }
 
@@ -99,10 +99,12 @@
     static final boolean DBG = true;
 
     // Miscellaneous dependencies and helpers not related to detection state.
-    private final int mPhoneId;
+    private final int mSlotIndex;
     /** Applied to NITZ signals during input filtering. */
     private final NitzSignalInputFilterPredicate mNitzSignalInputFilter;
-    /** Creates {@link PhoneTimeZoneSuggestion} for passing to the time zone detection service. */
+    /**
+     * Creates a {@link TelephonyTimeZoneSuggestion} for passing to the time zone detection service.
+     */
     private final TimeZoneSuggester mTimeZoneSuggester;
     /** A facade to the time / time zone detection services. */
     private final NewTimeServiceHelper mNewTimeServiceHelper;
@@ -132,7 +134,7 @@
     public static NewNitzStateMachineImpl createInstance(@NonNull Phone phone) {
         Objects.requireNonNull(phone);
 
-        int phoneId = phone.getPhoneId();
+        int slotIndex = phone.getPhoneId();
         DeviceState deviceState = new DeviceStateImpl(phone);
         TimeZoneLookupHelper timeZoneLookupHelper = new TimeZoneLookupHelper();
         TimeZoneSuggester timeZoneSuggester =
@@ -141,7 +143,7 @@
         NitzSignalInputFilterPredicate nitzSignalFilter =
                 NitzSignalInputFilterPredicateFactory.create(phone.getContext(), deviceState);
         return new NewNitzStateMachineImpl(
-                phoneId, nitzSignalFilter, timeZoneSuggester, newTimeServiceHelper);
+                slotIndex, nitzSignalFilter, timeZoneSuggester, newTimeServiceHelper);
     }
 
     /**
@@ -149,11 +151,11 @@
      * See {@link #createInstance(Phone)}
      */
     @VisibleForTesting
-    public NewNitzStateMachineImpl(int phoneId,
+    public NewNitzStateMachineImpl(int slotIndex,
             @NonNull NitzSignalInputFilterPredicate nitzSignalInputFilter,
             @NonNull TimeZoneSuggester timeZoneSuggester,
             @NonNull NewTimeServiceHelper newTimeServiceHelper) {
-        mPhoneId = phoneId;
+        mSlotIndex = slotIndex;
         mTimeZoneSuggester = Objects.requireNonNull(timeZoneSuggester);
         mNewTimeServiceHelper = Objects.requireNonNull(newTimeServiceHelper);
         mNitzSignalInputFilter = Objects.requireNonNull(nitzSignalInputFilter);
@@ -284,8 +286,8 @@
         try {
             Objects.requireNonNull(reason);
 
-            PhoneTimeZoneSuggestion suggestion =
-                    mTimeZoneSuggester.getTimeZoneSuggestion(mPhoneId, countryIsoCode, nitzSignal);
+            TelephonyTimeZoneSuggestion suggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    mSlotIndex, countryIsoCode, nitzSignal);
             suggestion.addDebugInfo("Detection reason=" + reason);
 
             if (DBG) {
@@ -296,7 +298,7 @@
             mNewTimeServiceHelper.maybeSuggestDeviceTimeZone(suggestion);
         } catch (RuntimeException ex) {
             Rlog.e(LOG_TAG, "doTimeZoneDetection: Exception thrown"
-                    + " mPhoneId=" + mPhoneId
+                    + " mSlotIndex=" + mSlotIndex
                     + ", countryIsoCode=" + countryIsoCode
                     + ", nitzSignal=" + nitzSignal
                     + ", reason=" + reason
@@ -312,7 +314,8 @@
         try {
             Objects.requireNonNull(reason);
 
-            PhoneTimeSuggestion.Builder builder = new PhoneTimeSuggestion.Builder(mPhoneId);
+            TelephonyTimeSuggestion.Builder builder =
+                    new TelephonyTimeSuggestion.Builder(mSlotIndex);
             if (nitzSignal == null) {
                 builder.addDebugInfo("Clearing time suggestion"
                         + " reason=" + reason);
@@ -328,7 +331,7 @@
             mNewTimeServiceHelper.suggestDeviceTime(builder.build());
         } catch (RuntimeException ex) {
             Rlog.e(LOG_TAG, "doTimeDetection: Exception thrown"
-                    + " mPhoneId=" + mPhoneId
+                    + " mSlotIndex=" + mSlotIndex
                     + ", nitzSignal=" + nitzSignal
                     + ", reason=" + reason
                     + ", ex=" + ex, ex);
diff --git a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
index bc3a726..8d827ee 100644
--- a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
+++ b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
@@ -17,9 +17,9 @@
 package com.android.internal.telephony.nitz;
 
 import android.annotation.NonNull;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.app.timedetector.TimeDetector;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -36,17 +36,18 @@
      *
      * @param suggestion the time
      */
-    void suggestDeviceTime(@NonNull PhoneTimeSuggestion suggestion);
+    void suggestDeviceTime(@NonNull TelephonyTimeSuggestion suggestion);
 
     /**
      * Suggests the time zone to the time zone detector.
      *
-     * <p>NOTE: The PhoneTimeZoneSuggestion cannot be null. The zoneId it contains can be null to
-     * indicate there is no active suggestion; this can be used to clear a previous suggestion.
+     * <p>NOTE: The {@link TelephonyTimeZoneSuggestion} cannot be null. The zoneId it contains can
+     * be null to indicate there is no active suggestion; this can be used to clear a previous
+     * suggestion.
      *
      * @param suggestion the time zone
      */
-    void maybeSuggestDeviceTimeZone(@NonNull PhoneTimeZoneSuggestion suggestion);
+    void maybeSuggestDeviceTimeZone(@NonNull TelephonyTimeZoneSuggestion suggestion);
 
     /**
      * Dumps any logs held to the supplied writer.
diff --git a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
index adbebc2..31e450d 100644
--- a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
@@ -18,9 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.app.timedetector.TimeDetector;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.app.timezonedetector.TimeZoneDetector;
 import android.content.Context;
 import android.os.TimestampedValue;
@@ -38,7 +38,7 @@
  */
 public final class NewTimeServiceHelperImpl implements NewTimeServiceHelper {
 
-    private final int mPhoneId;
+    private final int mSlotIndex;
     private final TimeDetector mTimeDetector;
     private final TimeZoneDetector mTimeZoneDetector;
 
@@ -51,10 +51,10 @@
      * been made.
      */
     @NonNull
-    private PhoneTimeZoneSuggestion mLastSuggestedTimeZone;
+    private TelephonyTimeZoneSuggestion mLastSuggestedTimeZone;
 
     public NewTimeServiceHelperImpl(@NonNull Phone phone) {
-        mPhoneId = phone.getPhoneId();
+        mSlotIndex = phone.getPhoneId();
         Context context = Objects.requireNonNull(phone.getContext());
         mTimeDetector = Objects.requireNonNull(context.getSystemService(TimeDetector.class));
         mTimeZoneDetector =
@@ -62,33 +62,33 @@
     }
 
     @Override
-    public void suggestDeviceTime(@NonNull PhoneTimeSuggestion phoneTimeSuggestion) {
-        mTimeLog.log("Sending time suggestion: " + phoneTimeSuggestion);
+    public void suggestDeviceTime(@NonNull TelephonyTimeSuggestion timeSuggestion) {
+        mTimeLog.log("Sending time suggestion: " + timeSuggestion);
 
-        Objects.requireNonNull(phoneTimeSuggestion);
+        Objects.requireNonNull(timeSuggestion);
 
-        if (phoneTimeSuggestion.getUtcTime() != null) {
-            TimestampedValue<Long> utcTime = phoneTimeSuggestion.getUtcTime();
-            TelephonyMetrics.getInstance().writeNITZEvent(mPhoneId, utcTime.getValue());
+        if (timeSuggestion.getUtcTime() != null) {
+            TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
+            TelephonyMetrics.getInstance().writeNITZEvent(mSlotIndex, utcTime.getValue());
         }
-        mTimeDetector.suggestPhoneTime(phoneTimeSuggestion);
+        mTimeDetector.suggestTelephonyTime(timeSuggestion);
     }
 
     @Override
-    public void maybeSuggestDeviceTimeZone(@NonNull PhoneTimeZoneSuggestion newSuggestion) {
+    public void maybeSuggestDeviceTimeZone(@NonNull TelephonyTimeZoneSuggestion newSuggestion) {
         Objects.requireNonNull(newSuggestion);
 
-        PhoneTimeZoneSuggestion oldSuggestion = mLastSuggestedTimeZone;
+        TelephonyTimeZoneSuggestion oldSuggestion = mLastSuggestedTimeZone;
         if (shouldSendNewTimeZoneSuggestion(oldSuggestion, newSuggestion)) {
             mTimeZoneLog.log("Suggesting time zone update: " + newSuggestion);
-            mTimeZoneDetector.suggestPhoneTimeZone(newSuggestion);
+            mTimeZoneDetector.suggestTelephonyTimeZone(newSuggestion);
             mLastSuggestedTimeZone = newSuggestion;
         }
     }
 
     private static boolean shouldSendNewTimeZoneSuggestion(
-            @Nullable PhoneTimeZoneSuggestion oldSuggestion,
-            @NonNull PhoneTimeZoneSuggestion newSuggestion) {
+            @Nullable TelephonyTimeZoneSuggestion oldSuggestion,
+            @NonNull TelephonyTimeZoneSuggestion newSuggestion) {
         if (oldSuggestion == null) {
             // No previous suggestion.
             return true;
diff --git a/src/java/com/android/internal/telephony/nitz/NitzSignalInputFilterPredicateFactory.java b/src/java/com/android/internal/telephony/nitz/NitzSignalInputFilterPredicateFactory.java
index 4f4e256..5c238b7 100644
--- a/src/java/com/android/internal/telephony/nitz/NitzSignalInputFilterPredicateFactory.java
+++ b/src/java/com/android/internal/telephony/nitz/NitzSignalInputFilterPredicateFactory.java
@@ -22,12 +22,12 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.os.TimestampedValue;
-import android.telephony.Rlog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.NitzData;
 import com.android.internal.telephony.NitzStateMachine.DeviceState;
 import com.android.internal.telephony.nitz.NewNitzStateMachineImpl.NitzSignalInputFilterPredicate;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 import java.util.Objects;
diff --git a/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java b/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
index 96adfe4..a01f09b 100644
--- a/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
@@ -16,13 +16,12 @@
 
 package com.android.internal.telephony.nitz;
 
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.createEmptySuggestion;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.createEmptySuggestion;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.os.TimestampedValue;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.timezone.CountryTimeZones.OffsetResult;
 
@@ -32,6 +31,7 @@
 import com.android.internal.telephony.TimeZoneLookupHelper;
 import com.android.internal.telephony.TimeZoneLookupHelper.CountryResult;
 import com.android.internal.telephony.nitz.NewNitzStateMachineImpl.TimeZoneSuggester;
+import com.android.telephony.Rlog;
 
 import java.util.Objects;
 
@@ -55,46 +55,46 @@
 
     @Override
     @NonNull
-    public PhoneTimeZoneSuggestion getTimeZoneSuggestion(int phoneId,
+    public TelephonyTimeZoneSuggestion getTimeZoneSuggestion(int slotIndex,
             @Nullable String countryIsoCode, @Nullable TimestampedValue<NitzData> nitzSignal) {
         try {
             // Check for overriding NITZ-based signals from Android running in an emulator.
-            PhoneTimeZoneSuggestion overridingSuggestion = null;
+            TelephonyTimeZoneSuggestion overridingSuggestion = null;
             if (nitzSignal != null) {
                 NitzData nitzData = nitzSignal.getValue();
                 if (nitzData.getEmulatorHostTimeZone() != null) {
-                    PhoneTimeZoneSuggestion.Builder builder =
-                            new PhoneTimeZoneSuggestion.Builder(phoneId)
+                    TelephonyTimeZoneSuggestion.Builder builder =
+                            new TelephonyTimeZoneSuggestion.Builder(slotIndex)
                             .setZoneId(nitzData.getEmulatorHostTimeZone().getID())
-                            .setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID)
-                            .setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
+                            .setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID)
+                            .setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
                             .addDebugInfo("Emulator time zone override: " + nitzData);
                     overridingSuggestion = builder.build();
                 }
             }
 
-            PhoneTimeZoneSuggestion suggestion;
+            TelephonyTimeZoneSuggestion suggestion;
             if (overridingSuggestion != null) {
                 suggestion = overridingSuggestion;
             } else if (countryIsoCode == null) {
                 if (nitzSignal == null) {
-                    suggestion = createEmptySuggestion(phoneId,
+                    suggestion = createEmptySuggestion(slotIndex,
                             "getTimeZoneSuggestion: nitzSignal=null, countryIsoCode=null");
                 } else {
                     // NITZ only - wait until we have a country.
-                    suggestion = createEmptySuggestion(phoneId, "getTimeZoneSuggestion:"
+                    suggestion = createEmptySuggestion(slotIndex, "getTimeZoneSuggestion:"
                             + " nitzSignal=" + nitzSignal + ", countryIsoCode=null");
                 }
             } else { // countryIsoCode != null
                 if (nitzSignal == null) {
                     if (countryIsoCode.isEmpty()) {
                         // This is assumed to be a test network with no NITZ data to go on.
-                        suggestion = createEmptySuggestion(phoneId,
+                        suggestion = createEmptySuggestion(slotIndex,
                                 "getTimeZoneSuggestion: nitzSignal=null, countryIsoCode=\"\"");
                     } else {
                         // Country only
                         suggestion = findTimeZoneFromNetworkCountryCode(
-                                phoneId, countryIsoCode, mDeviceState.currentTimeMillis());
+                                slotIndex, countryIsoCode, mDeviceState.currentTimeMillis());
                     }
                 } else { // nitzSignal != null
                     if (countryIsoCode.isEmpty()) {
@@ -103,11 +103,11 @@
                         // (eg, "001"). Obtain a TimeZone based only on the NITZ parameters: without
                         // a country it will be arbitrary, but it should at least have the correct
                         // offset.
-                        suggestion = findTimeZoneForTestNetwork(phoneId, nitzSignal);
+                        suggestion = findTimeZoneForTestNetwork(slotIndex, nitzSignal);
                     } else {
                         // We have both NITZ and Country code.
                         suggestion = findTimeZoneFromCountryAndNitz(
-                                phoneId, countryIsoCode, nitzSignal);
+                                slotIndex, countryIsoCode, nitzSignal);
                     }
                 }
             }
@@ -123,25 +123,25 @@
                     + " countryIsoCode=" + countryIsoCode
                     + ", nitzSignal=" + nitzSignal
                     + ", e=" + e.getMessage();
-            PhoneTimeZoneSuggestion errorSuggestion = createEmptySuggestion(phoneId, message);
+            TelephonyTimeZoneSuggestion errorSuggestion = createEmptySuggestion(slotIndex, message);
             Rlog.w(LOG_TAG, message, e);
             return errorSuggestion;
         }
     }
 
     /**
-     * Creates a {@link PhoneTimeZoneSuggestion} using only NITZ. This happens when the device
+     * Creates a {@link TelephonyTimeZoneSuggestion} using only NITZ. This happens when the device
      * is attached to a test cell with an unrecognized MCC. In these cases we try to return a
      * suggestion for an arbitrary time zone that matches the NITZ offset information.
      */
     @NonNull
-    private PhoneTimeZoneSuggestion findTimeZoneForTestNetwork(
-            int phoneId, @NonNull TimestampedValue<NitzData> nitzSignal) {
+    private TelephonyTimeZoneSuggestion findTimeZoneForTestNetwork(
+            int slotIndex, @NonNull TimestampedValue<NitzData> nitzSignal) {
         Objects.requireNonNull(nitzSignal);
         NitzData nitzData = Objects.requireNonNull(nitzSignal.getValue());
 
-        PhoneTimeZoneSuggestion.Builder suggestionBuilder =
-                new PhoneTimeZoneSuggestion.Builder(phoneId);
+        TelephonyTimeZoneSuggestion.Builder suggestionBuilder =
+                new TelephonyTimeZoneSuggestion.Builder(slotIndex);
         suggestionBuilder.addDebugInfo("findTimeZoneForTestNetwork: nitzSignal=" + nitzSignal);
         OffsetResult lookupResult =
                 mTimeZoneLookupHelper.lookupByNitz(nitzData);
@@ -150,10 +150,10 @@
         } else {
             suggestionBuilder.setZoneId(lookupResult.getTimeZone().getID());
             suggestionBuilder.setMatchType(
-                    PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY);
+                    TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY);
             int quality = lookupResult.isOnlyMatch()
-                    ? PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE
-                    : PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+                    ? TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE
+                    : TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
             suggestionBuilder.setQuality(quality);
             suggestionBuilder.addDebugInfo(
                     "findTimeZoneForTestNetwork: lookupResult=" + lookupResult);
@@ -162,17 +162,17 @@
     }
 
     /**
-     * Creates a {@link PhoneTimeZoneSuggestion} using network country code and NITZ.
+     * Creates a {@link TelephonyTimeZoneSuggestion} using network country code and NITZ.
      */
     @NonNull
-    private PhoneTimeZoneSuggestion findTimeZoneFromCountryAndNitz(
-            int phoneId, @NonNull String countryIsoCode,
+    private TelephonyTimeZoneSuggestion findTimeZoneFromCountryAndNitz(
+            int slotIndex, @NonNull String countryIsoCode,
             @NonNull TimestampedValue<NitzData> nitzSignal) {
         Objects.requireNonNull(countryIsoCode);
         Objects.requireNonNull(nitzSignal);
 
-        PhoneTimeZoneSuggestion.Builder suggestionBuilder =
-                new PhoneTimeZoneSuggestion.Builder(phoneId);
+        TelephonyTimeZoneSuggestion.Builder suggestionBuilder =
+                new TelephonyTimeZoneSuggestion.Builder(slotIndex);
         suggestionBuilder.addDebugInfo("findTimeZoneFromCountryAndNitz:"
                 + " countryIsoCode=" + countryIsoCode
                 + ", nitzSignal=" + nitzSignal);
@@ -189,10 +189,10 @@
         if (lookupResult != null) {
             suggestionBuilder.setZoneId(lookupResult.getTimeZone().getID());
             suggestionBuilder.setMatchType(
-                    PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET);
+                    TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET);
             int quality = lookupResult.isOnlyMatch()
-                    ? PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE
-                    : PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+                    ? TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE
+                    : TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
             suggestionBuilder.setQuality(quality);
             suggestionBuilder.addDebugInfo("findTimeZoneFromCountryAndNitz:"
                     + " lookupResult=" + lookupResult);
@@ -215,8 +215,9 @@
         if (countryResult.quality == CountryResult.QUALITY_SINGLE_ZONE
                 || countryResult.quality == CountryResult.QUALITY_DEFAULT_BOOSTED) {
             suggestionBuilder.setZoneId(countryResult.zoneId);
-            suggestionBuilder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
-            suggestionBuilder.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+            suggestionBuilder.setMatchType(
+                    TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+            suggestionBuilder.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
             suggestionBuilder.addDebugInfo(
                     "findTimeZoneFromCountryAndNitz: high quality country-only suggestion:"
                             + " countryResult=" + countryResult);
@@ -230,39 +231,40 @@
     }
 
     /**
-     * Creates a {@link PhoneTimeZoneSuggestion} using only network country code; works well on
+     * Creates a {@link TelephonyTimeZoneSuggestion} using only network country code; works well on
      * countries which only have one time zone or multiple zones with the same offset.
      *
      * @param countryIsoCode country code from network MCC
      * @param whenMillis the time to use when looking at time zone rules data
      */
     @NonNull
-    private PhoneTimeZoneSuggestion findTimeZoneFromNetworkCountryCode(
-            int phoneId, @NonNull String countryIsoCode, long whenMillis) {
+    private TelephonyTimeZoneSuggestion findTimeZoneFromNetworkCountryCode(
+            int slotIndex, @NonNull String countryIsoCode, long whenMillis) {
         Objects.requireNonNull(countryIsoCode);
         if (TextUtils.isEmpty(countryIsoCode)) {
             throw new IllegalArgumentException("countryIsoCode must not be empty");
         }
 
-        PhoneTimeZoneSuggestion.Builder suggestionBuilder =
-                new PhoneTimeZoneSuggestion.Builder(phoneId);
+        TelephonyTimeZoneSuggestion.Builder suggestionBuilder =
+                new TelephonyTimeZoneSuggestion.Builder(slotIndex);
         suggestionBuilder.addDebugInfo("findTimeZoneFromNetworkCountryCode:"
                 + " whenMillis=" + whenMillis + ", countryIsoCode=" + countryIsoCode);
         CountryResult lookupResult = mTimeZoneLookupHelper.lookupByCountry(
                 countryIsoCode, whenMillis);
         if (lookupResult != null) {
             suggestionBuilder.setZoneId(lookupResult.zoneId);
-            suggestionBuilder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+            suggestionBuilder.setMatchType(
+                    TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
 
             int quality;
             if (lookupResult.quality == CountryResult.QUALITY_SINGLE_ZONE
                     || lookupResult.quality == CountryResult.QUALITY_DEFAULT_BOOSTED) {
-                quality = PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+                quality = TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
             } else if (lookupResult.quality == CountryResult.QUALITY_MULTIPLE_ZONES_SAME_OFFSET) {
-                quality = PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+                quality = TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
             } else if (lookupResult.quality
                     == CountryResult.QUALITY_MULTIPLE_ZONES_DIFFERENT_OFFSETS) {
-                quality = PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+                quality = TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
             } else {
                 // This should never happen.
                 throw new IllegalArgumentException(
diff --git a/src/java/com/android/internal/telephony/sip/SipConnectionBase.java b/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
index acf6d36..40e5203 100644
--- a/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
+++ b/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -16,16 +16,15 @@
 
 package com.android.internal.telephony.sip;
 
+import android.os.SystemClock;
+import android.telephony.PhoneNumberUtils;
+
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.UUSInfo;
-
-import android.os.SystemClock;
-import android.telephony.DisconnectCause;
-import android.telephony.Rlog;
-import android.telephony.PhoneNumberUtils;
+import com.android.telephony.Rlog;
 
 abstract class SipConnectionBase extends Connection {
     private static final String LOG_TAG = "SipConnBase";
diff --git a/src/java/com/android/internal/telephony/sip/SipPhone.java b/src/java/com/android/internal/telephony/sip/SipPhone.java
old mode 100644
new mode 100755
index c014531..c8dbf72
--- a/src/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhone.java
@@ -30,7 +30,6 @@
 import android.os.Message;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.text.TextUtils;
 
@@ -40,6 +39,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneNotifier;
+import com.android.telephony.Rlog;
 
 import java.text.ParseException;
 import java.util.List;
@@ -1036,6 +1036,19 @@
             throw new CallStateException ("deflect is not supported for SipPhone");
         }
 
+        @Override
+        public void transfer(String number, boolean isConfirmationRequired)
+                throws CallStateException {
+            //Transfer is not supported.
+            throw new CallStateException("transfer is not supported for SipPhone");
+        }
+
+        @Override
+        public void consultativeTransfer(Connection other) throws CallStateException {
+            //Transfer is not supported.
+            throw new CallStateException("transfer is not supported for SipPhone");
+        }
+
         private void log(String s) {
             Rlog.d(SCN_TAG, s);
         }
diff --git a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 85c97ea..dea124b 100755
--- a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -25,7 +25,6 @@
 import android.os.ResultReceiver;
 import android.sysprop.TelephonyProperties;
 import android.telephony.NetworkScanRequest;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 
@@ -39,6 +38,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneNotifier;
 import com.android.internal.telephony.uicc.IccFileHandler;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -324,12 +324,23 @@
     }
 
     @Override
+    public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
+            Message onComplete) {
+    }
+
+    @Override
     public void setCallForwardingOption(int commandInterfaceCFAction,
             int commandInterfaceCFReason, String dialingNumber,
             int timerSeconds, Message onComplete) {
     }
 
     @Override
+    public void setCallForwardingOption(int commandInterfaceCFAction,
+            int commandInterfaceCFReason, String dialingNumber, int serviceClass,
+            int timerSeconds, Message onComplete) {
+    }
+
+    @Override
     public void getOutgoingCallerIdDisplay(Message onComplete) {
         // FIXME: what to reply?
         AsyncResult.forMessage(onComplete, null, null);
diff --git a/src/java/com/android/internal/telephony/sip/SipPhoneFactory.java b/src/java/com/android/internal/telephony/sip/SipPhoneFactory.java
index 3383bed..42b7be7 100644
--- a/src/java/com/android/internal/telephony/sip/SipPhoneFactory.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhoneFactory.java
@@ -16,11 +16,11 @@
 
 package com.android.internal.telephony.sip;
 
-import com.android.internal.telephony.PhoneNotifier;
-
 import android.content.Context;
 import android.net.sip.SipProfile;
-import android.telephony.Rlog;
+
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.telephony.Rlog;
 
 import java.text.ParseException;
 
diff --git a/src/java/com/android/internal/telephony/uicc/AdnRecord.java b/src/java/com/android/internal/telephony/uicc/AdnRecord.java
index bd99932..8ab7722 100644
--- a/src/java/com/android/internal/telephony/uicc/AdnRecord.java
+++ b/src/java/com/android/internal/telephony/uicc/AdnRecord.java
@@ -20,14 +20,13 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.GsmAlphabet;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 
-
 /**
  *
  * Used to load or store ADNs (Abbreviated Dialing Numbers).
diff --git a/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java b/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java
index 64b47b5..a23248c 100644
--- a/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java
+++ b/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java
@@ -21,7 +21,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 
diff --git a/src/java/com/android/internal/telephony/uicc/AnswerToReset.java b/src/java/com/android/internal/telephony/uicc/AnswerToReset.java
index 6fd7c68..9ded7d6 100644
--- a/src/java/com/android/internal/telephony/uicc/AnswerToReset.java
+++ b/src/java/com/android/internal/telephony/uicc/AnswerToReset.java
@@ -17,10 +17,10 @@
 package com.android.internal.telephony.uicc;
 
 import android.annotation.Nullable;
-import android.telephony.Rlog;
 import android.util.ArrayMap;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java b/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java
index d098cff..da51848 100644
--- a/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java
+++ b/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java
@@ -17,10 +17,10 @@
 package com.android.internal.telephony.uicc;
 
 import android.os.Environment;
-import android.telephony.Rlog;
 import android.util.Xml;
 
 import com.android.internal.telephony.util.XmlUtils;
+import com.android.telephony.Rlog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/src/java/com/android/internal/telephony/uicc/CsimFileHandler.java b/src/java/com/android/internal/telephony/uicc/CsimFileHandler.java
index e45afa9..c5dd05c 100644
--- a/src/java/com/android/internal/telephony/uicc/CsimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/CsimFileHandler.java
@@ -16,9 +16,8 @@
 
 package com.android.internal.telephony.uicc;
 
-import android.telephony.Rlog;
-
 import com.android.internal.telephony.CommandsInterface;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/uicc/IccCardApplicationStatus.java b/src/java/com/android/internal/telephony/uicc/IccCardApplicationStatus.java
index 06a60b3..a47cc00 100644
--- a/src/java/com/android/internal/telephony/uicc/IccCardApplicationStatus.java
+++ b/src/java/com/android/internal/telephony/uicc/IccCardApplicationStatus.java
@@ -17,10 +17,9 @@
 package com.android.internal.telephony.uicc;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
-
+import com.android.telephony.Rlog;
 
 /**
  * See also RIL_AppStatus in include/telephony/ril.h
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index 47f2d5e..fdfd05a 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -18,14 +18,13 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
-import android.telephony.Rlog;
+import android.os.SystemClock;
 import android.telephony.SubscriptionInfo;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -34,6 +33,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.util.ArrayUtils;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -78,35 +78,26 @@
     };
 
     // ***** Instance Variables
-    @UnsupportedAppUsage
     protected AtomicBoolean mDestroyed = new AtomicBoolean(false);
     protected AtomicBoolean mLoaded = new AtomicBoolean(false);
-    @UnsupportedAppUsage
     protected Context mContext;
-    @UnsupportedAppUsage
     protected CommandsInterface mCi;
-    @UnsupportedAppUsage
     protected IccFileHandler mFh;
-    @UnsupportedAppUsage
     protected UiccCardApplication mParentApp;
-    @UnsupportedAppUsage
     protected TelephonyManager mTelephonyManager;
 
     protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList();
     protected RegistrantList mLockedRecordsLoadedRegistrants = new RegistrantList();
     protected RegistrantList mNetworkLockedRecordsLoadedRegistrants = new RegistrantList();
     protected RegistrantList mImsiReadyRegistrants = new RegistrantList();
-    @UnsupportedAppUsage
     protected RegistrantList mRecordsEventsRegistrants = new RegistrantList();
     protected RegistrantList mNewSmsRegistrants = new RegistrantList();
     protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList();
     protected RegistrantList mSpnUpdatedRegistrants = new RegistrantList();
     protected RegistrantList mRecordsOverrideRegistrants = new RegistrantList();
 
-    @UnsupportedAppUsage
     protected int mRecordsToLoad;  // number of pending load requests
 
-    @UnsupportedAppUsage
     protected AdnRecordCache mAdnCache;
 
     // ***** Cached SIM State; cleared on channel close
@@ -121,7 +112,6 @@
     protected boolean mRecordsRequested = false; // true if we've made requests for the sim records
     protected int mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
 
-    @UnsupportedAppUsage
     protected String mIccId;  // Includes only decimals (no hex)
 
     protected String mFullIccId;  // Includes hex characters in ICCID
@@ -129,28 +119,20 @@
     protected String mMsisdnTag = null;
     protected String mNewMsisdn = null;
     protected String mNewMsisdnTag = null;
-    @UnsupportedAppUsage
     protected String mVoiceMailNum = null;
     protected String mVoiceMailTag = null;
     protected String mNewVoiceMailNum = null;
     protected String mNewVoiceMailTag = null;
-    @UnsupportedAppUsage
     protected boolean mIsVoiceMailFixed = false;
-    @UnsupportedAppUsage
     protected String mImsi; // IMSI must be only valid numeric characters 0-9 without padding 'f's
-    @UnsupportedAppUsage
-    private IccIoResult auth_rsp;
 
-    @UnsupportedAppUsage
     protected int mMncLength = UNINITIALIZED;
     protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated
 
     protected int mSmsCountOnIcc = 0;
 
-    @UnsupportedAppUsage
     private String mSpn;
 
-    @UnsupportedAppUsage
     protected String mGid1;
     protected String mGid2;
 
@@ -174,9 +156,6 @@
     protected String[] mEhplmns;
     protected String[] mFplmns;
 
-    @UnsupportedAppUsage
-    private final Object mLock = new Object();
-
     CarrierTestOverride mCarrierTestOverride;
 
     //Arbitrary offset for the Handler
@@ -216,7 +195,7 @@
 
     public static final int EVENT_GET_ICC_RECORD_DONE = 100;
     public static final int EVENT_REFRESH = 31; // ICC refresh occurred
-    private static final int EVENT_AKA_AUTHENTICATE_DONE          = 90;
+    private static final int EVENT_AKA_AUTHENTICATE_DONE = 90;
     protected static final int EVENT_GET_SMS_RECORD_SIZE_DONE = 28;
 
     protected static final int SYSTEM_EVENT_BASE = 0x100;
@@ -231,6 +210,20 @@
     public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2;
     public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1;
 
+    // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not
+    // arrive and returning null to the callers.
+    private static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500;
+
+    /**
+     * There are two purposes for this class. First, each instance of AuthAsyncResponse acts as a
+     * lock to for calling thead to wait in getIccSimChallengeResponse(). Second, pass the IMS
+     * authentication response to the getIccSimChallengeResponse().
+     */
+    private static class AuthAsyncResponse {
+        public IccIoResult authRsp;
+        public Throwable exception;
+    }
+
     @Override
     public String toString() {
         String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId);
@@ -311,13 +304,6 @@
     public void dispose() {
         mDestroyed.set(true);
 
-        // It is possible that there is another thread waiting for the response
-        // to requestIccSimAuthentication() in getIccSimChallengeResponse().
-        auth_rsp = null;
-        synchronized (mLock) {
-            mLock.notifyAll();
-        }
-
         mCi.unregisterForIccRefresh(this);
         mParentApp.unregisterForReady(this);
         mParentApp.unregisterForLocked(this);
@@ -392,7 +378,6 @@
      * hex digits.
      * @return ICC ID without hex digits
      */
-    @UnsupportedAppUsage
     public String getIccId() {
         if (mCarrierTestOverride.isInTestMode()) {
             String fakeIccId = mCarrierTestOverride.getFakeIccid();
@@ -411,7 +396,6 @@
         return mFullIccId;
     }
 
-    @UnsupportedAppUsage
     public void registerForRecordsLoaded(Handler h, int what, Object obj) {
         if (mDestroyed.get()) {
             return;
@@ -424,7 +408,7 @@
             r.notifyRegistrant(new AsyncResult(null, null, null));
         }
     }
-    @UnsupportedAppUsage
+
     public void unregisterForRecordsLoaded(Handler h) {
         mRecordsLoadedRegistrants.remove(h);
     }
@@ -524,7 +508,6 @@
         mSpnUpdatedRegistrants.remove(h);
     }
 
-    @UnsupportedAppUsage
     public void registerForRecordsEvents(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
         mRecordsEventsRegistrants.add(r);
@@ -534,28 +517,25 @@
         r.notifyResult(EVENT_MWI);
         r.notifyResult(EVENT_CFI);
     }
-    @UnsupportedAppUsage
+
     public void unregisterForRecordsEvents(Handler h) {
         mRecordsEventsRegistrants.remove(h);
     }
 
-    @UnsupportedAppUsage
     public void registerForNewSms(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
         mNewSmsRegistrants.add(r);
     }
-    @UnsupportedAppUsage
+
     public void unregisterForNewSms(Handler h) {
         mNewSmsRegistrants.remove(h);
     }
 
-    @UnsupportedAppUsage
     public void registerForNetworkSelectionModeAutomatic(
             Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
         mNetworkSelectionModeAutomaticRegistrants.add(r);
     }
-    @UnsupportedAppUsage
     public void unregisterForNetworkSelectionModeAutomatic(Handler h) {
         mNetworkSelectionModeAutomaticRegistrants.remove(h);
     }
@@ -567,7 +547,6 @@
      *
      * @return null if SIM is not yet ready or unavailable
      */
-    @UnsupportedAppUsage
     public String getIMSI() {
         if (mCarrierTestOverride.isInTestMode()) {
             String fakeImsi = mCarrierTestOverride.getFakeIMSI();
@@ -664,7 +643,6 @@
         return null;
     }
 
-    @UnsupportedAppUsage
     public String getMsisdnNumber() {
         return mMsisdn;
     }
@@ -673,7 +651,6 @@
      * Get the Group Identifier Level 1 (GID1) on a SIM for GSM.
      * @return null if SIM is not yet ready
      */
-    @UnsupportedAppUsage
     public String getGid1() {
         if (mCarrierTestOverride.isInTestMode()) {
             String fakeGid1 = mCarrierTestOverride.getFakeGid1();
@@ -712,7 +689,6 @@
         return mPnnHomeName;
     }
 
-    @UnsupportedAppUsage
     public void setMsisdnNumber(String alphaTag, String number,
             Message onComplete) {
         loge("setMsisdn() should not be invoked on base IccRecords");
@@ -735,7 +711,6 @@
      *
      * @return null if SIM is not yet ready or no RUIM entry
      */
-    @UnsupportedAppUsage
     public String getServiceProviderName() {
         if (mCarrierTestOverride.isInTestMode()) {
             String fakeSpn = mCarrierTestOverride.getFakeSpn();
@@ -822,7 +797,6 @@
      */
     public abstract void onRefresh(boolean fileChanged, int[] fileList);
 
-    @UnsupportedAppUsage
     public boolean getRecordsLoaded() {
         return mRecordsToLoad == 0 && mRecordsRequested;
     }
@@ -889,21 +863,28 @@
                 break;
 
             case EVENT_AKA_AUTHENTICATE_DONE:
-                ar = (AsyncResult)msg.obj;
-                auth_rsp = null;
+                ar = (AsyncResult) msg.obj;
+                AuthAsyncResponse rsp = (AuthAsyncResponse) ar.userObj;
                 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE");
-                if (ar.exception != null) {
-                    loge("Exception ICC SIM AKA: " + ar.exception);
-                } else {
-                    try {
-                        auth_rsp = (IccIoResult)ar.result;
-                        if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp);
-                    } catch (Exception e) {
-                        loge("Failed to parse ICC SIM AKA contents: " + e);
+
+                synchronized (rsp) {
+                    if (ar.exception != null) {
+                        rsp.exception = ar.exception;
+                        loge("Exception ICC SIM AKA: " + ar.exception);
+                    } else if (ar.result == null) {
+                        rsp.exception = new NullPointerException(
+                                "Null SIM authentication response");
+                        loge("EVENT_AKA_AUTHENTICATE_DONE: null response");
+                    } else {
+                        try {
+                            rsp.authRsp = (IccIoResult) ar.result;
+                            if (VDBG) log("ICC SIM AKA: authRsp = " + rsp.authRsp);
+                        } catch (ClassCastException e) {
+                            rsp.exception = e;
+                            loge("Failed to parse ICC SIM AKA contents: " + e);
+                        }
                     }
-                }
-                synchronized (mLock) {
-                    mLock.notifyAll();
+                    rsp.notifyAll();
                 }
 
                 break;
@@ -985,7 +966,6 @@
 
     protected abstract void handleFileUpdate(int efid);
 
-    @UnsupportedAppUsage
     protected void handleRefresh(IccRefreshResponse refreshResponse){
         if (refreshResponse == null) {
             if (DBG) log("handleRefresh received without input");
@@ -1090,7 +1070,6 @@
      * or is not valid for the type of IccCard. Generally used for
      * GSM/UMTS and the like SIMS
      */
-    @UnsupportedAppUsage
     public String getOperatorNumeric() {
         return null;
     }
@@ -1111,7 +1090,6 @@
      * @param enable
      * @param number to which CFU is enabled
      */
-    @UnsupportedAppUsage
     public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
     }
 
@@ -1139,7 +1117,6 @@
      *
      * @param s is the string to write
      */
-    @UnsupportedAppUsage
     protected abstract void log(String s);
 
     /**
@@ -1176,60 +1153,74 @@
         return null;
     }
 
-    @UnsupportedAppUsage
     public UsimServiceTable getUsimServiceTable() {
         return null;
     }
 
     /**
+     * Solve authentication leakage issue. See b/147463955.
      * Returns the response of the SIM application on the UICC to authentication
      * challenge/response algorithm. The data string and challenge response are
      * Base64 encoded Strings.
      * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102.
      *
-     * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2)
+     * @param authContext parameter P2 that specifies the authentication context
+     * per 3GPP TS 31.102 (Section 7.1.2)
      * @param data authentication challenge data
      * @return challenge response
      */
-    @UnsupportedAppUsage
+    @Nullable
     public String getIccSimChallengeResponse(int authContext, String data) {
-        if (DBG) log("getIccSimChallengeResponse:");
+        if (VDBG) log("getIccSimChallengeResponse:");
 
-        try {
-            synchronized(mLock) {
-                CommandsInterface ci = mCi;
-                UiccCardApplication parentApp = mParentApp;
-                if (ci != null && parentApp != null) {
-                    ci.requestIccSimAuthentication(authContext, data,
-                            parentApp.getAid(),
-                            obtainMessage(EVENT_AKA_AUTHENTICATE_DONE));
-                    try {
-                        mLock.wait();
-                    } catch (InterruptedException e) {
-                        loge("getIccSimChallengeResponse: Fail, interrupted"
-                                + " while trying to request Icc Sim Auth");
-                        return null;
-                    }
-                } else {
-                    loge( "getIccSimChallengeResponse: "
-                            + "Fail, ci or parentApp is null");
-                    return null;
+        //final here is for defensive copy.
+        final CommandsInterface ci = mCi;
+        final UiccCardApplication parentApp = mParentApp;
+        if (ci == null || parentApp == null) {
+            loge("getIccSimChallengeResponse: Fail, ci or parentApp is null");
+            return null;
+        }
+
+        AuthAsyncResponse rsp = new AuthAsyncResponse();
+
+        synchronized (rsp) {
+            ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(),
+                    obtainMessage(EVENT_AKA_AUTHENTICATE_DONE, 0, 0, rsp));
+            //TODO: factor wait with timeout into a separate method
+            final long startTime = SystemClock.elapsedRealtime();
+            do {
+                try {
+                    long sleepTime = startTime + ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
+                            - SystemClock.elapsedRealtime();
+                    if (sleepTime > 0) rsp.wait(sleepTime);
+                } catch (InterruptedException e) {
+                    Rlog.w("IccRecords", "getIccSimChallengeResponse: InterruptedException.");
                 }
+            } while (SystemClock.elapsedRealtime() - startTime < ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
+                    && rsp.authRsp == null && rsp.exception == null);
+
+            if (SystemClock.elapsedRealtime() - startTime >= ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
+                    && rsp.authRsp == null && rsp.exception == null) {
+                loge("getIccSimChallengeResponse timeout!");
+                return null;
             }
-        } catch(Exception e) {
-            loge( "getIccSimChallengeResponse: "
-                    + "Fail while trying to request Icc Sim Auth");
-            return null;
+
+            if (rsp.exception != null) {
+                loge("getIccSimChallengeResponse exception: " + rsp.exception);
+                //TODO: propagate better exceptions up to the user now that we have them available
+                //in the call stack.
+                return null;
+            }
+
+            if (rsp.authRsp == null) {
+                loge("getIccSimChallengeResponse: No authentication response");
+                return null;
+            }
         }
+        if (VDBG) log("getIccSimChallengeResponse: return rsp.authRsp");
 
-        if (auth_rsp == null) {
-            loge("getIccSimChallengeResponse: No authentication response");
-            return null;
-        }
-
-        if (DBG) log("getIccSimChallengeResponse: return auth_rsp");
-
-        return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP);
+        return android.util.Base64.encodeToString(rsp.authRsp.payload,
+                android.util.Base64.NO_WRAP);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/uicc/IccServiceTable.java b/src/java/com/android/internal/telephony/uicc/IccServiceTable.java
index b811d5c..fe6e433 100644
--- a/src/java/com/android/internal/telephony/uicc/IccServiceTable.java
+++ b/src/java/com/android/internal/telephony/uicc/IccServiceTable.java
@@ -17,7 +17,8 @@
 package com.android.internal.telephony.uicc;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 /**
  * Wrapper class for an ICC EF containing a bit field of enabled services.
diff --git a/src/java/com/android/internal/telephony/uicc/IsimFileHandler.java b/src/java/com/android/internal/telephony/uicc/IsimFileHandler.java
index 6fe16c9..fe900cb 100644
--- a/src/java/com/android/internal/telephony/uicc/IsimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/IsimFileHandler.java
@@ -16,9 +16,8 @@
 
 package com.android.internal.telephony.uicc;
 
-import android.telephony.Rlog;
-
 import com.android.internal.telephony.CommandsInterface;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
index 766668c..460afc7 100644
--- a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
@@ -21,11 +21,11 @@
 import android.content.Intent;
 import android.os.AsyncResult;
 import android.os.Message;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.gsm.SimTlv;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -344,6 +344,7 @@
                 mRecordsToLoad++;
 
             default:
+                mLoaded.set(false);
                 fetchIsimRecords();
                 break;
         }
@@ -434,12 +435,20 @@
     @UnsupportedAppUsage
     @Override
     protected void log(String s) {
-        if (DBG) Rlog.d(LOG_TAG, "[ISIM] " + s);
+        if (mParentApp != null) {
+            Rlog.d(LOG_TAG, "[ISIM-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.d(LOG_TAG, "[ISIM] " + s);
+        }
     }
 
     @Override
     protected void loge(String s) {
-        if (DBG) Rlog.e(LOG_TAG, "[ISIM] " + s);
+        if (mParentApp != null) {
+            Rlog.e(LOG_TAG, "[ISIM-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.e(LOG_TAG, "[ISIM] " + s);
+        }
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
index 4d0b484..61352d9 100755
--- a/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
+++ b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
@@ -19,7 +19,8 @@
 import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/src/java/com/android/internal/telephony/uicc/RuimFileHandler.java b/src/java/com/android/internal/telephony/uicc/RuimFileHandler.java
index 58e939f..2323b5a 100644
--- a/src/java/com/android/internal/telephony/uicc/RuimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/RuimFileHandler.java
@@ -17,9 +17,9 @@
 package com.android.internal.telephony.uicc;
 
 import android.os.*;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandsInterface;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
index 0951678..28ce2d2 100644
--- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
@@ -22,7 +22,6 @@
 import android.os.AsyncResult;
 import android.os.Message;
 import android.sysprop.TelephonyProperties;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
@@ -35,6 +34,7 @@
 import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.util.BitwiseInputStream;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -936,6 +936,7 @@
 
     @Override
     protected void handleFileUpdate(int efid) {
+        mLoaded.set(false);
         mAdnCache.reset();
         fetchRuimRecords();
     }
@@ -964,13 +965,21 @@
     @UnsupportedAppUsage
     @Override
     protected void log(String s) {
-        Rlog.d(LOG_TAG, "[RuimRecords] " + s);
+        if (mParentApp != null) {
+            Rlog.d(LOG_TAG, "[RuimRecords-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.d(LOG_TAG, "[RuimRecords] " + s);
+        }
     }
 
     @UnsupportedAppUsage
     @Override
     protected void loge(String s) {
-        Rlog.e(LOG_TAG, "[RuimRecords] " + s);
+        if (mParentApp != null) {
+            Rlog.e(LOG_TAG, "[RuimRecords-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.e(LOG_TAG, "[RuimRecords] " + s);
+        }
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
index 3be0c99..be165c1 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
@@ -16,9 +16,8 @@
 
 package com.android.internal.telephony.uicc;
 
-import android.telephony.Rlog;
-
 import com.android.internal.telephony.CommandsInterface;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index baa5683..1118045 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony.uicc;
 
+import static android.telephony.SmsManager.STATUS_ON_ICC_READ;
+import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
+
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
@@ -24,7 +27,6 @@
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionInfo;
 import android.text.TextUtils;
@@ -36,6 +38,7 @@
 import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.gsm.SimTlv;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -929,7 +932,7 @@
                     break;
 
                 case EVENT_MARK_SMS_READ_DONE:
-                    Rlog.i("ENF", "marked read: sms " + msg.arg1);
+                    log("marked read: sms " + msg.arg1);
                     break;
 
 
@@ -1345,6 +1348,7 @@
                 // For now, fetch all records if this is not a
                 // voicemail number.
                 // TODO: Handle other cases, instead of fetching all.
+                mLoaded.set(false);
                 mAdnCache.reset();
                 fetchSimRecords();
                 break;
@@ -1355,21 +1359,18 @@
      * Dispatch 3GPP format message to registrant ({@code GsmCdmaPhone}) to pass to the 3GPP SMS
      * dispatcher for delivery.
      */
-    private int dispatchGsmMessage(SmsMessage message) {
+    private void dispatchGsmMessage(SmsMessage message) {
         mNewSmsRegistrants.notifyResult(message);
-        return 0;
     }
 
     private void handleSms(byte[] ba) {
-        if (ba[0] != 0)
-            Rlog.d("ENF", "status : " + ba[0]);
+        if (DBG) log("handleSms status : " + ba[0]);
 
-        // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
-        // 3 == "received by MS from network; message to be read"
-        if (ba[0] == 3) {
+        // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3)
+        if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) {
             int n = ba.length;
 
-            // Note: Data may include trailing FF's.  That's OK; message
+            // Note: Data may include trailing FF's. That's OK; message
             // should still parse correctly.
             byte[] pdu = new byte[n - 1];
             System.arraycopy(ba, 1, pdu, 0, n - 1);
@@ -1379,23 +1380,19 @@
         }
     }
 
-
     private void handleSmses(ArrayList<byte[]> messages) {
         int count = messages.size();
 
         for (int i = 0; i < count; i++) {
             byte[] ba = messages.get(i);
 
-            if (ba[0] != 0)
-                Rlog.i("ENF", "status " + i + ": " + ba[0]);
+            if (DBG) log("handleSmses status " + i + ": " + ba[0]);
 
-            // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
-            // 3 == "received by MS from network; message to be read"
-
-            if (ba[0] == 3) {
+            // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3)
+            if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) {
                 int n = ba.length;
 
-                // Note: Data may include trailing FF's.  That's OK; message
+                // Note: Data may include trailing FF's. That's OK; message
                 // should still parse correctly.
                 byte[] pdu = new byte[n - 1];
                 System.arraycopy(ba, 1, pdu, 0, n - 1);
@@ -1403,10 +1400,7 @@
 
                 dispatchGsmMessage(message);
 
-                // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
-                // 1 == "received by MS from network; message read"
-
-                ba[0] = 1;
+                ba[0] = (byte) STATUS_ON_ICC_READ;
 
                 if (false) { // FIXME: writing seems to crash RdoServD
                     mFh.updateEFLinearFixed(EF_SMS,
@@ -1926,22 +1920,38 @@
     @UnsupportedAppUsage
     @Override
     protected void log(String s) {
-        Rlog.d(LOG_TAG, "[SIMRecords] " + s);
+        if (mParentApp != null) {
+            Rlog.d(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.d(LOG_TAG, "[SIMRecords] " + s);
+        }
     }
 
     @UnsupportedAppUsage
     @Override
     protected void loge(String s) {
-        Rlog.e(LOG_TAG, "[SIMRecords] " + s);
+        if (mParentApp != null) {
+            Rlog.e(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.e(LOG_TAG, "[SIMRecords] " + s);
+        }
     }
 
     protected void logw(String s, Throwable tr) {
-        Rlog.w(LOG_TAG, "[SIMRecords] " + s, tr);
+        if (mParentApp != null) {
+            Rlog.w(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s, tr);
+        } else {
+            Rlog.w(LOG_TAG, "[SIMRecords] " + s, tr);
+        }
     }
 
     @UnsupportedAppUsage
     protected void logv(String s) {
-        Rlog.v(LOG_TAG, "[SIMRecords] " + s);
+        if (mParentApp != null) {
+            Rlog.v(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
+        } else {
+            Rlog.v(LOG_TAG, "[SIMRecords] " + s);
+        }
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCard.java b/src/java/com/android/internal/telephony/uicc/UiccCard.java
index d06cdb0..73e26a9 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCard.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCard.java
@@ -24,7 +24,6 @@
 import android.content.pm.Signature;
 import android.os.Handler;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
@@ -33,6 +32,7 @@
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index 5921046..83fbb65 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -23,7 +23,6 @@
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.PhoneConstants;
@@ -31,6 +30,7 @@
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
index 2177656..e1bc0b7 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
@@ -27,13 +27,13 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.telephony.UiccAccessRule;
 import android.text.TextUtils;
 import android.util.LocalLog;
 
 import com.android.internal.telephony.CommandException;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 96c9d1b..a00a364 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -35,7 +35,6 @@
 import android.os.storage.StorageManager;
 import android.preference.PreferenceManager;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.telephony.UiccCardInfo;
 import android.text.TextUtils;
@@ -51,6 +50,7 @@
 import com.android.internal.telephony.RadioConfig;
 import com.android.internal.telephony.SubscriptionInfoUpdater;
 import com.android.internal.telephony.uicc.euicc.EuiccCard;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -696,17 +696,32 @@
             cardString = card.getIccId();
         }
 
-        // EID may be unpopulated if RadioConfig<1.2
-        // If so, just register for EID loaded and skip this stuff
-        if (isEuicc && cardString == null
-                && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) {
-            ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index);
-        }
-
         if (cardString != null) {
             addCardId(cardString);
         }
 
+        // EID is unpopulated if Radio HAL < 1.4 (RadioConfig < 1.2)
+        // If so, just register for EID loaded and skip this stuff
+        if (isEuicc && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) {
+            if (cardString == null) {
+                ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index);
+            } else {
+                // If we know the EID from IccCardStatus, just use it to set mDefaultEuiccCardId if
+                // it's not already set.
+                // This is needed in cases where slot status doesn't include EID, and we don't want
+                // to register for EID from APDU because we already know cardString from a previous
+                // APDU
+                if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID
+                        || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) {
+                    mDefaultEuiccCardId = convertToPublicCardId(cardString);
+                    String logStr = "IccCardStatus eid=" + cardString + " slot=" + slotId
+                            + " mDefaultEuiccCardId=" + mDefaultEuiccCardId;
+                    sLocalLog.log(logStr);
+                    log(logStr);
+                }
+            }
+        }
+
         if (DBG) log("Notifying IccChangedRegistrants");
         mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
     }
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java b/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
index cc99ae9..3513bb9 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
@@ -19,9 +19,9 @@
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules.TLV;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 971c93a..9ac21b0 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -38,7 +38,6 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -62,6 +61,7 @@
 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
 import com.android.internal.telephony.uicc.euicc.EuiccCard;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index 0c2c60b..db0aeb7 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -27,7 +27,6 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.UserHandle;
-import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.view.WindowManager;
@@ -39,6 +38,7 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
 import com.android.internal.telephony.uicc.euicc.EuiccCard;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
index b120eb6..ff8d63d 100755
--- a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
@@ -16,10 +16,8 @@
 
 package com.android.internal.telephony.uicc;
 
-import android.telephony.Rlog;
-
 import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.uicc.UiccCardApplication;
+import com.android.telephony.Rlog;
 
 /**
  * {@hide}
diff --git a/src/java/com/android/internal/telephony/uicc/VoiceMailConstants.java b/src/java/com/android/internal/telephony/uicc/VoiceMailConstants.java
index 792c7dc..b10b875 100644
--- a/src/java/com/android/internal/telephony/uicc/VoiceMailConstants.java
+++ b/src/java/com/android/internal/telephony/uicc/VoiceMailConstants.java
@@ -18,10 +18,10 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Environment;
-import android.telephony.Rlog;
 import android.util.Xml;
 
 import com.android.internal.telephony.util.XmlUtils;
+import com.android.telephony.Rlog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java b/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
index 12f2ead..bff29ff 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
@@ -25,7 +25,6 @@
 import android.os.RegistrantList;
 import android.service.carrier.CarrierIdentifier;
 import android.service.euicc.EuiccProfileInfo;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.UiccAccessRule;
 import android.telephony.euicc.EuiccCardManager;
@@ -53,6 +52,7 @@
 import com.android.internal.telephony.uicc.euicc.apdu.RequestProvider;
 import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
 import com.android.internal.telephony.uicc.euicc.async.AsyncResultHelper;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/EuiccSpecVersion.java b/src/java/com/android/internal/telephony/uicc/euicc/EuiccSpecVersion.java
index b038716..9450bfc 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/EuiccSpecVersion.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/EuiccSpecVersion.java
@@ -16,12 +16,11 @@
 
 package com.android.internal.telephony.uicc.euicc;
 
-import android.telephony.Rlog;
-
 import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
 import com.android.internal.telephony.uicc.asn1.Asn1Node;
 import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
 import com.android.internal.telephony.uicc.asn1.TagNotFoundException;
+import com.android.telephony.Rlog;
 
 import java.util.Arrays;
 
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index 00b4945..8e7237e 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -20,12 +20,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.telephony.IccOpenLogicalChannelResponse;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
 import com.android.internal.telephony.uicc.euicc.async.AsyncResultHelper;
+import com.android.telephony.Rlog;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/CloseLogicalChannelInvocation.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/CloseLogicalChannelInvocation.java
index edd89d6..82ddb80 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/CloseLogicalChannelInvocation.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/CloseLogicalChannelInvocation.java
@@ -18,11 +18,11 @@
 
 import android.os.AsyncResult;
 import android.os.Message;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.uicc.euicc.async.AsyncMessageInvocation;
+import com.android.telephony.Rlog;
 
 /**
  * Invokes {@link CommandsInterface#iccCloseLogicalChannel(int, Message)}. This takes a channel id
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/OpenLogicalChannelInvocation.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/OpenLogicalChannelInvocation.java
index 15b0c43..caed9cf 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/OpenLogicalChannelInvocation.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/OpenLogicalChannelInvocation.java
@@ -19,11 +19,11 @@
 import android.os.AsyncResult;
 import android.os.Message;
 import android.telephony.IccOpenLogicalChannelResponse;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.uicc.euicc.async.AsyncMessageInvocation;
+import com.android.telephony.Rlog;
 
 /**
  * Invokes {@link CommandsInterface#iccOpenLogicalChannel(String, int, Message)}. This takes AID
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/TransmitApduLogicalChannelInvocation.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/TransmitApduLogicalChannelInvocation.java
index 296fe47..09de54a 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/TransmitApduLogicalChannelInvocation.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/TransmitApduLogicalChannelInvocation.java
@@ -18,12 +18,12 @@
 
 import android.os.AsyncResult;
 import android.os.Message;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.euicc.async.AsyncMessageInvocation;
+import com.android.telephony.Rlog;
 
 /**
  * Invokes {@link CommandsInterface#iccTransmitApduLogicalChannel(int, int, int, int, int, int,
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/async/AsyncResultCallback.java b/src/java/com/android/internal/telephony/uicc/euicc/async/AsyncResultCallback.java
index b28e7e7..58ab6bf 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/async/AsyncResultCallback.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/async/AsyncResultCallback.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony.uicc.euicc.async;
 
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
 
 /**
  * Class to deliver the returned value from an asynchronous call. Either {@link #onResult(Result)}
diff --git a/src/java/com/android/internal/telephony/util/LocaleUtils.java b/src/java/com/android/internal/telephony/util/LocaleUtils.java
index 755585b..064b10d 100644
--- a/src/java/com/android/internal/telephony/util/LocaleUtils.java
+++ b/src/java/com/android/internal/telephony/util/LocaleUtils.java
@@ -18,10 +18,10 @@
 
 import android.content.Context;
 import android.icu.util.ULocale;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.MccTable;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/src/java/com/android/internal/telephony/vendor/VendorGsmCdmaPhone.java b/src/java/com/android/internal/telephony/vendor/VendorGsmCdmaPhone.java
new file mode 100644
index 0000000..0c92159
--- /dev/null
+++ b/src/java/com/android/internal/telephony/vendor/VendorGsmCdmaPhone.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.vendor;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.GsmCdmaPhone;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.TelephonyComponentFactory;
+
+public class VendorGsmCdmaPhone extends GsmCdmaPhone {
+    private static final String LOG_TAG = "VendorGsmCdmaPhone";
+    private static final int PROP_EVENT_START = EVENT_LAST;
+    private static final int DEFAULT_PHONE_INDEX = 0;
+
+    private boolean mIsPhoneReadySent = false;
+    private boolean mIsPhoneReadyPending = false;
+    private static int READY = 1;
+
+    public VendorGsmCdmaPhone(Context context,
+            CommandsInterface ci, PhoneNotifier notifier, int phoneId,
+            int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) {
+        this(context, ci, notifier, false, phoneId, precisePhoneType,
+                telephonyComponentFactory);
+    }
+
+    public VendorGsmCdmaPhone(Context context,
+            CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId,
+            int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) {
+        super(context, ci, notifier, unitTestMode, phoneId, precisePhoneType,
+                telephonyComponentFactory);
+        Rlog.d(LOG_TAG, "Constructor");
+    }
+
+    @Override
+    protected void phoneObjectUpdater(int newVoiceTech) {
+        super.phoneObjectUpdater(newVoiceTech);
+    }
+
+    @Override
+    public boolean getCallForwardingIndicator() {
+        if (!isCurrentSubValid()) {
+            return false;
+        }
+        return super.getCallForwardingIndicator();
+    }
+
+    private boolean isCurrentSubValid() {
+        boolean isUiccApplicationEnabled = true;
+        // FIXME get the SubscriptionManager.UICC_APPLICATIONS_ENABLED value and use it above
+
+        SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
+
+        Rlog.d(LOG_TAG, "ProvisionStatus: " + isUiccApplicationEnabled + " phone id:" + mPhoneId);
+        return subscriptionManager.isActiveSubscriptionId(getSubId()) && isUiccApplicationEnabled;
+    }
+
+    public void fetchIMEI() {
+            Rlog.d(LOG_TAG, "fetching device id");
+            mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        Rlog.d(LOG_TAG, "handleMessage: Event: " + msg.what);
+        AsyncResult ar;
+        switch(msg.what) {
+
+            case EVENT_SIM_RECORDS_LOADED:
+                if(isPhoneTypeGsm()) {
+                    Rlog.d(LOG_TAG, "notify call forward indication, phone id:" + mPhoneId);
+                    notifyCallForwardingIndicator();
+                }
+
+                super.handleMessage(msg);
+                break;
+
+            case EVENT_RADIO_AVAILABLE:
+                mIsPhoneReadySent = false;
+                super.handleMessage(msg);
+                break;
+
+            case EVENT_RIL_CONNECTED:
+                mIsPhoneReadySent = false;
+                super.handleMessage(msg);
+                break;
+
+            default: {
+                super.handleMessage(msg);
+            }
+
+        }
+    }
+
+    // In DSDA, char 'D' is used as DTMF char for playing supervisory tone for G/W.
+    // For CDMA, '#' is used. A, B, C & D are also supported as DTMF digits for G/W networks.
+    @Override
+    public void startDtmf(char c) {
+        if (!(PhoneNumberUtils.is12Key(c) || (c == 'D'))) {
+            Rlog.e(LOG_TAG, "startDtmf called with invalid character '" + c + "'");
+        } else {
+            if (isPhoneTypeCdma() && c == 'D') {
+                c = '#';
+            }
+            mCi.startDtmf(c, null);
+        }
+    }
+
+    // For CDMA sendBurstDtmf is used, if dtmf char is 'D' then it with '#'
+    // since 'D' is used for SCH tone and for CDMA it has to be '#'.
+    @Override
+    public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
+        Character c = dtmfString.charAt(0);
+        if(dtmfString.length() == 1 && c == 'D') {
+            dtmfString = c.toString();
+        }
+        super.sendBurstDtmf(dtmfString, on, off, onComplete);
+    }
+
+    // When OOS occurs, IMS registration may be still available so that IMS service
+    // state is also in-service, then reports in-service to upper layer.
+    // Add a precondition to merge IMS service so that notifies proper service state
+    // after IMS changes RAT.
+    @Override
+    public ServiceState getServiceState() {
+        if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
+            // Ensure UE has IMS service capability, then merge IMS service state.
+            // Video enabled includes WIFI video
+            final boolean isImsEnabled = mImsPhone != null && (mImsPhone.isVolteEnabled()
+                    || mImsPhone.isVideoEnabled()
+                    || mImsPhone.isWifiCallingEnabled());
+            if (isImsEnabled) {
+                return ServiceState.mergeServiceStates(
+                        ((mSST == null) ? new ServiceState() : mSST.mSS),
+                        mImsPhone.getServiceState());
+            }
+        }
+
+        if (mSST != null) {
+            return mSST.mSS;
+        } else {
+            // avoid potential NPE in EmergencyCallHelper during Phone switch
+            return new ServiceState();
+        }
+    }
+
+    private void logd(String msg) {
+        Rlog.d(LOG_TAG, "[" + mPhoneId +" ] " + msg);
+    }
+
+    private void loge(String msg) {
+        Rlog.e(LOG_TAG, "[" + mPhoneId +" ] " + msg);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/vendor/VendorServiceStateTracker.java b/src/java/com/android/internal/telephony/vendor/VendorServiceStateTracker.java
new file mode 100644
index 0000000..de9d42c
--- /dev/null
+++ b/src/java/com/android/internal/telephony/vendor/VendorServiceStateTracker.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.vendor;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.GsmCdmaPhone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+
+public class VendorServiceStateTracker extends ServiceStateTracker {
+    private static final String LOG_TAG = "VendorServiceStateTracker";
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;  // STOPSHIP if true
+    private static final String ACTION_MANAGED_ROAMING_IND =
+            "android.intent.action.ACTION_MANAGED_ROAMING_IND";
+
+    public VendorServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
+        super(phone,ci);
+    }
+
+    @Override
+    protected void handlePollStateResultMessage(int what, AsyncResult ar) {
+        switch (what) {
+            case EVENT_POLL_STATE_CS_CELLULAR_REGISTRATION: {
+                super.handlePollStateResultMessage(what, ar);
+                if (mPhone.isPhoneTypeGsm()) {
+                    NetworkRegistrationInfo regStates = (NetworkRegistrationInfo) ar.result;
+                    int regState = regStates.getRegistrationState();
+
+                    if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_DENIED) {
+                        int rejCode = regStates.getRejectCause();
+                        // Check if rejCode is "Persistent location update reject",
+                        if (rejCode == 10) {
+                            log(" Posting Managed roaming intent sub = "
+                                    + mPhone.getSubId());
+                            try {
+                                Intent intent =
+                                        new Intent(ACTION_MANAGED_ROAMING_IND);
+                                // component would display Dialog to perform Manual scan
+                                // if current Network selection Mode is Manual.
+                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                                intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                                        mPhone.getSubId());
+                                mPhone.getContext().startActivity(intent);
+                            } catch (ActivityNotFoundException e) {
+                                loge("unable to start activity: " + e);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+
+            default:
+                super.handlePollStateResultMessage(what, ar);
+        }
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        if (msg.what == EVENT_RADIO_STATE_CHANGED) {
+            if (mPhone.mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
+                setPowerStateToDesired();
+                log("Trigger as manual polling");
+                pollState();
+            } else {
+                super.handleMessage(msg);
+            }
+        } else {
+            super.handleMessage(msg);
+        }
+    }
+}
diff --git a/src/java/com/android/internal/telephony/vendor/VendorSubscriptionController.java b/src/java/com/android/internal/telephony/vendor/VendorSubscriptionController.java
new file mode 100644
index 0000000..37fa9af
--- /dev/null
+++ b/src/java/com/android/internal/telephony/vendor/VendorSubscriptionController.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.vendor;
+
+import android.content.Context;
+import android.content.Intent;
+import android.Manifest;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.PhoneFactory;
+
+import java.util.Iterator;
+import java.util.List;
+
+/*
+ * Extending SubscriptionController here:
+ * To implement fall back of sms/data user preferred subId value to next
+ * available subId when current preferred SIM deactivated or removed.
+ */
+public class VendorSubscriptionController extends SubscriptionController {
+    static final String LOG_TAG = "VendorSubscriptionController";
+    private static final boolean DBG = true;
+    private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
+
+    private static int sNumPhones;
+
+    private static final int PROVISIONED = 1;
+    private static final int NOT_PROVISIONED = 0;
+
+    private TelecomManager mTelecomManager;
+    private TelephonyManager mTelephonyManager;
+
+    private RegistrantList mAddSubscriptionRecordRegistrants = new RegistrantList();
+
+    private static final String SETTING_USER_PREF_DATA_SUB = "user_preferred_data_sub";
+    /**
+     * This intent would be broadcasted when a subId/slotId pair added to the
+     * sSlotIdxToSubId hashmap.
+     */
+    private static final String ACTION_SUBSCRIPTION_RECORD_ADDED =
+            "android.intent.action.SUBSCRIPTION_INFO_RECORD_ADDED";
+
+    public static VendorSubscriptionController init(Context c) {
+        synchronized (VendorSubscriptionController.class) {
+            if (sInstance == null) {
+                sInstance = new VendorSubscriptionController(c);
+            } else {
+                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
+            }
+            return (VendorSubscriptionController)sInstance;
+        }
+    }
+
+    public static VendorSubscriptionController getInstance() {
+        if (sInstance == null) {
+           Log.wtf(LOG_TAG, "getInstance null");
+        }
+
+        return (VendorSubscriptionController)sInstance;
+    }
+
+    protected VendorSubscriptionController(Context c) {
+        super(c);
+        if (DBG) logd(" init by Context");
+
+        mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        sNumPhones = TelephonyManager.getDefault().getPhoneCount();
+    }
+
+    public void registerForAddSubscriptionRecord(Handler handler, int what, Object obj) {
+        Registrant r = new Registrant(handler, what, obj);
+        synchronized (mAddSubscriptionRecordRegistrants) {
+            mAddSubscriptionRecordRegistrants.add(r);
+            List<SubscriptionInfo> subInfoList =
+                    getActiveSubscriptionInfoList(mContext.getOpPackageName());
+            if (subInfoList != null) {
+                r.notifyRegistrant();
+            }
+        }
+    }
+
+    public void unregisterForAddSubscriptionRecord(Handler handler) {
+        synchronized (mAddSubscriptionRecordRegistrants) {
+            mAddSubscriptionRecordRegistrants.remove(handler);
+        }
+    }
+
+    @Override
+    public int addSubInfoRecord(String iccId, int slotIndex) {
+        logd("addSubInfoRecord: broadcast intent subId[" + slotIndex + "]");
+        return addSubInfo(iccId, null, slotIndex, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+    }
+
+    @Override
+    public int addSubInfo(String uniqueId, String displayName, int slotIndex,
+            int subscriptionType) {
+
+        int retVal = super.addSubInfo(uniqueId, displayName, slotIndex, subscriptionType);
+
+        int[] subId = getSubId(slotIndex);
+        if (subId != null && (subId.length > 0)) {
+            // When a new entry added in sSlotIdxToSubId for slotId, broadcast intent
+            logd("addSubInfoRecord: broadcast intent subId[" + slotIndex + "] = " + subId[0]);
+            mAddSubscriptionRecordRegistrants.notifyRegistrants(
+                    new AsyncResult(null, slotIndex, null));
+            Intent intent = new Intent(ACTION_SUBSCRIPTION_RECORD_ADDED);
+            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, slotIndex, subId[0]);
+            mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+        }
+        return retVal;
+    }
+
+    protected boolean isRadioAvailableOnAllSubs() {
+        for (int i = 0; i < sNumPhones; i++) {
+            if (PhoneFactory.getPhone(i).mCi != null &&
+                    PhoneFactory.getPhone(i).mCi.getRadioState() ==
+                    TelephonyManager.RADIO_POWER_UNAVAILABLE) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected boolean isShuttingDown() {
+        for (int i = 0; i < sNumPhones; i++) {
+            if (PhoneFactory.getPhone(i) != null &&
+                    PhoneFactory.getPhone(i).isShuttingDown()) return true;
+        }
+        return false;
+    }
+
+    public boolean isRadioInValidState() {
+
+        // Radio Unavailable, do not updateUserPrefs. As this may happened due to SSR or RIL Crash.
+        if (!isRadioAvailableOnAllSubs()) {
+            logd(" isRadioInValidState, radio not available");
+            return false;
+        }
+
+        //Do not updateUserPrefs when Shutdown is in progress
+        if (isShuttingDown()) {
+            logd(" isRadioInValidState: device shutdown in progress ");
+            return false;
+        }
+        return true;
+    }
+
+    // If any of the voice/data/sms preference related SIM
+    // deactivated/re-activated this will update the preference
+    // with next available/activated SIM.
+    public void updateUserPreferences() {
+        SubscriptionInfo mNextActivatedSub = null;
+        int activeCount = 0;
+        if (!isRadioInValidState()) {
+            logd("Radio is in Invalid state, Ignore Updating User Preference!!!");
+            return;
+        }
+        List<SubscriptionInfo> sil = getActiveSubscriptionInfoList(mContext.getOpPackageName());
+        // If list of active subscriptions empty OR non of the SIM provisioned
+        // clear defaults preference of voice/sms/data.
+        if (sil == null || sil.size() < 1) {
+            logi("updateUserPreferences: Subscription list is empty");
+            return;
+        }
+
+        // Do not fallback to next available sub if AOSP feature
+        // "User choice of selecting data/sms fallback preference" enabled.
+        if (SystemProperties.getBoolean("persist.vendor.radio.aosp_usr_pref_sel", false)) {
+            logi("updateUserPreferences: AOSP user preference option enabled ");
+            return;
+        }
+
+        //Get num of activated Subs and next available activated sub info.
+        for (SubscriptionInfo subInfo : sil) {
+            if (getUiccProvisionStatus(subInfo.getSimSlotIndex()) == PROVISIONED) {
+                activeCount++;
+                if (mNextActivatedSub == null) mNextActivatedSub = subInfo;
+            }
+        }
+        logd("updateUserPreferences:: active sub count = " + activeCount + " dds = "
+                 + getDefaultDataSubId() + " voice = " + getDefaultVoiceSubId() +
+                 " sms = " + getDefaultSmsSubId());
+
+        // If active SUB count is 1, Always Ask Prompt to be disabled and
+        // preference fallback to the next available SUB.
+        if (activeCount == 1) {
+            setSmsPromptEnabled(false);
+        }
+
+        // TODO Set all prompt options to false ?
+
+        // in Single SIM case or if there are no activated subs available, no need to update. EXIT.
+        if ((mNextActivatedSub == null) || (getActiveSubInfoCountMax() == 1)) return;
+
+        handleDataPreference(mNextActivatedSub.getSubscriptionId());
+
+        if (!isSubProvisioned(getDefaultSmsSubId())) {
+            setDefaultSmsSubId(mNextActivatedSub.getSubscriptionId());
+        }
+        if (!isSubProvisioned(getDefaultVoiceSubId())) {
+            setDefaultVoiceSubId(mNextActivatedSub.getSubscriptionId());
+        }
+
+        // voice preference is handled in such a way that
+        // 1. Whenever current Sub is deactivated or removed It fall backs to
+        //    next available Sub.
+        // 2. When device is flashed for the first time, initial voice preference
+        //    would be set to always ask.
+        if (!isNonSimAccountFound() && activeCount == 1) {
+            final int subId = mNextActivatedSub.getSubscriptionId();
+            PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(subId);
+            logi("set default phoneaccount to  " + subId);
+            mTelecomManager.setUserSelectedOutgoingPhoneAccount(phoneAccountHandle);
+        }
+        if (!isSubProvisioned(mDefaultFallbackSubId)) {
+            setDefaultFallbackSubId(mNextActivatedSub.getSubscriptionId(),
+                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+        }
+
+        notifySubscriptionInfoChanged();
+        logd("updateUserPreferences: after currentDds = " + getDefaultDataSubId() + " voice = " +
+                 getDefaultVoiceSubId() + " sms = " + getDefaultSmsSubId());
+    }
+
+    protected void handleDataPreference(int nextActiveSubId) {
+        int userPrefDataSubId = getUserPrefDataSubIdFromDB();
+        int currentDataSubId = getDefaultDataSubId();
+
+        List<SubscriptionInfo> subInfoList =
+                getActiveSubscriptionInfoList(mContext.getOpPackageName());
+        if (subInfoList == null) {
+            return;
+        }
+        boolean userPrefSubValid = false;
+        for (SubscriptionInfo subInfo : subInfoList) {
+            if (subInfo.getSubscriptionId() == userPrefDataSubId) {
+                userPrefSubValid = true;
+            }
+        }
+        logd("havePrefSub = " + userPrefSubValid + " user pref subId = "
+                 + userPrefDataSubId + " current dds " + currentDataSubId
+                 + " next active subId " + nextActiveSubId);
+
+        // If earlier user selected DDS is now available, set that as DDS subId.
+        if (userPrefSubValid && isSubProvisioned(userPrefDataSubId) &&
+                 (currentDataSubId != userPrefDataSubId)) {
+            setDefaultDataSubId(userPrefDataSubId);
+        } else if (!isSubProvisioned(currentDataSubId)) {
+            setDefaultDataSubId(nextActiveSubId);
+        }
+
+    }
+
+    protected int getUiccProvisionStatus(int slotId) {
+        // FIXME use valid SIM provision value
+        return PROVISIONED; 
+    }
+
+    // This method returns true if subId and corresponding slotId is in valid
+    // range and the Uicc card corresponds to this slot is provisioned.
+    protected boolean isSubProvisioned(int subId) {
+        boolean isSubIdUsable = SubscriptionManager.isUsableSubIdValue(subId);
+
+        if (isSubIdUsable) {
+            int slotId = getSlotIndex(subId);
+            if (!SubscriptionManager.isValidSlotIndex(slotId)) {
+                loge(" Invalid slotId " + slotId + " or subId = " + subId);
+                isSubIdUsable = false;
+            } else {
+                if (getUiccProvisionStatus(slotId) != PROVISIONED) {
+                    isSubIdUsable = false;
+                }
+                loge("isSubProvisioned, state = " + isSubIdUsable + " subId = " + subId);
+            }
+        }
+        return isSubIdUsable;
+    }
+
+    /* Returns User SMS Prompt property,  enabled or not */
+    public boolean isSmsPromptEnabled() {
+        boolean prompt = false;
+        int value = 0;
+        try {
+            value = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.MULTI_SIM_SMS_PROMPT);
+        } catch (SettingNotFoundException snfe) {
+            loge("Settings Exception Reading Dual Sim SMS Prompt Values");
+        }
+        prompt = (value == 0) ? false : true ;
+        if (VDBG) logd("SMS Prompt option:" + prompt);
+
+       return prompt;
+    }
+
+    /*Sets User SMS Prompt property,  enable or not */
+    public void setSmsPromptEnabled(boolean enabled) {
+        enforceModifyPhoneState("setSMSPromptEnabled");
+        int value = (enabled == false) ? 0 : 1;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.MULTI_SIM_SMS_PROMPT, value);
+        logi("setSMSPromptOption to " + enabled);
+    }
+
+    protected boolean isNonSimAccountFound() {
+        final Iterator<PhoneAccountHandle> phoneAccounts =
+                mTelecomManager.getCallCapablePhoneAccounts().listIterator();
+
+        while (phoneAccounts.hasNext()) {
+            final PhoneAccountHandle phoneAccountHandle = phoneAccounts.next();
+            final PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(phoneAccountHandle);
+            if (mTelephonyManager.getSubIdForPhoneAccount(phoneAccount) ==
+                            SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                logi("Other than SIM account found. ");
+                return true;
+            }
+        }
+        logi("Other than SIM account not found ");
+        return false;
+    }
+
+    protected PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) {
+        final Iterator<PhoneAccountHandle> phoneAccounts =
+                mTelecomManager.getCallCapablePhoneAccounts().listIterator();
+
+        while (phoneAccounts.hasNext()) {
+            final PhoneAccountHandle phoneAccountHandle = phoneAccounts.next();
+            final PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(phoneAccountHandle);
+            if (subId == mTelephonyManager.getSubIdForPhoneAccount(phoneAccount)) {
+                return phoneAccountHandle;
+            }
+        }
+
+        return null;
+    }
+
+    protected int getUserPrefDataSubIdFromDB() {
+        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                SETTING_USER_PREF_DATA_SUB, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    private void logd(String string) {
+        if (DBG) Rlog.d(LOG_TAG, string);
+    }
+
+    private void logi(String string) {
+        Rlog.i(LOG_TAG, string);
+    }
+
+    private void loge(String string) {
+        Rlog.e(LOG_TAG, string);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java b/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java
new file mode 100644
index 0000000..6adc1ef
--- /dev/null
+++ b/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.vendor.dataconnection;
+
+import android.telephony.AccessNetworkConstants;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.dataconnection.DcTracker;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.uicc.IccRecords;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+public class VendorDcTracker extends DcTracker {
+    private String LOG_TAG = "VendorDCT";
+    private static final boolean DBG = true;
+    private HashSet<String> mIccidSet = new HashSet<String>();
+    private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+
+    // Constructor
+    public VendorDcTracker(Phone phone, int transportType) {
+        super(phone, transportType);
+        mTransportType = transportType;
+        LOG_TAG = LOG_TAG + "-" +
+                ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) ? "C" : "I");
+        if (DBG) log(LOG_TAG + ".constructor");
+        fillIccIdSet();
+    }
+
+    protected boolean isRecordsLoaded() {
+        boolean recordsLoaded = false;
+
+        IccRecords r = mIccRecords.get();
+        if (r != null) {
+            recordsLoaded = r.getRecordsLoaded();
+        }
+
+        return recordsLoaded;
+    }
+
+    @Override
+    protected void onRecordsLoadedOrSubIdChanged() {
+        if (DBG) log("onRecordsLoaded: createAllApnList");
+        // Just support auto attach for WWAN only
+        if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+            mAutoAttachOnCreationConfig = mPhone.getContext().getResources()
+                    .getBoolean(com.android.internal.R.bool.config_auto_attach_data_on_creation);
+        }
+
+        createAllApnList();
+        setDataProfilesAsNeeded();
+        // Send initial attach apn only if sim records are loaded
+        if (isRecordsLoaded()) {
+            setInitialAttachApn();
+        }
+        mPhone.notifyAllActiveDataConnections();
+        setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS);
+    }
+
+    @Override
+    protected boolean allowInitialAttachForOperator() {
+        IccRecords r = mIccRecords.get();
+        String iccId = (r != null) ? r.getIccId() : "";
+        if (iccId != null) {
+            Iterator<String> itr = mIccidSet.iterator();
+            while (itr.hasNext()) {
+                if (iccId.contains(itr.next())) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // Support added to allow initial attach request with only default for a Carrier
+    protected void fillIccIdSet() {
+        mIccidSet.add("8991840");
+        mIccidSet.add("8991854");
+        mIccidSet.add("8991855");
+        mIccidSet.add("8991856");
+        mIccidSet.add("8991857");
+        mIccidSet.add("8991858");
+        mIccidSet.add("8991859");
+        mIccidSet.add("899186");
+        mIccidSet.add("8991870");
+        mIccidSet.add("8991871");
+        mIccidSet.add("8991872");
+        mIccidSet.add("8991873");
+        mIccidSet.add("8991874");
+    }
+
+    @Override
+    protected void log(String s) {
+        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
+    }
+}
diff --git a/tests/telephonytests/Android.bp b/tests/telephonytests/Android.bp
index 4690c89..eba61c8 100644
--- a/tests/telephonytests/Android.bp
+++ b/tests/telephonytests/Android.bp
@@ -16,6 +16,7 @@
         "frameworks-base-testutils",
         "guava",
         "mockito-target-minus-junit4",
+        "net-tests-utils",
         "platform-test-annotations",
         "services.core",
         "services.net",
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index 1fad90f..10b31a5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 
+import android.os.Message;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -81,4 +82,15 @@
         assertNotNull(mCarrierServiceBindHelper.mBindings.get(0));
         assertNotNull(mCarrierServiceBindHelper.mLastSimState.get(0));
     }
+
+    @Test
+    public void testUnbindWhenNotBound() throws Exception {
+        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+
+        // Try unbinding without binding and make sure we don't throw an Exception
+        mCarrierServiceBindHelper.mHandler.handleMessage(
+                Message.obtain(mCarrierServiceBindHelper.mHandler,
+                        CarrierServiceBindHelper.EVENT_PERFORM_IMMEDIATE_UNBIND,
+                        new Integer(0)));
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
index 8246094..9030124 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
@@ -15,9 +15,8 @@
  */
 package com.android.internal.telephony;
 
-import static com.android.internal.telephony.TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE;
-import static com.android.internal.telephony.TelephonyIntents
-        .ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED;
+import static android.telephony.TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE;
+import static android.telephony.TelephonyManager.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyLong;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
old mode 100644
new mode 100755
index 5e2affb..9986cfc
--- a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
@@ -70,6 +70,13 @@
         public void deflect(String number) throws CallStateException {}
 
         @Override
+        public void transfer(String number, boolean isConfirmationRequired)
+                throws CallStateException {}
+
+        @Override
+        public void consultativeTransfer(Connection other) throws CallStateException {}
+
+        @Override
         public void hangup() throws CallStateException {}
 
         @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
index 19bf186..d9f5dfb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
@@ -136,19 +136,24 @@
     @SmallTest
     public void testUpdateOperatorNumericSync() throws Exception {
         mLocaleTracker.updateOperatorNumeric(US_MCC + FAKE_MNC);
-        assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
-        verifyCountryCodeNotified(new String[]{US_COUNTRY_CODE});
+        // Because the service state is in APM, the country ISO should be set empty.
+        assertEquals(COUNTRY_CODE_UNAVAILABLE, mLocaleTracker.getCurrentCountry());
     }
 
     @Test
     @SmallTest
     public void testNoSim() throws Exception {
+        // Set the state as STATE_OUT_OF_SERVICE. This will trigger an country change to US.
+        sendServiceState(ServiceState.STATE_OUT_OF_SERVICE);
+        assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
+        verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE});
+
         // updateOperatorNumeric("") will not trigger an instantaneous country change
         mLocaleTracker.updateOperatorNumeric("");
         sendGsmCellInfo();
         sendServiceState(ServiceState.STATE_EMERGENCY_ONLY);
         assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
-        verifyCountryCodeNotified(new String[]{US_COUNTRY_CODE});
+        verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE});
         assertTrue(mLocaleTracker.isTracking());
     }
 
@@ -178,6 +183,13 @@
         verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE});
         sendServiceState(ServiceState.STATE_POWER_OFF);
         assertFalse(mLocaleTracker.isTracking());
+
+        // updateOperatorNumeric("") will trigger a country change in APM
+        mLocaleTracker.updateOperatorNumeric("");
+        processAllMessages();
+        assertEquals(COUNTRY_CODE_UNAVAILABLE, mLocaleTracker.getCurrentCountry());
+        verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE,
+                COUNTRY_CODE_UNAVAILABLE});
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java b/tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java
index 7499a7a..ddb99d9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java
@@ -19,7 +19,8 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.HandlerThread;
 import android.os.Looper;
-import android.telephony.Rlog;
+
+import com.android.telephony.Rlog;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
index 79140e4..30833e3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
@@ -33,7 +33,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
 import android.icu.util.TimeZone;
 import android.os.TimestampedValue;
 import android.timezone.CountryTimeZones.OffsetResult;
@@ -95,7 +95,7 @@
                 .nitzReceived(nitzSignal);
 
         // Country + NITZ is enough for both time + time zone detection.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedTimeSuggestion, scenario.getTimeZoneId());
@@ -156,7 +156,7 @@
                 .networkAvailable();
 
         script.nitzReceived(nitzSignal);
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -189,7 +189,7 @@
                 .networkAvailable();
 
         script.nitzReceived(nitzSignal);
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -215,7 +215,7 @@
                 .nitzReceived(nitzSignal);
 
         // Country + NITZ is enough for both time + time zone detection.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedTimeSuggestion, scenario.getTimeZoneId());
@@ -249,7 +249,7 @@
             script.nitzReceived(nitzSignal);
 
             // Country + NITZ is enough for both time + time zone detection.
-            PhoneTimeSuggestion expectedTimeSuggestion =
+            TelephonyTimeSuggestion expectedTimeSuggestion =
                     createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
             script.verifyTimeSuggestedAndZoneSetAndReset(
                     expectedTimeSuggestion, scenario.getTimeZoneId());
@@ -316,7 +316,7 @@
             script.nitzReceived(nitzSignal);
 
             // Country + NITZ is enough for both time + time zone detection.
-            PhoneTimeSuggestion expectedTimeSuggestion =
+            TelephonyTimeSuggestion expectedTimeSuggestion =
                     createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
             script.verifyTimeSuggestedAndZoneSetAndReset(
                     expectedTimeSuggestion, scenario.getTimeZoneId());
@@ -376,7 +376,7 @@
                 .verifyNothingWasSetAndReset()
                 .nitzReceived(nitzSignal);
         // Time zone detection is disabled, but time should be suggested from NITZ.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -402,7 +402,7 @@
                 .verifyNothingWasSetAndReset()
                 .nitzReceived(nitzSignal);
         // Time zone detection is disabled, but time should be suggested from NITZ.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -427,7 +427,7 @@
         script.nitzReceived(nitzSignal);
 
         // The NITZ alone isn't enough to detect a time zone.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -461,7 +461,7 @@
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
         script.nitzReceived(nitzSignal);
         // The NITZ alone isn't enough to detect a time zone.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -498,7 +498,7 @@
         script.nitzReceived(goodNitzSignal);
 
         // The NITZ alone isn't enough to detect a time zone.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), goodNitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -544,7 +544,7 @@
 
         // The time will be suggested from the NITZ signal.
         // The combination of NITZ + country will cause the time zone to be set.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), goodNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedTimeSuggestion, scenario.getTimeZoneId());
@@ -580,7 +580,7 @@
 
         // The NITZ alone isn't enough to detect a time zone, but there isn't enough
         // information to work out it is bogus.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), badNitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -633,7 +633,7 @@
         script.nitzReceived(badNitzSignal);
 
         // The NITZ should be detected as bogus so only the time will be suggested.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), badNitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -667,7 +667,7 @@
         script.nitzReceived(badNitzSignal);
         // The NITZ alone isn't enough to detect a time zone, but there isn't enough
         // information to work out its bogus.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), badNitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -723,7 +723,7 @@
         script.nitzReceived(badNitzSignal);
 
         // The NITZ should be detected as bogus so only the time will be suggested.
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), badNitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -760,7 +760,7 @@
         // Simulate receiving the emulator NITZ signal.
         script.nitzReceived(emulatorNitzSignal);
 
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), emulatorNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(expectedTimeSuggestion, emulatorTimeZoneId);
 
@@ -794,7 +794,7 @@
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
         script.nitzReceived(nitzSignal);
 
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(expectedTimeSuggestion, expectedZoneId);
 
@@ -820,7 +820,7 @@
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
         script.nitzReceived(nitzSignal);
 
-        PhoneTimeSuggestion expectedTimeSuggestion =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), nitzSignal);
         script.verifyOnlyTimeWasSuggestedAndReset(expectedTimeSuggestion);
 
@@ -857,7 +857,7 @@
         script.nitzReceived(preflightNitzSignal)
                 .countryReceived(scenario.getNetworkCountryIsoCode());
 
-        PhoneTimeSuggestion expectedPreFlightTimeSuggestion =
+        TelephonyTimeSuggestion expectedPreFlightTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), preflightNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedPreFlightTimeSuggestion, scenario.getTimeZoneId());
@@ -893,7 +893,8 @@
         assertNull(mNitzStateMachine.getSavedTimeZoneId());
 
         // Verify there's no time zone opinion by toggling auto time zone off and on.
-        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
+        TelephonyTimeSuggestion emptyTimeSuggestion =
+                createEmptyTimeSuggestion(mPhone.getPhoneId());
         script.toggleTimeZoneDetectionEnabled(false)
                 .verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion)
                 .toggleTimeZoneDetectionEnabled(true)
@@ -936,7 +937,7 @@
         script.countryReceived(scenario.getNetworkCountryIsoCode())
                 .nitzReceived(postFlightNitzSignal);
 
-        PhoneTimeSuggestion expectedPostFlightTimeSuggestion =
+        TelephonyTimeSuggestion expectedPostFlightTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), postFlightNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(expectedPostFlightTimeSuggestion,
                         scenario.getTimeZoneId());
@@ -968,7 +969,7 @@
                 .nitzReceived(initialNitzSignal)
                 .countryReceived(scenario.getNetworkCountryIsoCode());
 
-        PhoneTimeSuggestion expectedInitialTimeSuggestion =
+        TelephonyTimeSuggestion expectedInitialTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), initialNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedInitialTimeSuggestion, scenario.getTimeZoneId());
@@ -993,7 +994,8 @@
         // having an opinion about time zone.
         script.networkUnavailable();
 
-        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
+        TelephonyTimeSuggestion emptyTimeSuggestion =
+                createEmptyTimeSuggestion(mPhone.getPhoneId());
         script.verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion);
 
         // Simulate the passage of time and update the device realtime clock.
@@ -1039,7 +1041,7 @@
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
         script.nitzReceived(finalNitzSignal);
 
-        PhoneTimeSuggestion expectedFinalTimeSuggestion =
+        TelephonyTimeSuggestion expectedFinalTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), finalNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(expectedFinalTimeSuggestion,
                         scenario.getTimeZoneId());
@@ -1071,7 +1073,7 @@
                 .nitzReceived(initialNitzSignal)
                 .countryReceived(scenario.getNetworkCountryIsoCode());
 
-        PhoneTimeSuggestion expectedInitialTimeSuggestion =
+        TelephonyTimeSuggestion expectedInitialTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), initialNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(
                 expectedInitialTimeSuggestion, scenario.getTimeZoneId());
@@ -1097,7 +1099,8 @@
         // is sufficient to detect time zone in the UK.
         script.networkUnavailable();
 
-        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
+        TelephonyTimeSuggestion emptyTimeSuggestion =
+                createEmptyTimeSuggestion(mPhone.getPhoneId());
         script.verifyTimeSuggestedAndZoneSetAndReset(emptyTimeSuggestion, scenario.getTimeZoneId());
 
         // Simulate the passage of time and update the device realtime clock.
@@ -1143,7 +1146,7 @@
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
         script.nitzReceived(finalNitzSignal);
 
-        PhoneTimeSuggestion expectedFinalTimeSuggestion =
+        TelephonyTimeSuggestion expectedFinalTimeSuggestion =
                 createTimeSuggestionFromNitzSignal(mPhone.getPhoneId(), finalNitzSignal);
         script.verifyTimeSuggestedAndZoneSetAndReset(expectedFinalTimeSuggestion,
                         scenario.getTimeZoneId());
@@ -1253,7 +1256,7 @@
             return this;
         }
 
-        Script verifyOnlyTimeWasSuggestedAndReset(PhoneTimeSuggestion timeSuggestion) {
+        Script verifyOnlyTimeWasSuggestedAndReset(TelephonyTimeSuggestion timeSuggestion) {
             verifyTimeZoneWasNotSet();
             verifyTimeWasSuggested(timeSuggestion);
             commitStateChanges();
@@ -1261,7 +1264,7 @@
         }
 
         Script verifyTimeSuggestedAndZoneSetAndReset(
-                PhoneTimeSuggestion timeSuggestion, String timeZoneId) {
+                TelephonyTimeSuggestion timeSuggestion, String timeZoneId) {
             verifyTimeZoneWasSet(timeZoneId);
             verifyTimeWasSuggested(timeSuggestion);
             commitStateChanges();
@@ -1281,9 +1284,9 @@
             mFakeTimeServiceHelper.deviceTimeZone.assertLatestEquals(timeZoneId);
         }
 
-        private void verifyTimeWasSuggested(PhoneTimeSuggestion phoneTimeSuggestion) {
+        private void verifyTimeWasSuggested(TelephonyTimeSuggestion timeSuggestion) {
             mFakeTimeServiceHelper.suggestedTime.assertChangeCount(1);
-            mFakeTimeServiceHelper.suggestedTime.assertLatestEquals(phoneTimeSuggestion);
+            mFakeTimeServiceHelper.suggestedTime.assertLatestEquals(timeSuggestion);
         }
 
         private void commitStateChanges() {
@@ -1349,7 +1352,7 @@
 
         // State we want to track.
         public TestState<String> deviceTimeZone = new TestState<>();
-        public TestState<PhoneTimeSuggestion> suggestedTime = new TestState<>();
+        public TestState<TelephonyTimeSuggestion> suggestedTime = new TestState<>();
 
         FakeTimeServiceHelper(FakeDeviceState fakeDeviceState) {
             mFakeDeviceState = fakeDeviceState;
@@ -1376,11 +1379,11 @@
         }
 
         @Override
-        public void suggestDeviceTime(PhoneTimeSuggestion phoneTimeSuggestion) {
-            suggestedTime.set(phoneTimeSuggestion);
-            if (phoneTimeSuggestion.getUtcTime() != null) {
+        public void suggestDeviceTime(TelephonyTimeSuggestion timeSuggestion) {
+            suggestedTime.set(timeSuggestion);
+            if (timeSuggestion.getUtcTime() != null) {
                 // The fake time service just uses the latest suggestion.
-                mFakeDeviceState.currentTimeMillis = phoneTimeSuggestion.getUtcTime().getValue();
+                mFakeDeviceState.currentTimeMillis = timeSuggestion.getUtcTime().getValue();
             }
         }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
index 1affa25..45af1c0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
@@ -18,8 +18,8 @@
 
 import static org.junit.Assert.fail;
 
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.icu.util.Calendar;
 import android.icu.util.GregorianCalendar;
 import android.icu.util.TimeZone;
@@ -271,21 +271,21 @@
         return cal.getTimeInMillis();
     }
 
-    public static PhoneTimeZoneSuggestion createEmptyTimeZoneSuggestion(int phoneId) {
-        return new PhoneTimeZoneSuggestion.Builder(phoneId)
+    public static TelephonyTimeZoneSuggestion createEmptyTimeZoneSuggestion(int slotIndex) {
+        return new TelephonyTimeZoneSuggestion.Builder(slotIndex)
                 .addDebugInfo("Test")
                 .build();
     }
 
-    public static PhoneTimeSuggestion createEmptyTimeSuggestion(int phoneId) {
-        return new PhoneTimeSuggestion.Builder(phoneId)
+    public static TelephonyTimeSuggestion createEmptyTimeSuggestion(int slotIndex) {
+        return new TelephonyTimeSuggestion.Builder(slotIndex)
                 .addDebugInfo("Test")
                 .build();
     }
 
-    public static PhoneTimeSuggestion createTimeSuggestionFromNitzSignal(
-            int phoneId, TimestampedValue<NitzData> nitzSignal) {
-        return new PhoneTimeSuggestion.Builder(phoneId)
+    public static TelephonyTimeSuggestion createTimeSuggestionFromNitzSignal(
+            int slotIndex, TimestampedValue<NitzData> nitzSignal) {
+        return new TelephonyTimeSuggestion.Builder(slotIndex)
                 .setUtcTime(createTimeSignalFromNitzSignal(nitzSignal))
                 .addDebugInfo("Test")
                 .build();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 1e9a289..24c9351 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -179,6 +179,8 @@
     @Mock
     private ConnectivityManager mConnectionManager;
     @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
     private IRadio mRadioProxy;
     @Mock
     private IOemHook mOemHookProxy;
@@ -272,6 +274,9 @@
             .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
         doReturn(mConnectionManager).when(context)
             .getSystemService(Context.CONNECTIVITY_SERVICE);
+        doReturn(mTelephonyManager).when(context)
+                .getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(true).when(mTelephonyManager).isDataCapable();
         PowerManager powerManager = new PowerManager(context, mock(IPowerManager.class),
                 new Handler(Looper.myLooper()));
         doReturn(powerManager).when(context).getSystemService(Context.POWER_SERVICE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
index f9ff2b7..f738a37 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
@@ -43,7 +43,6 @@
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.NetworkScanRequest;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SignalThresholdInfo;
@@ -71,6 +70,7 @@
 import com.android.internal.telephony.uicc.IccCardStatus;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -79,7 +79,7 @@
 
 public class SimulatedCommands extends BaseCommands
         implements CommandsInterface, SimulatedRadioControl {
-    private final static String LOG_TAG = "SimulatedCommands";
+    private static final String LOG_TAG = "SimulatedCommands";
 
     private enum SimLockState {
         NONE,
@@ -95,21 +95,27 @@
         SIM_PERM_LOCKED
     }
 
-    private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
-    public final static String DEFAULT_SIM_PIN_CODE = "1234";
-    private final static String SIM_PUK_CODE = "12345678";
-    private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE;
-    public final static String DEFAULT_SIM_PIN2_CODE = "5678";
-    private final static String SIM_PUK2_CODE = "87654321";
-    public final static String FAKE_LONG_NAME = "Fake long name";
-    public final static String FAKE_SHORT_NAME = "Fake short name";
-    public final static String FAKE_MCC_MNC = "310260";
-    public final static String FAKE_IMEI = "012345678901234";
-    public final static String FAKE_IMEISV = "99";
-    public final static String FAKE_ESN = "1234";
-    public final static String FAKE_MEID = "1234";
-    public final static int DEFAULT_PIN1_ATTEMPT = 5;
-    public final static int DEFAULT_PIN2_ATTEMPT = 5;
+    private static final SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
+    public static final String DEFAULT_SIM_PIN_CODE = "1234";
+    private static final String SIM_PUK_CODE = "12345678";
+    private static final SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE;
+    public static final String DEFAULT_SIM_PIN2_CODE = "5678";
+    private static final String SIM_PUK2_CODE = "87654321";
+    public static final String FAKE_LONG_NAME = "Fake long name";
+    public static final String FAKE_SHORT_NAME = "Fake short name";
+    public static final String FAKE_MCC_MNC = "310260";
+    public static final String FAKE_IMEI = "012345678901234";
+    public static final String FAKE_IMEISV = "99";
+    public static final String FAKE_ESN = "1234";
+    public static final String FAKE_MEID = "1234";
+    public static final int DEFAULT_PIN1_ATTEMPT = 5;
+    public static final int DEFAULT_PIN2_ATTEMPT = 5;
+    public static final int ICC_AUTHENTICATION_MODE_DEFAULT = 0;
+    public static final int ICC_AUTHENTICATION_MODE_NULL = 1;
+    public static final int ICC_AUTHENTICATION_MODE_TIMEOUT = 2;
+    // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not
+    // arrive and returning null to the callers.
+    public static final  long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500;
 
     private String mImei;
     private String mImeiSv;
@@ -162,6 +168,8 @@
     private SetupDataCallResult mSetupDataCallResult;
     private boolean mIsRadioPowerFailResponse = false;
 
+    // mode for Icc Sim Authentication
+    private int mAuthenticationMode;
     //***** Constructor
     public
     SimulatedCommands() {
@@ -179,6 +187,7 @@
         mSimFdnEnabledState = INITIAL_FDN_STATE;
         mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE);
         mPin2Code = DEFAULT_SIM_PIN2_CODE;
+        mAuthenticationMode = ICC_AUTHENTICATION_MODE_DEFAULT;
     }
 
     public void dispose() {
@@ -1896,7 +1905,38 @@
 
     @Override
     public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) {
-        unimplemented(response);
+        switch (mAuthenticationMode) {
+            case ICC_AUTHENTICATION_MODE_TIMEOUT:
+                break;
+
+            case ICC_AUTHENTICATION_MODE_NULL:
+                sendMessageResponse(response, null);
+                break;
+
+            default:
+                if (data == null || data.length() == 0) {
+                    sendMessageResponse(response,  null);
+                } else {
+                    sendMessageResponse(response, new IccIoResult(0, 0, (byte[]) data.getBytes()));
+                }
+                break;
+        }
+    }
+
+    /**
+     * Helper function to send response msg
+     * @param msg Response message to be sent
+     * @param ret Return object to be included in the response message
+     */
+    private void sendMessageResponse(Message msg, Object ret) {
+        if (msg != null) {
+            AsyncResult.forMessage(msg, ret, null);
+            msg.sendToTarget();
+        }
+    }
+
+    public void setAuthenticationMode(int authenticationMode) {
+        mAuthenticationMode = authenticationMode;
     }
 
     @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java
index 6d4f385..53fd987 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java
@@ -21,10 +21,10 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
 
 import com.android.internal.telephony.ATParseEx;
 import com.android.internal.telephony.DriverCall;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
index 32dfef8..bd963ef 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -16,18 +16,11 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
-import android.telephony.Rlog;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
-import com.android.internal.telephony.SmsConstants;
-
-import java.util.Random;
+import com.android.telephony.Rlog;
 
 /**
  * Test cases to verify selection of the optimal 7 bit encoding tables
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
index c6d0cf8..0399245 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.times;
@@ -1069,18 +1068,6 @@
                 UiccSlotInfo.CARD_STATE_INFO_PRESENT, logicalSlotIndex, true, true);
     }
 
-    // TODO: Move this test once SubscriptionManager.setAlwaysAllowMmsData is moved to telephony
-    // manager.
-    @Test
-    @SmallTest
-    public void testSetAlwaysAllowMmsData() throws Exception {
-        mSubscriptionControllerUT.setAlwaysAllowMmsData(0, true);
-        verify(mDataEnabledSettings).setAlwaysAllowMmsData(eq(true));
-        clearInvocations(mDataEnabledSettings);
-        mSubscriptionControllerUT.setAlwaysAllowMmsData(0, false);
-        verify(mDataEnabledSettings).setAlwaysAllowMmsData(eq(false));
-    }
-
     @Test
     @SmallTest
     public void testNameSourcePriority() throws Exception {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index d4946c6..881d454 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -52,6 +52,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 @RunWith(AndroidTestingRunner.class)
@@ -65,6 +66,48 @@
     private int mActiveSubId;
     private int mSrvccState = -1;
     private int mRadioPowerState = RADIO_POWER_UNAVAILABLE;
+    // All events contribute to TelephonyRegistry.ENFORCE_PHONE_STATE_PERMISSION_MASK
+    private static final Map<Integer, String> READ_PHONE_STATE_EVENTS = Map.of(
+            PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR,
+            "PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR",
+            PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR,
+            "PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR",
+            PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST,
+            "PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST",
+            PhoneStateListener.LISTEN_REGISTRATION_FAILURE,
+            "PhoneStateListener.LISTEN_REGISTRATION_FAILURE");
+
+    // All events contribute to TelephonyRegistry.PRECISE_PHONE_STATE_PERMISSION_MASK
+    private static final Map<Integer, String> READ_PRECISE_PHONE_STATE_EVENTS = Map.of(
+            PhoneStateListener.LISTEN_PRECISE_CALL_STATE,
+            "PhoneStateListener.LISTEN_PRECISE_CALL_STATE",
+            PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE,
+            "PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE",
+            PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES,
+            "PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES",
+            PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED,
+            "PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED",
+            PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES,
+            "PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES");
+
+    // All events contribute to TelephonyRegistry.PREVILEGED_PHONE_STATE_PERMISSION_MASK
+    // TODO: b/148021947 will create the permission group with PREVILIGED_STATE_PERMISSION_MASK
+    private static final Map<Integer, String> READ_PREVILIGED_PHONE_STATE_EVENTS = Map.of(
+            PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED,
+            "PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED",
+            PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT,
+            "PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT",
+            PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED,
+            "PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED",
+            PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE,
+            "PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE");
+
+    // All events contribute to TelephonyRegistry.READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK
+    private static final Map<Integer, String> READ_ACTIVE_EMERGENCY_SESSION_EVENTS = Map.of(
+            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL,
+            "PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL",
+            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS,
+            "PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS");
 
     public class PhoneStateListenerWrapper extends PhoneStateListener {
         // This class isn't mockable to get invocation counts because the IBinder is null and
@@ -294,38 +337,81 @@
     }
 
     /**
-     * Validate that SecuirtyException is thrown when we try to listen without permission
-     * READ_PRECISE_PHONE_STATE.
+     * Test listen to events that require READ_PHONE_STATE permission.
      */
     @Test
-    @SmallTest
-    public void testListenWithoutPermission() {
+    public void testReadPhoneStatePermission() {
         // Clear all permission grants for test.
         mContextFixture.addCallingOrSelfPermission("");
+        for (Map.Entry<Integer, String> entry : READ_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionThrown(entry.getKey(), entry.getValue());
+        }
 
-        assertThrowSecurityExceptionWhenListenWithoutPermission(
-                PhoneStateListener.LISTEN_PRECISE_CALL_STATE,
-                "LISTEN_PRECISE_CALL_STATE");
-
-        assertThrowSecurityExceptionWhenListenWithoutPermission(
-                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE,
-                "LISTEN_PRECISE_DATA_CONNECTION_STATE");
-
-        assertThrowSecurityExceptionWhenListenWithoutPermission(
-                PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES,
-                "LISTEN_CALL_DISCONNECT_CAUSES");
-
-        assertThrowSecurityExceptionWhenListenWithoutPermission(
-                PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED,
-                "LISTEN_CALL_ATTRIBUTES_CHANGED");
-
-        assertThrowSecurityExceptionWhenListenWithoutPermission(
-                PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES,
-                "LISTEN_IMS_CALL_DISCONNECT_CAUSES");
+        // Grant permssion
+        mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE);
+        for (Map.Entry<Integer, String> entry : READ_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionNotThrown(entry.getKey(), entry.getValue());
+        }
     }
 
-    private void assertThrowSecurityExceptionWhenListenWithoutPermission(int event,
-            String eventDesc) {
+    /**
+     * Test listen to events that require READ_PRECISE_PHONE_STATE permission.
+     */
+    @Test
+    public void testReadPrecisePhoneStatePermission() {
+        // Clear all permission grants for test.
+        mContextFixture.addCallingOrSelfPermission("");
+        for (Map.Entry<Integer, String> entry : READ_PRECISE_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionThrown(entry.getKey(), entry.getValue());
+        }
+
+        // Grant permssion
+        mContextFixture.addCallingOrSelfPermission(
+                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
+        for (Map.Entry<Integer, String> entry : READ_PRECISE_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionNotThrown(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Test listen to events that require READ_PRIVILEGED_PHONE_STATE permission.
+     */
+    @Test
+    public void testReadPrivilegedPhoneStatePermission() {
+        // Clear all permission grants for test.
+        mContextFixture.addCallingOrSelfPermission("");
+        for (Map.Entry<Integer, String> entry : READ_PREVILIGED_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionThrown(entry.getKey(), entry.getValue());
+        }
+
+        // Grant permssion
+        mContextFixture.addCallingOrSelfPermission(
+                android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+        for (Map.Entry<Integer, String> entry : READ_PREVILIGED_PHONE_STATE_EVENTS.entrySet()) {
+            assertSecurityExceptionNotThrown(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Test listen to events that require READ_ACTIVE_EMERGENCY_SESSION permission.
+     */
+    @Test
+    public void testReadActiveEmergencySessionPermission() {
+        // Clear all permission grants for test.
+        mContextFixture.addCallingOrSelfPermission("");
+        for (Map.Entry<Integer, String> entry : READ_ACTIVE_EMERGENCY_SESSION_EVENTS.entrySet()) {
+            assertSecurityExceptionThrown(entry.getKey(), entry.getValue());
+        }
+
+        // Grant permssion
+        mContextFixture.addCallingOrSelfPermission(
+                android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION);
+        for (Map.Entry<Integer, String> entry : READ_ACTIVE_EMERGENCY_SESSION_EVENTS.entrySet()) {
+            assertSecurityExceptionNotThrown(entry.getKey(), entry.getValue());
+        }
+    }
+
+    private void assertSecurityExceptionThrown(int event, String eventDesc) {
         try {
             mTelephonyRegistry.listen(mContext.getOpPackageName(),
                     mPhoneStateListener.callback, event, true);
@@ -333,4 +419,13 @@
         } catch (SecurityException expected) {
         }
     }
+
+    private void assertSecurityExceptionNotThrown(int event, String eventDesc) {
+        try {
+            mTelephonyRegistry.listen(mContext.getOpPackageName(),
+                    mPhoneStateListener.callback, event, true);
+        } catch (SecurityException unexpected) {
+            fail("SecurityException thrown when listen " + eventDesc + " with permission");
+        }
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index d3115fe..809f3ec 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -30,6 +30,7 @@
 
 import android.app.ActivityManager;
 import android.app.IActivityManager;
+import android.app.usage.NetworkStatsManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IIntentSender;
@@ -270,6 +271,8 @@
     protected MultiSimSettingController mMultiSimSettingController;
     @Mock
     protected IccCard mIccCard;
+    @Mock
+    protected NetworkStatsManager mStatsManager;
 
     protected ImsCallProfile mImsCallProfile;
     protected TelephonyManager mTelephonyManager;
@@ -575,6 +578,7 @@
         doAnswer((invocation)->Math.max(mTelephonyManager.getActiveModemCount(),
                 mTelephonyManager.getPhoneCount()))
                 .when(mTelephonyManager).getSupportedModemCount();
+        doReturn(mStatsManager).when(mContext).getSystemService(eq(Context.NETWORK_STATS_SERVICE));
 
         //Data
         //Initial state is: userData enabled, provisioned.
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
index 3cbc501..3d707da 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -17,7 +17,6 @@
 package com.android.internal.telephony.cdma;
 
 import android.hardware.radio.V1_0.CdmaSmsMessage;
-import android.telephony.Rlog;
 import android.telephony.SmsCbCmasInfo;
 import android.telephony.SmsCbMessage;
 import android.telephony.cdma.CdmaSmsCbProgramData;
@@ -32,6 +31,7 @@
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.util.BitwiseOutputStream;
+import com.android.telephony.Rlog;
 
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
index 069b08c..0e0f113 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
@@ -337,7 +337,7 @@
         assertEquals(bearerData.depositIndex, 1382);
         assertEquals(bearerData.userResponseCode, 5);
         assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
-        assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+        assertEquals(bearerData.msgCenterTimeStamp.monthOrdinal, 12);
         assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
         assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
         assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
@@ -345,7 +345,7 @@
         assertEquals(bearerData.validityPeriodAbsolute, null);
         assertEquals(bearerData.validityPeriodRelative, 193);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthOrdinal, 6);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
@@ -384,7 +384,7 @@
         assertEquals(bearerData.depositIndex, 1382);
         assertEquals(bearerData.userResponseCode, 5);
         assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
-        assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+        assertEquals(bearerData.msgCenterTimeStamp.monthOrdinal, 12);
         assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
         assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
         assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
@@ -392,7 +392,7 @@
         assertEquals(bearerData.validityPeriodAbsolute, null);
         assertEquals(bearerData.validityPeriodRelative, 61);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthOrdinal, 6);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
         assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 3694b31..851ae35 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -18,8 +18,8 @@
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
-import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
+import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED;
+import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
 
 import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
 import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_ADDRESS;
@@ -646,12 +646,13 @@
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        mDc.onSubscriptionOverride(OVERRIDE_UNMETERED, OVERRIDE_UNMETERED);
+        mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED,
+                SUBSCRIPTION_OVERRIDE_UNMETERED);
 
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        mDc.onSubscriptionOverride(OVERRIDE_UNMETERED, 0);
+        mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED, 0);
 
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
@@ -667,12 +668,13 @@
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        mDc.onSubscriptionOverride(OVERRIDE_CONGESTED, OVERRIDE_CONGESTED);
+        mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED,
+                SUBSCRIPTION_OVERRIDE_CONGESTED);
 
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        mDc.onSubscriptionOverride(OVERRIDE_CONGESTED, 0);
+        mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED, 0);
 
         assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
index a4bc00e..8f7bc4f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
@@ -39,7 +39,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.telephony.AccessNetworkConstants;
-import android.telephony.Rlog;
 import android.telephony.data.ApnSetting;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -52,6 +51,7 @@
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams;
 import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams.HandoverCallback;
+import com.android.telephony.Rlog;
 
 import org.junit.After;
 import org.junit.Before;
@@ -63,7 +63,6 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class TelephonyNetworkFactoryTest extends TelephonyTest {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java.broken b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java.broken
index aa94e0e..16861fa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java.broken
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java.broken
@@ -22,7 +22,7 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
 
 import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.test.SimulatedCommands;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmCellBroadcastHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmCellBroadcastHandlerTest.java
deleted file mode 100644
index 18bc486..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmCellBroadcastHandlerTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import static android.provider.Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.nullable;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.Manifest;
-import android.app.Activity;
-import android.app.AppOpsManager;
-import android.content.BroadcastReceiver;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Telephony;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import com.android.internal.telephony.SmsStorageMonitor;
-import com.android.internal.telephony.TelephonyTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-
-import java.util.List;
-
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class GsmCellBroadcastHandlerTest extends TelephonyTest {
-    @Mock
-    private SmsStorageMonitor mSmsStorageMonitor;
-    @Mock
-    private android.telephony.SmsMessage mSmsMessage;
-    @Mock
-    private SmsMessage mGsmSmsMessage;
-
-    private GsmCellBroadcastHandler mGsmCellBroadcastHandler;
-
-    @Before
-    public void setUp() throws Exception {
-
-        super.setUp(getClass().getSimpleName());
-
-        doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
-        doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
-
-        mGsmCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(
-                mContext, mPhone);
-        monitorTestableLooper(
-                new TestableLooper(mGsmCellBroadcastHandler.getHandler().getLooper()));
-        processAllMessages();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mGsmCellBroadcastHandler = null;
-        super.tearDown();
-    }
-
-    @Test
-    @Ignore
-    public void testBroadcastSms() {
-        mContextFixture.putStringArrayResource(
-                com.android.internal.R.array.config_defaultCellBroadcastReceiverPkgs,
-                new String[]{"fake.cellbroadcastreceiver"});
-
-        Settings.Secure.putString(mContext.getContentResolver(),
-                CMAS_ADDITIONAL_BROADCAST_PKG, "another.fake.pkg");
-        mSimulatedCommands.notifyGsmBroadcastSms(new byte[] {
-                (byte)0xc0, //geographical scope
-                (byte)0x01, //serial number
-                (byte)0x01, //serial number
-                (byte)0x01, //message identifier
-                (byte)0x01, //message identifier
-                (byte)0x01
-        });
-        processAllMessages();
-        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContextFixture.getTestDouble(), times(2)).sendOrderedBroadcastAsUser(
-                intentArgumentCaptor.capture(), eq(UserHandle.ALL),
-                eq(Manifest.permission.RECEIVE_SMS), eq(AppOpsManager.OP_RECEIVE_SMS),
-                nullable(BroadcastReceiver.class), any(Handler.class), eq(Activity.RESULT_OK),
-                eq(null), eq(null));
-
-        List<Intent> intentList = intentArgumentCaptor.getAllValues();
-
-        assertEquals(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION,
-                intentList.get(0).getAction());
-        assertEquals("another.fake.pkg", intentList.get(0).getPackage());
-
-        assertEquals(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION,
-                intentList.get(1).getAction());
-        assertEquals("fake.cellbroadcastreceiver", intentList.get(1).getPackage());
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java
deleted file mode 100644
index 8f61c21..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsCbTest.java
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import android.telephony.Rlog;
-import android.telephony.SmsCbEtwsInfo;
-import android.telephony.SmsCbLocation;
-import android.telephony.SmsCbMessage;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.internal.telephony.uicc.IccUtils;
-
-import org.junit.Test;
-
-import java.util.Random;
-
-/**
- * Test cases for basic SmsCbMessage operations
- */
-public class GsmSmsCbTest extends AndroidTestCase {
-
-    private static final String TAG = "GsmSmsCbTest";
-
-    private static final SmsCbLocation sTestLocation = new SmsCbLocation("94040", 1234, 5678);
-
-    private SmsCbMessage createFromPdu(byte[] pdu) {
-        try {
-            SmsCbHeader header = new SmsCbHeader(pdu);
-            byte[][] pdus = new byte[1][];
-            pdus[0] = pdu;
-            return GsmSmsCbMessage.createSmsCbMessage(getContext(), header, sTestLocation, pdus,
-                    /* slotIndex */ 0);
-        } catch (IllegalArgumentException e) {
-            return null;
-        }
-    }
-
-    private void doTestGeographicalScopeValue(byte[] pdu, byte b, int expectedGs) {
-        pdu[0] = b;
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected geographical scope decoded", expectedGs, msg
-                .getGeographicalScope());
-    }
-
-    @Test @SmallTest
-    public void testCreateNullPdu() {
-        SmsCbMessage msg = createFromPdu(null);
-        assertNull("createFromPdu(byte[] with null pdu should return null", msg);
-    }
-
-    @Test @SmallTest
-    public void testCreateTooShortPdu() {
-        byte[] pdu = new byte[4];
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertNull("createFromPdu(byte[] with too short pdu should return null", msg);
-    }
-
-    @Test @SmallTest
-    public void testGetGeographicalScope() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-
-        doTestGeographicalScopeValue(pdu, (byte)0x00,
-                SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE);
-        doTestGeographicalScopeValue(pdu, (byte)0x40, SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE);
-        doTestGeographicalScopeValue(pdu, (byte)0x80,
-                SmsCbMessage.GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE);
-        doTestGeographicalScopeValue(pdu, (byte)0xC0, SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE);
-    }
-
-    @Test @SmallTest
-    public void testGetGeographicalScopeUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
-                (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
-                (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
-                (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x34
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected geographical scope decoded",
-                SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE, msg.getGeographicalScope());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7Bit() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A GSM default alphabet message with carriage return padding",
-                msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
-                (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
-                (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
-                (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x34
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A GSM default alphabet message with carriage return padding",
-                msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitMultipageUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x40,
-
-                (byte)0x02,
-
-                (byte)0xC6, (byte)0xB4, (byte)0x7C, (byte)0x4E, (byte)0x07, (byte)0xC1,
-                (byte)0xC3, (byte)0xE7, (byte)0xF2, (byte)0xAA, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A,
-                (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34,
-                (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x0A,
-
-                (byte)0xD3, (byte)0xF2, (byte)0xF8, (byte)0xED, (byte)0x26, (byte)0x83,
-                (byte)0xE0, (byte)0xE1, (byte)0x73, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A,
-                (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34,
-                (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x0A
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected multipage 7-bit string decoded",
-                "First page+Second page",
-                msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitFull() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5,
-                (byte)0xB4, (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63,
-                (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40, (byte)0x63,
-                (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3, (byte)0xCB, (byte)0xF2,
-                (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76, (byte)0x9F, (byte)0x59, (byte)0xA0,
-                (byte)0x76, (byte)0x39, (byte)0xEC, (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20,
-                (byte)0x3A, (byte)0xBA, (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73,
-                (byte)0x90, (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4,
-                (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals(
-                "Unexpected 7-bit string decoded",
-                "A GSM default alphabet message being exactly 93 characters long, " +
-                "meaning there is no padding!",
-                msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitFullUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xC4, (byte)0xE5, (byte)0xB4,
-                (byte)0xFB, (byte)0x0C, (byte)0x2A, (byte)0xE3, (byte)0xC3, (byte)0x63,
-                (byte)0x3A, (byte)0x3B, (byte)0x0F, (byte)0xCA, (byte)0xCD, (byte)0x40,
-                (byte)0x63, (byte)0x74, (byte)0x58, (byte)0x1E, (byte)0x1E, (byte)0xD3,
-                (byte)0xCB, (byte)0xF2, (byte)0x39, (byte)0x88, (byte)0xFD, (byte)0x76,
-                (byte)0x9F, (byte)0x59, (byte)0xA0, (byte)0x76, (byte)0x39, (byte)0xEC,
-                (byte)0x4E, (byte)0xBB, (byte)0xCF, (byte)0x20, (byte)0x3A, (byte)0xBA,
-                (byte)0x2C, (byte)0x2F, (byte)0x83, (byte)0xD2, (byte)0x73, (byte)0x90,
-                (byte)0xFB, (byte)0x0D, (byte)0x82, (byte)0x87, (byte)0xC9, (byte)0xE4,
-                (byte)0xB4, (byte)0xFB, (byte)0x1C, (byte)0x02,
-
-                (byte)0x52
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals(
-                "Unexpected 7-bit string decoded",
-                "A GSM default alphabet message being exactly 93 characters long, " +
-                "meaning there is no padding!",
-                msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitWithLanguage() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x04, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A GSM default alphabet message with carriage return padding",
-                msg.getMessageBody());
-
-        assertEquals("Unexpected language indicator decoded", "es", msg.getLanguageCode());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitWithLanguageInBody() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x10, (byte)0x11, (byte)0x73,
-                (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E, (byte)0x9B, (byte)0x20,
-                (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE, (byte)0xB3, (byte)0xE9, (byte)0xA0,
-                (byte)0x30, (byte)0x1B, (byte)0x8E, (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74,
-                (byte)0x50, (byte)0xBB, (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65,
-                (byte)0xD0, (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61,
-                (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41, (byte)0xF2,
-                (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83, (byte)0xE0, (byte)0x61,
-                (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E, (byte)0x37, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A GSM default alphabet message with carriage return padding",
-                msg.getMessageBody());
-
-        assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody7BitWithLanguageInBodyUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x10,
-
-                (byte)0x01,
-
-                (byte)0x73, (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E,
-                (byte)0x9B, (byte)0x20, (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE,
-                (byte)0xB3, (byte)0xE9, (byte)0xA0, (byte)0x30, (byte)0x1B, (byte)0x8E,
-                (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74, (byte)0x50, (byte)0xBB,
-                (byte)0x3C, (byte)0x9F, (byte)0x87, (byte)0xCF, (byte)0x65, (byte)0xD0,
-                (byte)0x3D, (byte)0x4D, (byte)0x47, (byte)0x83, (byte)0xC6, (byte)0x61,
-                (byte)0xB9, (byte)0x3C, (byte)0x1D, (byte)0x3E, (byte)0x97, (byte)0x41,
-                (byte)0xF2, (byte)0x32, (byte)0xBD, (byte)0x2E, (byte)0x77, (byte)0x83,
-                (byte)0xE0, (byte)0x61, (byte)0x32, (byte)0x39, (byte)0xED, (byte)0x3E,
-                (byte)0x37, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x37
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A GSM default alphabet message with carriage return padding",
-                msg.getMessageBody());
-
-        assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBody8Bit() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x44, (byte)0x11, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x41,
-                (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("8-bit message body should be empty", "", msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBodyUcs2() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x48, (byte)0x11, (byte)0x00,
-                (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43,
-                (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00,
-                (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73,
-                (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00,
-                (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E,
-                (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69, (byte)0x00,
-                (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67,
-                (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04,
-                (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68,
-                (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00,
-                (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72,
-                (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A UCS2 message containing a \u0434 character", msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBodyUcs2Umts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
-
-                (byte)0x01,
-
-                (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55,
-                (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32,
-                (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65,
-                (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61,
-                (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x20,
-                (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F, (byte)0x00, (byte)0x6E,
-                (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x69,
-                (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E,
-                (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61,
-                (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20,
-                (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61,
-                (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x63,
-                (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x72,
-                (byte)0x00, (byte)0x0D, (byte)0x00, (byte)0x0D,
-
-                (byte)0x4E
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A UCS2 message containing a \u0434 character", msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBodyUcs2MultipageUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
-
-                (byte)0x02,
-
-                (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x41,
-                (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-
-                (byte)0x06,
-
-                (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42, (byte)0x00, (byte)0x42,
-                (byte)0x00, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-                (byte)0x0D, (byte)0x0D, (byte)0x0D, (byte)0x0D,
-
-                (byte)0x06
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected multipage UCS2 string decoded",
-                "AAABBB", msg.getMessageBody());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBodyUcs2WithLanguageInBody() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x11, (byte)0x11, (byte)0x78,
-                (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55,
-                (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00,
-                (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73,
-                (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00,
-                (byte)0x65, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F,
-                (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61, (byte)0x00,
-                (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E,
-                (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x61, (byte)0x00,
-                (byte)0x20, (byte)0x04, (byte)0x34, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63,
-                (byte)0x00, (byte)0x68, (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00,
-                (byte)0x61, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65,
-                (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A UCS2 message containing a \u0434 character", msg.getMessageBody());
-
-        assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageBodyUcs2WithLanguageInBodyUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x11,
-
-                (byte)0x01,
-
-                (byte)0x78, (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20,
-                (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53,
-                (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x6D,
-                (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73,
-                (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x65,
-                (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x6F,
-                (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x61,
-                (byte)0x00, (byte)0x69, (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x69,
-                (byte)0x00, (byte)0x6E, (byte)0x00, (byte)0x67, (byte)0x00, (byte)0x20,
-                (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x20, (byte)0x04, (byte)0x34,
-                (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x68,
-                (byte)0x00, (byte)0x61, (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x61,
-                (byte)0x00, (byte)0x63, (byte)0x00, (byte)0x74, (byte)0x00, (byte)0x65,
-                (byte)0x00, (byte)0x72, (byte)0x00, (byte)0x0D,
-
-                (byte)0x50
-        };
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected 7-bit string decoded",
-                "A UCS2 message containing a \u0434 character", msg.getMessageBody());
-
-        assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageIdentifier() {
-        byte[] pdu = {
-                (byte)0xC0, (byte)0x00, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageIdentifierUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
-                (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
-                (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
-                (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x34
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-
-        assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
-    }
-
-    @Test @SmallTest
-    public void testGetMessageCode() {
-        byte[] pdu = {
-                (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-        int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
-
-        assertEquals("Unexpected message code decoded", 682, messageCode);
-    }
-
-    @Test @SmallTest
-    public void testGetMessageCodeUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
-                (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
-                (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
-                (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x34
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-        int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
-
-        assertEquals("Unexpected message code decoded", 682, messageCode);
-    }
-
-    @Test @SmallTest
-    public void testGetUpdateNumber() {
-        byte[] pdu = {
-                (byte)0x2A, (byte)0xA5, (byte)0x30, (byte)0x39, (byte)0x40, (byte)0x11, (byte)0x41,
-                (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
-                (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
-                (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
-                (byte)0xF9, (byte)0x3C, (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69,
-                (byte)0x3A, (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9, (byte)0x75,
-                (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93, (byte)0xC9, (byte)0x69,
-                (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-        int updateNumber = msg.getSerialNumber() & 0x000f;
-
-        assertEquals("Unexpected update number decoded", 5, updateNumber);
-    }
-
-    @Test @SmallTest
-    public void testGetUpdateNumberUmts() {
-        byte[] pdu = {
-                (byte)0x01, (byte)0x30, (byte)0x39, (byte)0x2A, (byte)0xA5, (byte)0x40,
-
-                (byte)0x01,
-
-                (byte)0x41, (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91,
-                (byte)0xCB, (byte)0xE6, (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07,
-                (byte)0x85, (byte)0xD9, (byte)0x70, (byte)0x74, (byte)0x58, (byte)0x5C,
-                (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5, (byte)0xF9, (byte)0x3C,
-                (byte)0x7C, (byte)0x2E, (byte)0x83, (byte)0xEE, (byte)0x69, (byte)0x3A,
-                (byte)0x1A, (byte)0x34, (byte)0x0E, (byte)0xCB, (byte)0xE5, (byte)0xE9,
-                (byte)0xF0, (byte)0xB9, (byte)0x0C, (byte)0x92, (byte)0x97, (byte)0xE9,
-                (byte)0x75, (byte)0xB9, (byte)0x1B, (byte)0x04, (byte)0x0F, (byte)0x93,
-                (byte)0xC9, (byte)0x69, (byte)0xF7, (byte)0xB9, (byte)0xD1, (byte)0x68,
-                (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3, (byte)0xD1,
-                (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46, (byte)0xA3,
-                (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D, (byte)0x46,
-                (byte)0xA3, (byte)0xD1, (byte)0x68, (byte)0x34, (byte)0x1A, (byte)0x8D,
-                (byte)0x46, (byte)0xA3, (byte)0xD1, (byte)0x00,
-
-                (byte)0x34
-        };
-
-        SmsCbMessage msg = createFromPdu(pdu);
-        int updateNumber = msg.getSerialNumber() & 0x000f;
-
-        assertEquals("Unexpected update number decoded", 5, updateNumber);
-    }
-
-    /* ETWS Test message including header */
-    private static final byte[] etwsMessageNormal = IccUtils.hexStringToBytes("000011001101" +
-            "0D0A5BAE57CE770C531790E85C716CBF3044573065B930675730" +
-            "9707767A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" +
-            "0000000000000000000000000000");
-
-    private static final byte[] etwsMessageCancel = IccUtils.hexStringToBytes("000011001101" +
-            "0D0A5148307B3069002800310030003A0035" +
-            "00320029306E7DCA602557309707901F5831309253D66D883057307E3059FF086C178C615E81FF09" +
-            "00000000000000000000000000000000000000000000");
-
-    private static final byte[] etwsMessageTest = IccUtils.hexStringToBytes("000011031101" +
-            "0D0A5BAE57CE770C531790E85C716CBF3044" +
-            "573065B9306757309707300263FA308C306B5099304830664E0B30553044FF086C178C615E81FF09" +
-            "00000000000000000000000000000000000000000000");
-
-    // FIXME: add example of ETWS primary notification PDU
-
-    @Test @SmallTest
-    public void testEtwsMessageNormal() {
-        SmsCbMessage msg = createFromPdu(etwsMessageNormal);
-        Rlog.d(TAG, msg.toString());
-        assertEquals("GS mismatch", 0, msg.getGeographicalScope());
-        assertEquals("serial number mismatch", 0, msg.getSerialNumber());
-        assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
-        assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
-                msg.getEtwsWarningInfo().getWarningType());
-    }
-
-    @Test @SmallTest
-    public void testEtwsMessageCancel() {
-        SmsCbMessage msg = createFromPdu(etwsMessageCancel);
-        Rlog.d(TAG, msg.toString());
-        assertEquals("GS mismatch", 0, msg.getGeographicalScope());
-        assertEquals("serial number mismatch", 0, msg.getSerialNumber());
-        assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
-        assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
-                msg.getEtwsWarningInfo().getWarningType());
-    }
-
-    @Test @SmallTest
-    public void testEtwsMessageTest() {
-        SmsCbMessage msg = createFromPdu(etwsMessageTest);
-        Rlog.d(TAG, msg.toString());
-        assertEquals("GS mismatch", 0, msg.getGeographicalScope());
-        assertEquals("serial number mismatch", 0, msg.getSerialNumber());
-        assertEquals("message ID mismatch", 0x1103, msg.getServiceCategory());
-        assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE,
-                msg.getEtwsWarningInfo().getWarningType());
-    }
-
-    // Make sure we don't throw an exception if we feed random data to the PDU parser.
-    @Test @SmallTest
-    public void testRandomPdus() {
-        Random r = new Random(94040);
-        for (int run = 0; run < 10000; run++) {
-            int len = r.nextInt(140);
-            byte[] data = new byte[len];
-            for (int i = 0; i < len; i++) {
-                data[i] = (byte) r.nextInt(256);
-            }
-            try {
-                // this should return a SmsCbMessage object or null for invalid data
-                SmsCbMessage msg = createFromPdu(data);
-            } catch (Exception e) {
-                Rlog.d(TAG, "exception thrown", e);
-                fail("Exception in decoder at run " + run + " length " + len + ": " + e);
-            }
-        }
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java.broken b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java.broken
index c599ad0..a9d869c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java.broken
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java.broken
@@ -20,7 +20,7 @@
 import android.os.AsyncResult;
 import android.os.Message;
 import android.os.SystemClock;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
 
 import com.android.internal.telephony.BaseCommands;
 import com.android.internal.telephony.UUSInfo;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java.broken b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java.broken
index f32e4bd..9fbb86c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java.broken
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadTest.java.broken
@@ -18,7 +18,7 @@
 
 import android.os.HandlerThread;
 import android.test.AndroidTestCase;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
 
 import java.nio.charset.Charset;
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/FeatureConnectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/FeatureConnectorTest.java
index a544bc3..a2b4de8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/FeatureConnectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/FeatureConnectorTest.java
@@ -19,11 +19,13 @@
 import junit.framework.AssertionFailedError;
 
 import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.pm.PackageManager;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.telephony.ims.feature.ImsFeature;
@@ -70,7 +72,7 @@
         mHandlerThread = new HandlerThread("ConnectorHandlerThread");
         mHandlerThread.start();
 
-        mFeatureConnector = new FeatureConnector<ImsManager>(mContext, phoneId,
+        mFeatureConnector = new FeatureConnector<>(mContext, phoneId,
             mListener, mExecutor, mHandlerThread.getLooper());
         mFeatureConnector.mListener = mListener;
     }
@@ -85,7 +87,7 @@
     @SmallTest
     public void testConnect() {
         // ImsManager is supported on device
-        when(mListener.isSupported()).thenReturn(true);
+        setImsSupportedFeature(true);
         when(mListener.getFeatureManager()).thenReturn(mImsManager);
 
         mFeatureConnector.connect();
@@ -97,7 +99,7 @@
         reset(mListener);
 
         // ImsManager is NOT supported on device
-        when(mListener.isSupported()).thenReturn(false);
+        setImsSupportedFeature(false);
         when(mListener.getFeatureManager()).thenReturn(mImsManager);
 
         mFeatureConnector.connect();
@@ -145,4 +147,9 @@
         // Verify removeNotifyStatusChangedCallback will be called if ImsManager is not null.
         verify(mImsManager).removeNotifyStatusChangedCallback(anyObject());
     }
+
+    private void setImsSupportedFeature(boolean isSupported) {
+        doReturn(isSupported).when(mPackageManager).hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY_IMS);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 0a1d51c..e24074e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -15,11 +15,21 @@
  */
 package com.android.internal.telephony.imsphone;
 
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.METERED_YES;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
+
+import static com.android.testutils.NetworkStatsUtilsKt.assertNetworkStatsEquals;
+
 import static junit.framework.TestCase.fail;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
@@ -32,6 +42,7 @@
 import static org.mockito.Mockito.isNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -40,6 +51,9 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.net.NetworkStats;
+import android.net.NetworkStats.Entry;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
 import android.os.Bundle;
 import android.os.Message;
 import android.os.PersistableBundle;
@@ -72,6 +86,7 @@
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker.VtDataUsageProvider;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -94,6 +109,8 @@
     private ImsCall mImsCall;
     private ImsCall mSecondImsCall;
     private Bundle mBundle = new Bundle();
+    private final ArgumentCaptor<VtDataUsageProvider> mVtDataUsageProviderCaptor =
+            ArgumentCaptor.forClass(VtDataUsageProvider.class);
     @Mock
     private ImsCallSession mImsCallSession;
     @Mock
@@ -104,6 +121,8 @@
     private ImsConfig mImsConfig;
     @Mock
     private ImsPhoneConnection mImsPhoneConnection;
+    @Mock
+    private NetworkStatsProviderCallback mVtDataUsageProviderCb;
 
     private void imsCallMocking(final ImsCall imsCall) throws Exception {
 
@@ -196,7 +215,7 @@
                 mSecondImsCall.setListener(mImsCallListener);
                 return mSecondImsCall;
             }
-        }).when(mImsManager).makeCall(eq(mImsCallProfile), (String []) any(),
+        }).when(mImsManager).makeCall(eq(mImsCallProfile), (String[]) any(),
                 (ImsCall.Listener) any());
 
         doAnswer(invocation -> {
@@ -209,6 +228,9 @@
 
         doNothing().when(mImsManager).addNotifyStatusChangedCallbackIfAvailable(any());
 
+        doReturn(mVtDataUsageProviderCb).when(mStatsManager).registerNetworkStatsProvider(
+                anyString(), any());
+
         mCTUT = new ImsPhoneCallTracker(mImsPhone, Runnable::run);
         mCTUT.addReasonCodeRemapping(null, "Wifi signal lost.", ImsReasonInfo.CODE_WIFI_LOST);
         mCTUT.addReasonCodeRemapping(501, "Call answered elsewhere.",
@@ -224,6 +246,8 @@
                 "service not allowed in this location",
                 ImsReasonInfo.CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION);
         mCTUT.setDataEnabled(true);
+        verify(mStatsManager).registerNetworkStatsProvider(anyString(),
+                mVtDataUsageProviderCaptor.capture());
 
         logd("ImsPhoneCallTracker initiated");
         processAllMessages();
@@ -1005,6 +1029,66 @@
         mCTUT.getImsCallListener().onCallHoldFailed(mImsPhoneConnection.getImsCall(), info);
     }
 
+    @Test
+    @SmallTest
+    public void testVtDataUsageProvider() {
+        final VtDataUsageProvider provider = mVtDataUsageProviderCaptor.getValue();
+
+        provider.requestStatsUpdate(11);
+
+        // Verify that requestStatsUpdate triggers onStatsUpdated, where the initial token should
+        // be reported with current stats.
+        assertVtDataUsageUpdated(0, 0, 0);
+
+        // Establish a MT call.
+        testImsMTCallAccept();
+        final ImsPhoneConnection connection = mCTUT.mForegroundCall.getFirstConnection();
+        final ImsCall call = connection.getImsCall();
+        mCTUT.updateVtDataUsage(call, 51);
+
+        // Make another request, and verify stats updated accordingly, with previously issued token.
+        reset(mVtDataUsageProviderCb);
+        provider.requestStatsUpdate(13);
+        assertVtDataUsageUpdated(11, 25, 25);
+
+        // Update accumulated data usage twice. updateVtDataUsage takes accumulated stats from
+        // boot up.
+        reset(mVtDataUsageProviderCb);
+        mCTUT.updateVtDataUsage(call, 70);
+        mCTUT.updateVtDataUsage(call, 91);
+        verify(mVtDataUsageProviderCb, never()).onStatsUpdated(anyInt(), any(), any());
+
+        // Verify that diff stats from last update is reported accordingly.
+        provider.requestStatsUpdate(13);
+        // Rounding error occurs so (70-51)/2 + (91-70)/2 = 19 is expected for both direction.
+        assertVtDataUsageUpdated(13, 19, 19);
+    }
+
+    private void assertVtDataUsageUpdated(int expectedToken, long rxBytes, long txBytes) {
+        final ArgumentCaptor<NetworkStats> ifaceStatsCaptor = ArgumentCaptor.forClass(
+                NetworkStats.class);
+        final ArgumentCaptor<NetworkStats> uidStatsCaptor = ArgumentCaptor.forClass(
+                NetworkStats.class);
+
+        verify(mVtDataUsageProviderCb).onStatsUpdated(eq(expectedToken), ifaceStatsCaptor.capture(),
+                uidStatsCaptor.capture());
+
+        // Default dialer's package uid is not set during test, thus the uid stats looks the same
+        // as iface stats and the records are always merged into the same entry.
+        // TODO: Mock different dialer's uid and verify uid stats has corresponding uid in the
+        //  records.
+        NetworkStats expectedStats = new NetworkStats(0L, 0);
+
+        if (rxBytes != 0 || txBytes != 0) {
+            expectedStats = expectedStats.addValues(
+                    new Entry(NetworkStats.IFACE_VT, UID_ALL, SET_FOREGROUND,
+                            TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, rxBytes, 0L,
+                            txBytes, 0L, 0L));
+        }
+        assertNetworkStatsEquals(expectedStats, ifaceStatsCaptor.getValue());
+        assertNetworkStatsEquals(expectedStats, uidStatsCaptor.getValue());
+    }
+
     private ImsPhoneConnection placeCallAndMakeActive() {
         try {
             doAnswer(new Answer<ImsCall>() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 677f402..8aab248 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -35,7 +35,6 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
@@ -57,7 +56,6 @@
 import android.telephony.ims.ImsCallProfile;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.RegistrationManager;
-import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.stub.ImsUtImplBase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -66,10 +64,8 @@
 
 import androidx.test.filters.FlakyTest;
 
-import com.android.ims.FeatureConnector;
 import com.android.ims.ImsEcbmStateListener;
 import com.android.ims.ImsUtInterface;
-import com.android.ims.RcsFeatureManager;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.CommandsInterface;
@@ -667,27 +663,6 @@
 
     @Test
     @SmallTest
-    public void testRegisteringImsRcsRegistrationCallback() throws Exception {
-        RcsFeatureManager rcsFeatureManager = mock(RcsFeatureManager.class);
-
-        // When initialized RcsFeatureManager and
-        mImsPhoneUT.initRcsFeatureManager();
-        assertNotNull(mImsPhoneUT.mRcsManagerConnector);
-
-        // When connection is ready, the register IMS registration callback should be called.
-        mImsPhoneUT.mRcsFeatureConnectorListener.connectionReady(rcsFeatureManager);
-        verify(rcsFeatureManager).registerImsRegistrationCallback(
-                any(IImsRegistrationCallback.class));
-
-        // When connection is unavailable, the IMS registration state should be not registered.
-        mImsPhoneUT.mRcsFeatureConnectorListener.connectionUnavailable();
-        Consumer<Integer> registrationState = mock(Consumer.class);
-        mImsPhoneUT.getImsRcsRegistrationState(registrationState);
-        verify(registrationState).accept(RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
-    }
-
-    @Test
-    @SmallTest
     public void testImsRegistered() throws Exception {
         mImsPhoneUT.setServiceState(ServiceState.STATE_IN_SERVICE);
         mImsPhoneUT.setImsRegistrationState(RegistrationManager.REGISTRATION_STATE_REGISTERED);
@@ -871,19 +846,6 @@
         assertNotNull(mImsPhoneUT.getServiceStateTracker());
     }
 
-    @Test
-    @SmallTest
-    public void testRcsFeatureManagerInitialization() throws Exception {
-        FeatureConnector<RcsFeatureManager> mockRcsManagerConnector =
-                (FeatureConnector<RcsFeatureManager>) mock(FeatureConnector.class);
-        mImsPhoneUT.mRcsManagerConnector = mockRcsManagerConnector;
-
-        mImsPhoneUT.initRcsFeatureManager();
-
-        verify(mockRcsManagerConnector).disconnect();
-        assertNotNull(mImsPhoneUT.mRcsManagerConnector);
-    }
-
     private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) {
         ServiceState ss = new ServiceState();
         ss.setStateOutOfService();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
index 4881d54..f2f69db 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
@@ -48,7 +48,8 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
 
-        mRegistrationCallbackHelper = new ImsRegistrationCallbackHelper(mMockRegistrationUpdate);
+        mRegistrationCallbackHelper = new ImsRegistrationCallbackHelper(mMockRegistrationUpdate,
+                Runnable::run);
     }
 
     @After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
index e298da4..8c4eab1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.nitz;
 
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
 
 import static com.android.internal.telephony.NitzStateMachineTestSupport.ARBITRARY_SYSTEM_CLOCK_TIME;
 import static com.android.internal.telephony.NitzStateMachineTestSupport.UNIQUE_US_ZONE_SCENARIO1;
@@ -33,8 +33,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.os.TimestampedValue;
 
 import com.android.internal.telephony.IndentingPrintWriter;
@@ -55,11 +55,11 @@
 
 public class NewNitzStateMachineImplTest extends TelephonyTest {
 
-    private static final int PHONE_ID = 99999;
-    private static final PhoneTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
-            createEmptyTimeZoneSuggestion(PHONE_ID);
-    private static final PhoneTimeSuggestion EMPTY_TIME_SUGGESTION =
-            createEmptyTimeSuggestion(PHONE_ID);
+    private static final int SLOT_INDEX = 99999;
+    private static final TelephonyTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
+            createEmptyTimeZoneSuggestion(SLOT_INDEX);
+    private static final TelephonyTimeSuggestion EMPTY_TIME_SUGGESTION =
+            createEmptyTimeSuggestion(SLOT_INDEX);
 
     private FakeNewTimeServiceHelper mFakeNewTimeServiceHelper;
     private FakeDeviceState mFakeDeviceState;
@@ -91,7 +91,7 @@
         mRealTimeZoneSuggester = new TimeZoneSuggesterImpl(mFakeDeviceState, timeZoneLookupHelper);
 
         mNitzStateMachineImpl = new NewNitzStateMachineImpl(
-                PHONE_ID, mFakeNitzSignalInputFilter, mRealTimeZoneSuggester,
+                SLOT_INDEX, mFakeNitzSignalInputFilter, mRealTimeZoneSuggester,
                 mFakeNewTimeServiceHelper);
 
         TelephonyTest.logd("NewNitzStateMachineImplTest -Setup!");
@@ -111,12 +111,12 @@
 
         // Capture expected results from the real suggester and confirm we can tell the difference
         // between them.
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion1 =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion1 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, networkCountryIsoCode, null /* nitzSignal */);
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion2 =
+                        SLOT_INDEX, networkCountryIsoCode, null /* nitzSignal */);
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion2 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, networkCountryIsoCode, nitzSignal);
+                        SLOT_INDEX, networkCountryIsoCode, nitzSignal);
         assertNotNull(expectedTimeZoneSuggestion2);
         assertNotEquals(expectedTimeZoneSuggestion1, expectedTimeZoneSuggestion2);
 
@@ -135,8 +135,8 @@
         // Simulate NITZ being received and verify the behavior.
         script.nitzReceived(nitzSignal);
 
-        PhoneTimeSuggestion expectedTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, nitzSignal);
+        TelephonyTimeSuggestion expectedTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, nitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedTimeSuggestion, expectedTimeZoneSuggestion2);
 
@@ -154,12 +154,12 @@
 
         // Capture test expectations from the real suggester and confirm we can tell the difference
         // between them.
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion1 =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion1 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, null /* countryIsoCode */, nitzSignal);
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion2 =
+                        SLOT_INDEX, null /* countryIsoCode */, nitzSignal);
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion2 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, networkCountryIsoCode, nitzSignal);
+                        SLOT_INDEX, networkCountryIsoCode, nitzSignal);
         assertNotEquals(expectedTimeZoneSuggestion1, expectedTimeZoneSuggestion2);
 
         Script script = new Script()
@@ -170,8 +170,8 @@
         script.nitzReceived(nitzSignal);
 
         // Verify the state machine did the right thing.
-        PhoneTimeSuggestion expectedTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, nitzSignal);
+        TelephonyTimeSuggestion expectedTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, nitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedTimeSuggestion, expectedTimeZoneSuggestion1);
 
@@ -208,13 +208,13 @@
         // Simulate receiving the NITZ signal.
         script.nitzReceived(nitzSignal);
 
-        PhoneTimeSuggestion expectedTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, nitzSignal);
+        TelephonyTimeSuggestion expectedTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, nitzSignal);
         // Capture output from the real suggester and confirm it meets the test's needs /
         // expectations.
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, "" /* countryIsoCode */, nitzSignal);
+                        SLOT_INDEX, "" /* countryIsoCode */, nitzSignal);
         assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY,
                 expectedTimeZoneSuggestion.getMatchType());
         assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
@@ -243,8 +243,8 @@
 
         // Verify the state machine did the right thing.
         // No time zone should be set. A NITZ signal by itself is not enough.
-        PhoneTimeSuggestion expectedTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, nitzSignal);
+        TelephonyTimeSuggestion expectedTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, nitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedTimeSuggestion, EMPTY_TIME_ZONE_SUGGESTION);
 
@@ -256,9 +256,9 @@
 
         // Capture output from the real suggester and confirm it meets the test's needs /
         // expectations.
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, "" /* countryIsoCode */, nitzSignal);
+                        SLOT_INDEX, "" /* countryIsoCode */, nitzSignal);
         assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY,
                 expectedTimeZoneSuggestion.getMatchType());
         assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
@@ -284,8 +284,8 @@
         // zone.
         TimestampedValue<NitzData> preFlightNitzSignal =
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-        PhoneTimeSuggestion expectedPreFlightTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, preFlightNitzSignal);
+        TelephonyTimeSuggestion expectedPreFlightTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, preFlightNitzSignal);
         String preFlightCountryIsoCode = scenario.getNetworkCountryIsoCode();
 
         // Simulate receiving the NITZ signal and country.
@@ -293,9 +293,9 @@
                 .countryReceived(preFlightCountryIsoCode);
 
         // Verify the state machine did the right thing.
-        PhoneTimeZoneSuggestion expectedPreFlightTimeZoneSuggestion =
+        TelephonyTimeZoneSuggestion expectedPreFlightTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, preFlightCountryIsoCode, preFlightNitzSignal);
+                        SLOT_INDEX, preFlightCountryIsoCode, preFlightNitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedPreFlightTimeSuggestion, expectedPreFlightTimeZoneSuggestion);
 
@@ -355,11 +355,11 @@
                 .nitzReceived(postFlightNitzSignal);
 
         // Verify the state machine did the right thing.
-        PhoneTimeSuggestion expectedPostFlightTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, postFlightNitzSignal);
-        PhoneTimeZoneSuggestion expectedPostFlightTimeZoneSuggestion =
+        TelephonyTimeSuggestion expectedPostFlightTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, postFlightNitzSignal);
+        TelephonyTimeZoneSuggestion expectedPostFlightTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, postFlightCountryCode, postFlightNitzSignal);
+                        SLOT_INDEX, postFlightCountryCode, postFlightNitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedPostFlightTimeSuggestion, expectedPostFlightTimeZoneSuggestion);
 
@@ -383,17 +383,17 @@
         // Simulate a device receiving signals that allow it to detect time and time zone.
         TimestampedValue<NitzData> initialNitzSignal =
                 scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-        PhoneTimeSuggestion expectedInitialTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, initialNitzSignal);
+        TelephonyTimeSuggestion expectedInitialTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, initialNitzSignal);
 
         // Simulate receiving the NITZ signal and country.
         script.nitzReceived(initialNitzSignal)
                 .countryReceived(countryIsoCode);
 
         // Verify the state machine did the right thing.
-        PhoneTimeZoneSuggestion expectedInitialTimeZoneSuggestion =
+        TelephonyTimeZoneSuggestion expectedInitialTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, countryIsoCode, initialNitzSignal);
+                        SLOT_INDEX, countryIsoCode, initialNitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedInitialTimeSuggestion, expectedInitialTimeZoneSuggestion);
 
@@ -408,9 +408,9 @@
         script.networkUnavailable();
 
         // Check the "no NITZ" time and time zone suggestions are made.
-        PhoneTimeZoneSuggestion expectedMiddleTimeZoneSuggestion =
+        TelephonyTimeZoneSuggestion expectedMiddleTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, countryIsoCode, null /* nitzSignal */);
+                        SLOT_INDEX, countryIsoCode, null /* nitzSignal */);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 EMPTY_TIME_SUGGESTION, expectedMiddleTimeZoneSuggestion);
 
@@ -439,11 +439,11 @@
         script.nitzReceived(finalNitzSignal);
 
         // Verify the state machine did the right thing.
-        PhoneTimeSuggestion expectedFinalTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, finalNitzSignal);
-        PhoneTimeZoneSuggestion expectedFinalTimeZoneSuggestion =
+        TelephonyTimeSuggestion expectedFinalTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, finalNitzSignal);
+        TelephonyTimeZoneSuggestion expectedFinalTimeZoneSuggestion =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, countryIsoCode, finalNitzSignal);
+                        SLOT_INDEX, countryIsoCode, finalNitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedFinalTimeSuggestion, expectedFinalTimeZoneSuggestion);
 
@@ -463,18 +463,18 @@
 
         // Simulate receiving the country and verify the state machine does the right thing.
         script.countryReceived(scenario.getNetworkCountryIsoCode());
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion1 =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion1 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+                        SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
         script.verifyOnlyTimeZoneWasSuggestedAndReset(expectedTimeZoneSuggestion1);
 
         // Simulate receiving an NITZ signal and verify the state machine does the right thing.
         script.nitzReceived(nitzSignal);
-        PhoneTimeSuggestion expectedTimeSuggestion =
-                createTimeSuggestionFromNitzSignal(PHONE_ID, nitzSignal);
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion2 =
+        TelephonyTimeSuggestion expectedTimeSuggestion =
+                createTimeSuggestionFromNitzSignal(SLOT_INDEX, nitzSignal);
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion2 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+                        SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
         script.verifyTimeAndTimeZoneSuggestedAndReset(
                 expectedTimeSuggestion, expectedTimeZoneSuggestion2);
 
@@ -484,9 +484,9 @@
         // Simulate the country becoming unavailable and verify the state machine does the right
         // thing.
         script.countryUnavailable();
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion3 =
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion3 =
                 mRealTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, null /* countryIsoCode */, nitzSignal);
+                        SLOT_INDEX, null /* countryIsoCode */, nitzSignal);
         script.verifyOnlyTimeZoneWasSuggestedAndReset(expectedTimeZoneSuggestion3);
 
         // Check state that NitzStateMachine must expose.
@@ -558,15 +558,16 @@
             return this;
         }
 
-        Script verifyOnlyTimeZoneWasSuggestedAndReset(PhoneTimeZoneSuggestion timeZoneSuggestion) {
+        Script verifyOnlyTimeZoneWasSuggestedAndReset(
+                TelephonyTimeZoneSuggestion timeZoneSuggestion) {
             justVerifyTimeZoneWasSuggested(timeZoneSuggestion);
             justVerifyTimeWasNotSuggested();
             commitStateChanges();
             return this;
         }
 
-        Script verifyTimeAndTimeZoneSuggestedAndReset(
-                PhoneTimeSuggestion timeSuggestion, PhoneTimeZoneSuggestion timeZoneSuggestion) {
+        Script verifyTimeAndTimeZoneSuggestedAndReset(TelephonyTimeSuggestion timeSuggestion,
+                TelephonyTimeZoneSuggestion timeZoneSuggestion) {
             justVerifyTimeZoneWasSuggested(timeZoneSuggestion);
             justVerifyTimeWasSuggested(timeSuggestion);
             commitStateChanges();
@@ -577,12 +578,13 @@
             mFakeNewTimeServiceHelper.suggestedTimes.assertHasNotBeenSet();
         }
 
-        private void justVerifyTimeZoneWasSuggested(PhoneTimeZoneSuggestion timeZoneSuggestion) {
+        private void justVerifyTimeZoneWasSuggested(
+                TelephonyTimeZoneSuggestion timeZoneSuggestion) {
             mFakeNewTimeServiceHelper.suggestedTimeZones.assertHasBeenSet();
             mFakeNewTimeServiceHelper.suggestedTimeZones.assertLatestEquals(timeZoneSuggestion);
         }
 
-        private void justVerifyTimeWasSuggested(PhoneTimeSuggestion timeSuggestion) {
+        private void justVerifyTimeWasSuggested(TelephonyTimeSuggestion timeSuggestion) {
             mFakeNewTimeServiceHelper.suggestedTimes.assertChangeCount(1);
             mFakeNewTimeServiceHelper.suggestedTimes.assertLatestEquals(timeSuggestion);
         }
@@ -650,15 +652,15 @@
         private final FakeDeviceState mFakeDeviceState;
 
         // State we want to track.
-        public final TestState<PhoneTimeSuggestion> suggestedTimes = new TestState<>();
-        public final TestState<PhoneTimeZoneSuggestion> suggestedTimeZones = new TestState<>();
+        public final TestState<TelephonyTimeSuggestion> suggestedTimes = new TestState<>();
+        public final TestState<TelephonyTimeZoneSuggestion> suggestedTimeZones = new TestState<>();
 
         FakeNewTimeServiceHelper(FakeDeviceState fakeDeviceState) {
             mFakeDeviceState = fakeDeviceState;
         }
 
         @Override
-        public void suggestDeviceTime(PhoneTimeSuggestion timeSuggestion) {
+        public void suggestDeviceTime(TelephonyTimeSuggestion timeSuggestion) {
             suggestedTimes.set(timeSuggestion);
             if (timeSuggestion.getUtcTime() != null) {
                 // The fake time service just uses the latest suggestion.
@@ -667,7 +669,7 @@
         }
 
         @Override
-        public void maybeSuggestDeviceTimeZone(PhoneTimeZoneSuggestion timeZoneSuggestion) {
+        public void maybeSuggestDeviceTimeZone(TelephonyTimeZoneSuggestion timeZoneSuggestion) {
             suggestedTimeZones.set(timeZoneSuggestion);
         }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
index 4c46d98..c32e447 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
@@ -16,13 +16,13 @@
 
 package com.android.internal.telephony.nitz;
 
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
 
 import static com.android.internal.telephony.NitzStateMachineTestSupport.ARBITRARY_REALTIME_MILLIS;
 import static com.android.internal.telephony.NitzStateMachineTestSupport.CZECHIA_SCENARIO;
@@ -39,7 +39,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.os.TimestampedValue;
 
 import com.android.internal.telephony.NitzData;
@@ -58,9 +58,9 @@
 
 public class TimeZoneSuggesterImplTest extends TelephonyTest {
 
-    private static final int PHONE_ID = 99999;
-    private static final PhoneTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
-            new PhoneTimeZoneSuggestion.Builder(PHONE_ID).build();
+    private static final int SLOT_INDEX = 99999;
+    private static final TelephonyTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
+            new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX).build();
 
     private FakeDeviceState mFakeDeviceState;
     private TimeZoneSuggester mTimeZoneSuggester;
@@ -90,7 +90,7 @@
     public void test_emptySuggestionForNullCountryNullNitz() throws Exception {
         assertEquals(EMPTY_TIME_ZONE_SUGGESTION,
                 mTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, null /* countryIsoCode */, null /* nitzSignal */));
+                        SLOT_INDEX, null /* countryIsoCode */, null /* nitzSignal */));
     }
 
     @Test
@@ -100,14 +100,14 @@
                 scenario.createNitzSignal(ARBITRARY_REALTIME_MILLIS);
         assertEquals(EMPTY_TIME_ZONE_SUGGESTION,
                 mTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, null /* countryIsoCode */, nitzSignal));
+                        SLOT_INDEX, null /* countryIsoCode */, nitzSignal));
     }
 
     @Test
     public void test_emptySuggestionForEmptyCountryNullNitz() throws Exception {
         assertEquals(EMPTY_TIME_ZONE_SUGGESTION,
                 mTimeZoneSuggester.getTimeZoneSuggestion(
-                        PHONE_ID, "" /* countryIsoCoe */, null /* nitzSignal */));
+                        SLOT_INDEX, "" /* countryIsoCoe */, null /* nitzSignal */));
     }
 
     /**
@@ -123,47 +123,47 @@
         // Country won't be enough to get a quality result for time zone detection but a suggestion
         // will be made.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
         // NITZ with a "" country code is interpreted as a test network so only offset is used
         // to get a match.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, "" /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, "" /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
-            assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
+            assertEquals(SLOT_INDEX, actualSuggestion.getSlotIndex());
             assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
             assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
         }
 
         // NITZ alone is not enough to get a result when the country is not available.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, null /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, null /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
 
         // Country + NITZ is enough for a unique time zone detection result for this scenario.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -174,9 +174,9 @@
             // We use an NITZ from CZ to generate an NITZ signal with a bad offset.
             TimestampedValue<NitzData> badNitzSignal =
                     CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     badNitzSignal);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -195,43 +195,43 @@
         // Country won't be enough to get a quality result for time zone detection but a suggestion
         // will be made.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
         // NITZ with a "" country code is interpreted as a test network so only offset is used
         // to get a match.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, "" /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, "" /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
-            assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
+            assertEquals(SLOT_INDEX, actualSuggestion.getSlotIndex());
             assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
             assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
         }
 
         // NITZ alone is not enough to get a result when the country is not available.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, null /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, null /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
 
         // Country + NITZ is not enough for a unique time zone detection result for this scenario.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
-            assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
+            assertEquals(SLOT_INDEX, actualSuggestion.getSlotIndex());
             assertEquals(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, actualSuggestion.getMatchType());
             assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
             List<String> allowedZoneIds = Arrays.asList(NON_UNIQUE_US_ZONE_SCENARIO_ZONES);
@@ -244,9 +244,9 @@
             // We use an NITZ from CZ to generate an NITZ signal with a bad offset.
             TimestampedValue<NitzData> badNitzSignal =
                     CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     badNitzSignal);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -264,25 +264,25 @@
 
         // Country alone is enough to guess the time zone.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
         // NITZ with a "" country code is interpreted as a test network so only offset is used
         // to get a match.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, "" /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, "" /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
-            assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
+            assertEquals(SLOT_INDEX, actualSuggestion.getSlotIndex());
             assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
             assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
 
@@ -290,23 +290,23 @@
 
         // NITZ alone is not enough to get a result when the country is not available.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, null /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, null /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
 
         // Country + NITZ is enough for both time + time zone detection.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -317,15 +317,15 @@
             // We use an NITZ from Czechia to generate an NITZ signal with a bad offset.
             TimestampedValue<NitzData> badNitzSignal =
                     CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     badNitzSignal);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -342,26 +342,26 @@
 
         // Country alone is enough to guess the time zone.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
         // NITZ with a "" country code is interpreted as a test network so only offset is used
         // to get a match.
         {
-            PhoneTimeZoneSuggestion actualSuggestion =
+            TelephonyTimeZoneSuggestion actualSuggestion =
                     mTimeZoneSuggester.getTimeZoneSuggestion(
-                            PHONE_ID, "" /* countryIsoCode */,
+                            SLOT_INDEX, "" /* countryIsoCode */,
                             scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
-            assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
+            assertEquals(SLOT_INDEX, actualSuggestion.getSlotIndex());
             assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
             assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
 
@@ -369,23 +369,23 @@
 
         // NITZ alone is not enough to get a result when the country is not available.
         {
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, null /* countryIsoCode */,
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, null /* countryIsoCode */,
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
 
         // Country + NITZ is enough for both time + time zone detection.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -396,15 +396,15 @@
             // We use an NITZ from the US to generate an NITZ signal with a bad offset.
             TimestampedValue<NitzData> badNitzSignal =
                     UNIQUE_US_ZONE_SCENARIO1.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(),
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(),
                     badNitzSignal);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
@@ -416,15 +416,15 @@
 
         // Country alone is enough to guess the time zone.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
@@ -440,8 +440,8 @@
             TimestampedValue<NitzData> badNitzSignal = new TimestampedValue<>(
                     goodNitzSignal.getReferenceTimeMillis(), bogusNitzData);
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), badNitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), badNitzSignal);
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
     }
@@ -452,15 +452,15 @@
 
         // Country alone is not enough to guess the time zone.
         {
-            PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
         }
 
@@ -476,8 +476,8 @@
             TimestampedValue<NitzData> badNitzSignal = new TimestampedValue<>(
                     goodNitzSignal.getReferenceTimeMillis(), bogusNitzData);
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), badNitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), badNitzSignal);
             assertEquals(EMPTY_TIME_ZONE_SUGGESTION, actualSuggestion);
         }
     }
@@ -503,15 +503,15 @@
         TimestampedValue<NitzData> emulatorNitzSignal = new TimestampedValue<>(
                 originalNitzSignal.getReferenceTimeMillis(), emulatorNitzData);
 
-        PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
-                new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+        TelephonyTimeZoneSuggestion expectedTimeZoneSuggestion =
+                new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                         .setZoneId(emulatorTimeZoneId)
                         .setMatchType(MATCH_TYPE_EMULATOR_ZONE_ID)
                         .setQuality(QUALITY_SINGLE_ZONE)
                         .build();
 
-        PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                PHONE_ID, scenario.getNetworkCountryIsoCode(), emulatorNitzSignal);
+        TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                SLOT_INDEX, scenario.getNetworkCountryIsoCode(), emulatorNitzSignal);
         assertEquals(expectedTimeZoneSuggestion, actualSuggestion);
     }
 
@@ -521,15 +521,15 @@
         // countryIsoCode.
         {
             Scenario scenario = NEW_ZEALAND_DEFAULT_SCENARIO;
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -538,15 +538,15 @@
             Scenario scenario = NEW_ZEALAND_DEFAULT_SCENARIO;
             TimestampedValue<NitzData> nitzSignal =
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -555,15 +555,15 @@
             Scenario scenario = NEW_ZEALAND_OTHER_SCENARIO;
             TimestampedValue<NitzData> nitzSignal =
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -574,15 +574,15 @@
             // Use a scenario that has a different offset than NZ to generate the NITZ signal.
             TimestampedValue<NitzData> nitzSignal =
                     CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
     }
@@ -593,15 +593,15 @@
         // we cannot get a zone only from the countryIsoCode.
         {
             Scenario scenario = UNIQUE_US_ZONE_SCENARIO1;
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
                             .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -610,15 +610,15 @@
             Scenario scenario = UNIQUE_US_ZONE_SCENARIO1;
             TimestampedValue<NitzData> nitzSignal =
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -627,15 +627,15 @@
             Scenario scenario = UNIQUE_US_ZONE_SCENARIO2;
             TimestampedValue<NitzData> nitzSignal =
                     scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion =
-                    new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+            TelephonyTimeZoneSuggestion expectedSuggestion =
+                    new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX)
                             .setZoneId(scenario.getTimeZoneId())
                             .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
                             .setQuality(QUALITY_SINGLE_ZONE)
                             .build();
 
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
 
@@ -647,9 +647,9 @@
             // Use a scenario that has a different offset than the US to generate the NITZ signal.
             TimestampedValue<NitzData> nitzSignal =
                     CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
-            PhoneTimeZoneSuggestion expectedSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
-            PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
-                    PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
+            TelephonyTimeZoneSuggestion expectedSuggestion = EMPTY_TIME_ZONE_SUGGESTION;
+            TelephonyTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
+                    SLOT_INDEX, scenario.getNetworkCountryIsoCode(), nitzSignal);
             assertEquals(expectedSuggestion, actualSuggestion);
         }
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java
index d668536..869064c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java
@@ -31,12 +31,14 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.*;
 
-import android.content.Context;
 import android.os.AsyncResult;
 import android.os.HandlerThread;
 import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.telephony.TelephonyTest;
@@ -124,4 +126,95 @@
         waitForLastHandlerAction(mIccRecords);
         assertEquals(mIccRecords.getSmsCapacityOnIcc(), 500);
     }
+
+    @Test
+    public void testGetIccSimChallengeResponseNull() {
+        long startTime;
+        long timeSpent;
+
+        // EAP-SIM rand is 16 bytes.
+        String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+
+        // Test for null result
+        mSimulatedCommands.setAuthenticationMode(mSimulatedCommands.ICC_AUTHENTICATION_MODE_NULL);
+
+        startTime = SystemClock.elapsedRealtime();
+        assertNull("getIccAuthentication should return null for empty data.",
+                mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA,
+                      base64Challenge));
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        assertTrue("getIccAuthentication should not timeout",
+                timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void testGetIccSimChallengeResponseTimeout() {
+        long startTime;
+        long timeSpent;
+
+        // EAP-SIM rand is 16 bytes.
+        String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+
+        mSimulatedCommands.setAuthenticationMode(
+                mSimulatedCommands.ICC_AUTHENTICATION_MODE_TIMEOUT);
+        startTime = SystemClock.elapsedRealtime();
+        assertNull("getIccAuthentication should return null for empty data.",
+                mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA,
+                      base64Challenge));
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        assertTrue("getIccAuthentication should timeout",
+                timeSpent >= mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void testGetIccSimChallengeResponseDefault() {
+        long startTime;
+        long timeSpent;
+
+        // EAP-SIM rand is 16 bytes.
+        String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+        String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
+
+        // Test for default setup
+        mSimulatedCommands.setAuthenticationMode(
+                mSimulatedCommands.ICC_AUTHENTICATION_MODE_DEFAULT);
+
+        // Test for null input
+        startTime = SystemClock.elapsedRealtime();
+        assertNull("getIccAuthentication should return null for empty data.",
+                mIccRecords.getIccSimChallengeResponse(
+                        UiccCardApplication.AUTH_CONTEXT_EAP_AKA, ""));
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        assertTrue("getIccAuthentication should not timeout",
+                timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
+
+        // EAP-SIM
+        startTime = SystemClock.elapsedRealtime();
+        String response = mIccRecords.getIccSimChallengeResponse(
+                UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge);
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response);
+        assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
+
+        startTime = SystemClock.elapsedRealtime();
+        String response1 = mIccRecords.getIccSimChallengeResponse(
+                UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge);
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response1);
+        assertTrue("Response to EAP-SIM Challenge must be consistent.",
+                response.equals(response1));
+
+        startTime = SystemClock.elapsedRealtime();
+        String response2 = mIccRecords.getIccSimChallengeResponse(
+                UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge2);
+        timeSpent = SystemClock.elapsedRealtime() - startTime;
+        Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
+        assertTrue("Two responses must be different.", !response.equals(response2));
+    }
+
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 336267c..e518f3e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -593,4 +593,42 @@
         assertEquals(mUiccControllerUT.convertToPublicCardId(eidForRemovableEuicc),
                 mUiccControllerUT.getCardIdForDefaultEuicc());
     }
+
+    /**
+     * When IccCardStatus is received, if the EID is known from previous APDU, use it to set the
+     * mDefaultEuiccCardId.
+     */
+    @Test
+    public void testEidFromPreviousApduSetsDefaultEuicc() {
+        // Give UiccController a real context so it can use shared preferences
+        mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
+
+        // Mock out UiccSlots
+        mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+        doReturn(true).when(mMockSlot).isEuicc();
+        doReturn(null).when(mMockSlot).getUiccCard();
+        doReturn("123451234567890").when(mMockSlot).getIccId();
+        doReturn(false).when(mMockSlot).isRemovable();
+
+        // If APDU has already happened, the EuiccCard already knows EID
+        String knownEidFromApdu = "A1B2C3D4E5";
+        doReturn(mMockEuiccCard).when(mMockSlot).getUiccCard();
+        doReturn(knownEidFromApdu).when(mMockEuiccCard).getEid();
+
+        // simulate card status loaded so that the UiccController sets the card ID
+        IccCardStatus ics = new IccCardStatus();
+        ics.setCardState(1 /* present */);
+        ics.setUniversalPinState(3 /* disabled */);
+        ics.atr = "abcdef0123456789abcdef";
+        ics.iccid = "123451234567890";
+        // the IccCardStatus does not contain EID, but it is known from previous APDU
+        ics.eid = null;
+        AsyncResult ar = new AsyncResult(null, ics, null);
+        Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_ICC_STATUS_DONE, ar);
+        mUiccControllerUT.handleMessage(msg);
+
+        // since EID is known and we've gotten card status, the default eUICC card ID should be set
+        assertEquals(mUiccControllerUT.convertToPublicCardId(knownEidFromApdu),
+                mUiccControllerUT.getCardIdForDefaultEuicc());
+    }
 }