Merge "migrate cdma home eri from resource overlay to carrierconfig"
diff --git a/src/java/com/android/internal/telephony/CellularNetworkService.java b/src/java/com/android/internal/telephony/CellularNetworkService.java
index ee10023..2e5d058 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkService.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkService.java
@@ -71,7 +71,7 @@
         CellularNetworkServiceProvider(int slotId) {
             super(slotId);
 
-            mPhone = PhoneFactory.getPhone(getSlotId());
+            mPhone = PhoneFactory.getPhone(getSlotIndex());
 
             mHandlerThread = new HandlerThread(CellularNetworkService.class.getSimpleName());
             mHandlerThread.start();
@@ -488,13 +488,13 @@
     }
 
     @Override
-    protected NetworkServiceProvider createNetworkServiceProvider(int slotId) {
-        if (DBG) log("Cellular network service created for slot " + slotId);
-        if (!SubscriptionManager.isValidSlotIndex(slotId)) {
-            loge("Tried to Cellular network service with invalid slotId " + slotId);
+    public NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex) {
+        if (DBG) log("Cellular network service created for slot " + slotIndex);
+        if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
+            loge("Tried to Cellular network service with invalid slotId " + slotIndex);
             return null;
         }
-        return new CellularNetworkServiceProvider(slotId);
+        return new CellularNetworkServiceProvider(slotIndex);
     }
 
     private void log(String s) {
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 05374f1..9b24946 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2266,6 +2266,13 @@
      */
     default void enableModem(boolean enable, Message result) {};
 
+    /**
+     * Query whether logical modem is enabled or disabled
+     *
+     * @param result a Message to return to the requester
+     */
+    default void getModemStatus(Message result) {};
+
     default List<ClientRequestStats> getClientRequestStats() {
         return null;
     }
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index 01a78ff..616e9fe 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -22,11 +22,15 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.SystemProperties;
+import android.os.storage.StorageManager;
 import android.telephony.PhoneCapability;
 import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * This class manages phone's configuration which defines the potential capability (static) of the
  * phone and its current activated capability (current).
@@ -40,6 +44,8 @@
     public static final String SSSS = "";
     private static final String LOG_TAG = "PhoneCfgMgr";
     private static final int EVENT_SWITCH_DSDS_CONFIG_DONE = 100;
+    private static final int EVENT_GET_MODEM_STATUS = 101;
+    private static final int EVENT_GET_MODEM_STATUS_DONE = 102;
 
     private static PhoneConfigurationManager sInstance = null;
     private final Context mContext;
@@ -47,6 +53,8 @@
     private PhoneCapability mCurrentCapability;
     private final RadioConfig mRadioConfig;
     private final MainThreadHandler mHandler;
+    private final Phone[] mPhones;
+    private final Map<Integer, Boolean> mPhoneStatusMap;
 
     /**
      * Init method to instantiate the object
@@ -75,8 +83,20 @@
         mCurrentCapability = mStaticCapability;
         mRadioConfig = RadioConfig.getInstance(mContext);
         mHandler = new MainThreadHandler();
+        mPhoneStatusMap = new HashMap<>();
 
         notifyCapabilityChanged();
+
+        mPhones = PhoneFactory.getPhones();
+        if (!StorageManager.inCryptKeeperBounce()) {
+            for (Phone phone : mPhones) {
+                phone.mCi.registerForAvailable(mHandler, Phone.EVENT_RADIO_AVAILABLE, phone);
+            }
+        } else {
+            for (Phone phone : mPhones) {
+                phone.mCi.registerForOn(mHandler, Phone.EVENT_RADIO_ON, phone);
+            }
+        }
     }
 
     /**
@@ -96,9 +116,24 @@
     private final class MainThreadHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
+            AsyncResult ar;
+            Phone phone = null;
             switch (msg.what) {
+                case Phone.EVENT_RADIO_AVAILABLE:
+                case Phone.EVENT_RADIO_ON:
+                    log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON");
+                    if (msg.obj instanceof Phone) {
+                        phone = (Phone) msg.obj;
+                    }
+                    if (phone == null) {
+                        log("Unable to add phoneStatus to cache. "
+                                + "No phone object provided for event " + msg.what);
+                    } else {
+                        updatePhoneStatus(phone);
+                    }
+                    break;
                 case EVENT_SWITCH_DSDS_CONFIG_DONE:
-                    AsyncResult ar = (AsyncResult) msg.obj;
+                    ar = (AsyncResult) msg.obj;
                     if (ar != null && ar.exception == null) {
                         int numOfLiveModems = msg.arg1;
                         setMultiSimProperties(numOfLiveModems);
@@ -106,6 +141,17 @@
                         log(msg.what + " failure. Not switching multi-sim config." + ar.exception);
                     }
                     break;
+                case EVENT_GET_MODEM_STATUS_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar != null && ar.exception == null) {
+                        int phoneId = msg.arg1;
+                        boolean enabled = (boolean) ar.result;
+                        //update the cache each time getModemStatus is requested
+                        mPhoneStatusMap.put(phoneId, enabled);
+                    } else {
+                        log(msg.what + " failure. Not updating modem status." + ar.exception);
+                    }
+                    break;
             }
         }
     }
@@ -123,6 +169,48 @@
             return;
         }
         phone.mCi.enableModem(enable, result);
+        updatePhoneStatus(phone);
+    }
+
+    /**
+     * Get phone status (enabled/disabled)
+     *
+     * @param phone which phone to operate on
+     */
+    public boolean getPhoneStatus(Phone phone) {
+        if (phone == null) {
+            log("getPhonetatus failed phone is null");
+            return false;
+        }
+
+        int phoneId = phone.getPhoneId();
+
+        //use cache if the status has already been updated/queried
+        if (mPhoneStatusMap.containsKey(phoneId)) {
+            return mPhoneStatusMap.get(phoneId);
+        } else {
+            //return false if modem status is not in cache
+            updatePhoneStatus(phone);
+            return false;
+        }
+    }
+
+    /**
+     * method to call RIL getM
+     */
+    private void updatePhoneStatus(Phone phone) {
+        Message callback = Message.obtain(
+                mHandler, EVENT_GET_MODEM_STATUS_DONE, phone.getPhoneId(), 0 /**dummy arg*/);
+        phone.mCi.getModemStatus(callback);
+    }
+
+    /**
+     * Add status of the phone to the status HashMap
+     * @param phoneId
+     * @param status
+     */
+    public void addToPhoneStatusCache(int phoneId, boolean status) {
+        mPhoneStatusMap.put(phoneId, status);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 42b3691..043de1c 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -242,7 +242,8 @@
 
                 sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);
 
-                sPhoneConfigurationManager = PhoneConfigurationManager.init(sContext);
+                sPhoneConfigurationManager = PhoneConfigurationManager.init(
+                        sContext);
 
                 sCellularNetworkValidator = CellularNetworkValidator.make(sContext);
 
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index e0c4557..aca9074 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -258,6 +258,7 @@
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MCX);
         netCap.setNetworkSpecifier(new MatchAllNetworkSpecifier());
 
         NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 1e7b026..03cb8b1 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -84,6 +84,7 @@
 import android.telephony.SmsManager;
 import android.telephony.TelephonyHistogram;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.PrefNetworkMode;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
@@ -903,6 +904,37 @@
     }
 
     @Override
+    public void getModemStatus(Message result) {
+        IRadio radioProxy = getRadioProxy(result);
+        if (mRadioVersion.less(RADIO_HAL_VERSION_1_3)) {
+            if (RILJ_LOGV) riljLog("getModemStatus: not supported.");
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+            return;
+        }
+
+        android.hardware.radio.V1_3.IRadio radioProxy13 =
+                (android.hardware.radio.V1_3.IRadio) radioProxy;
+        if (radioProxy13 != null) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_MODEM_STATUS, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+            }
+
+            try {
+                radioProxy13.getModemStackStatus(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(rr, "getModemStatus", e);
+            }
+        }
+    }
+
+    @Override
     public void dial(String address, boolean isEmergencyCall, EmergencyNumber emergencyNumberInfo,
                      boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo,
                      Message result) {
@@ -1438,7 +1470,8 @@
 
                     if (RILJ_LOGD) {
                         riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                                + ",accessNetworkType=" + accessNetworkType + ",isRoaming="
+                                + ",accessNetworkType="
+                                + AccessNetworkType.toString(accessNetworkType) + ",isRoaming="
                                 + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile
                                 + ",addresses=" + addresses + ",dnses=" + dnses);
                     }
@@ -1456,7 +1489,8 @@
 
                     if (RILJ_LOGD) {
                         riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                                + ",accessNetworkType=" + accessNetworkType + ",isRoaming="
+                                + ",accessNetworkType="
+                                + AccessNetworkType.toString(accessNetworkType) + ",isRoaming="
                                 + isRoaming + ",allowRoaming=" + allowRoaming + ","
                                 + dataProfile + ",addresses=" + addresses + ",dnses=" + dnses);
                     }
@@ -2518,7 +2552,7 @@
     }
 
     @Override
-    public void setPreferredNetworkType(int networkType , Message result) {
+    public void setPreferredNetworkType(@PrefNetworkMode int networkType , Message result) {
         IRadio radioProxy = getRadioProxy(result);
         if (radioProxy != null) {
             RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, result,
@@ -2542,7 +2576,7 @@
                         (android.hardware.radio.V1_4.IRadio) radioProxy;
                 try {
                     radioProxy14.setPreferredNetworkTypeBitmap(
-                            rr.mSerial, RadioAccessFamily.getRafFromNetworkType(networkType));
+                            rr.mSerial, convertToHalRadioAccessFamily(networkType));
                 } catch (RemoteException | RuntimeException e) {
                     handleRadioProxyExceptionForRR(rr, "setPreferredNetworkTypeBitmap", e);
                 }
@@ -2550,6 +2584,13 @@
         }
     }
 
+    private static int convertToHalRadioAccessFamily(@PrefNetworkMode int networkMode) {
+        // android.hardware.radio.V1_0.RadioAccessFamily is one bit shift
+        // from TelephonyManager.NetworkTypeBitMask
+        int networkTypeBitmask = RadioAccessFamily.getRafFromNetworkType(networkMode);
+        return networkTypeBitmask << 1;
+    }
+
     @Override
     public void getPreferredNetworkType(Message result) {
         IRadio radioProxy = getRadioProxy(result);
@@ -5307,6 +5348,8 @@
                 return "RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA";
             case RIL_REQUEST_ENABLE_MODEM:
                 return "RIL_REQUEST_ENABLE_MODEM";
+            case RIL_REQUEST_GET_MODEM_STATUS:
+                return "RIL_REQUEST_GET_MODEM_STATUS";
             default: return "<unknown request>";
         }
     }
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 90d37e5..fd0b011 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -77,6 +77,7 @@
 import android.util.LocalLog;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.StatsLog;
 import android.util.TimestampedValue;
 
@@ -174,10 +175,10 @@
     private RegistrantList mVoiceRoamingOffRegistrants = new RegistrantList();
     private RegistrantList mDataRoamingOnRegistrants = new RegistrantList();
     private RegistrantList mDataRoamingOffRegistrants = new RegistrantList();
-    protected RegistrantList mAttachedRegistrants = new RegistrantList();
-    protected RegistrantList mDetachedRegistrants = new RegistrantList();
+    protected SparseArray<RegistrantList> mAttachedRegistrants = new SparseArray<>();
+    protected SparseArray<RegistrantList> mDetachedRegistrants = new SparseArray();
     private RegistrantList mVoiceRegStateOrRatChangedRegistrants = new RegistrantList();
-    private RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList();
+    private SparseArray<RegistrantList> mDataRegStateOrRatChangedRegistrants = new SparseArray<>();
     private RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
     private RegistrantList mNetworkDetachedRegistrants = new RegistrantList();
     private RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
@@ -573,9 +574,9 @@
                 CarrierServiceStateTracker.CARRIER_EVENT_VOICE_REGISTRATION, null);
         registerForNetworkDetached(mCSST,
                 CarrierServiceStateTracker.CARRIER_EVENT_VOICE_DEREGISTRATION, null);
-        registerForDataConnectionAttached(mCSST,
+        registerForDataConnectionAttached(TransportType.WWAN, mCSST,
                 CarrierServiceStateTracker.CARRIER_EVENT_DATA_REGISTRATION, null);
-        registerForDataConnectionDetached(mCSST,
+        registerForDataConnectionDetached(TransportType.WWAN, mCSST,
                 CarrierServiceStateTracker.CARRIER_EVENT_DATA_DEREGISTRATION, null);
         registerForImsCapabilityChanged(mCSST,
                 CarrierServiceStateTracker.CARRIER_EVENT_IMS_CAPABILITIES_CHANGED, null);
@@ -602,8 +603,15 @@
         }
 
         // If we are previously in service, we need to notify that we are out of service now.
-        if (mSS != null && mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
-            mDetachedRegistrants.notifyRegistrants();
+        for (int transport : mTransportManager.getAvailableTransports()) {
+            if (mSS != null) {
+                NetworkRegistrationState nrs = mSS.getNetworkRegistrationState(
+                        NetworkRegistrationState.DOMAIN_PS, transport);
+                if (nrs != null && nrs.isInService()
+                        && mDetachedRegistrants.get(transport) != null) {
+                    mDetachedRegistrants.get(transport).notifyRegistrants();
+                }
+            }
         }
 
         mSS = new ServiceState();
@@ -672,7 +680,9 @@
 
         // Tell everybody that the registration state and RAT have changed.
         notifyVoiceRegStateRilRadioTechnologyChanged();
-        notifyDataRegStateRilRadioTechnologyChanged();
+        for (int transport : mTransportManager.getAvailableTransports()) {
+            notifyDataRegStateRilRadioTechnologyChanged(transport);
+        }
     }
 
     @VisibleForTesting
@@ -738,14 +748,24 @@
      * AsyncResult in msg.obj where AsyncResult#result contains the
      * new RAT as an Integer Object.
      */
-    protected void notifyDataRegStateRilRadioTechnologyChanged() {
-        int rat = mSS.getRilDataRadioTechnology();
-        int drs = mSS.getDataRegState();
-        if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
+    protected void notifyDataRegStateRilRadioTechnologyChanged(int transport) {
+        NetworkRegistrationState nrs = mSS.getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, transport);
+        if (nrs != null) {
+            int rat = ServiceState.networkTypeToRilRadioTechnology(
+                    nrs.getAccessNetworkTechnology());
+            int drs = regCodeToServiceState(nrs.getRegState());
+            if (DBG) {
+                log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
+            }
 
+            RegistrantList registrantList = mDataRegStateOrRatChangedRegistrants.get(transport);
+            if (registrantList != null) {
+                registrantList.notifyResult(new Pair<>(drs, rat));
+            }
+        }
         mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
-                ServiceState.rilRadioTechnologyToString(rat));
-        mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));
+                ServiceState.rilRadioTechnologyToString(mSS.getRilDataRadioTechnology()));
     }
 
     /**
@@ -2962,16 +2982,48 @@
                 mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
                         && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
 
-        boolean hasDataAttached =
-                mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
-                        && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+        SparseBooleanArray hasDataAttached = new SparseBooleanArray(
+                mTransportManager.getAvailableTransports().length);
+        SparseBooleanArray hasDataDetached = new SparseBooleanArray(
+                mTransportManager.getAvailableTransports().length);
+        SparseBooleanArray hasRilDataRadioTechnologyChanged = new SparseBooleanArray(
+                mTransportManager.getAvailableTransports().length);
+        SparseBooleanArray hasDataRegStateChanged = new SparseBooleanArray(
+                mTransportManager.getAvailableTransports().length);
+        boolean anyDataRegChanged = false;
+        boolean anyDataRatChanged = false;
+        for (int transport : mTransportManager.getAvailableTransports()) {
+            NetworkRegistrationState oldNrs = mSS.getNetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, transport);
+            NetworkRegistrationState newNrs = mNewSS.getNetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, transport);
 
-        boolean hasDataDetached =
-                mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
-                        && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
+            boolean changed = (oldNrs == null || !oldNrs.isInService())
+                    && (newNrs != null && newNrs.isInService());
+            hasDataAttached.put(transport, changed);
 
-        boolean hasDataRegStateChanged =
-                mSS.getDataRegState() != mNewSS.getDataRegState();
+            changed = (oldNrs != null && oldNrs.isInService())
+                    && (newNrs == null || !newNrs.isInService());
+            hasDataDetached.put(transport, changed);
+
+            int oldRAT = oldNrs != null ? oldNrs.getAccessNetworkTechnology()
+                    : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+            int newRAT = newNrs != null ? newNrs.getAccessNetworkTechnology()
+                    : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+            hasRilDataRadioTechnologyChanged.put(transport, oldRAT != newRAT);
+            if (oldRAT != newRAT) {
+                anyDataRatChanged = true;
+            }
+
+            int oldRegState = oldNrs != null ? oldNrs.getRegState()
+                    : NetworkRegistrationState.REG_STATE_UNKNOWN;
+            int newRegState = newNrs != null ? newNrs.getRegState()
+                    : NetworkRegistrationState.REG_STATE_UNKNOWN;
+            hasDataRegStateChanged.put(transport, oldRegState != newRegState);
+            if (oldRegState != newRegState) {
+                anyDataRegChanged = true;
+            }
+        }
 
         boolean hasVoiceRegStateChanged =
                 mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
@@ -3001,9 +3053,6 @@
         boolean hasRilVoiceRadioTechnologyChanged =
                 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
 
-        boolean hasRilDataRadioTechnologyChanged =
-                mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology();
-
         boolean hasChanged = !mNewSS.equals(mSS);
 
         boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
@@ -3070,7 +3119,7 @@
         }
 
         // Add an event log when connection state changes
-        if (hasVoiceRegStateChanged || hasDataRegStateChanged) {
+        if (hasVoiceRegStateChanged || anyDataRegChanged) {
             EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE :
                             EventLogTags.CDMA_SERVICE_STATE_CHANGE,
                     mSS.getVoiceRegState(), mSS.getDataRegState(),
@@ -3127,19 +3176,13 @@
             updatePhoneObject();
         }
 
-        TelephonyManager tm =
-                (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
-
-        if (hasRilDataRadioTechnologyChanged) {
+        TelephonyManager tm = (TelephonyManager) mPhone.getContext().getSystemService(
+                Context.TELEPHONY_SERVICE);
+        if (anyDataRatChanged) {
             tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology());
             StatsLog.write(StatsLog.MOBILE_RADIO_TECHNOLOGY_CHANGED,
-                    ServiceState.rilRadioTechnologyToNetworkType(mSS.getRilDataRadioTechnology()),
-                    mPhone.getPhoneId());
-
-            if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
-                    == mSS.getRilDataRadioTechnology()) {
-                log("pollStateDone: IWLAN enabled");
-            }
+                    ServiceState.rilRadioTechnologyToNetworkType(
+                            mSS.getRilDataRadioTechnology()), mPhone.getPhoneId());
         }
 
         if (hasRegistered) {
@@ -3159,9 +3202,6 @@
             updateSpnDisplay();
 
             tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlpha());
-
-            String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId());
-            String prevCountryIsoCode = tm.getNetworkCountryIso(mPhone.getPhoneId());
             String operatorNumeric = mSS.getOperatorNumeric();
 
             if (!mPhone.isPhoneTypeGsm()) {
@@ -3213,34 +3253,56 @@
             TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS);
         }
 
-        if (hasDataAttached || has4gHandoff || hasDataDetached || hasRegistered
-                || hasDeregistered) {
+        boolean shouldLogAttachedChange = false;
+        boolean shouldLogRatChange = false;
+
+        if (hasRegistered || hasDeregistered) {
+            shouldLogAttachedChange = true;
+        }
+
+        if (has4gHandoff) {
+            mAttachedRegistrants.get(TransportType.WWAN).notifyRegistrants();
+            shouldLogAttachedChange = true;
+        }
+
+        if (hasRilVoiceRadioTechnologyChanged) {
+            shouldLogRatChange = true;
+            notifySignalStrength();
+        }
+
+        for (int transport : mTransportManager.getAvailableTransports()) {
+            if (hasRilDataRadioTechnologyChanged.get(transport)) {
+                shouldLogRatChange = true;
+                notifySignalStrength();
+            }
+
+            if (hasDataRegStateChanged.get(transport)
+                    || hasRilDataRadioTechnologyChanged.get(transport)) {
+                notifyDataRegStateRilRadioTechnologyChanged(transport);
+                mPhone.notifyDataConnection();
+            }
+
+            if (hasDataAttached.get(transport)) {
+                shouldLogAttachedChange = true;
+                mAttachedRegistrants.get(transport).notifyRegistrants();
+            }
+            if (hasDataDetached.get(transport)) {
+                shouldLogAttachedChange = true;
+                mDetachedRegistrants.get(transport).notifyRegistrants();
+            }
+        }
+
+        if (shouldLogAttachedChange) {
             logAttachChange();
         }
-
-        if (hasDataAttached || has4gHandoff) {
-            mAttachedRegistrants.notifyRegistrants();
-        }
-
-        if (hasDataDetached) {
-            mDetachedRegistrants.notifyRegistrants();
-        }
-
-        if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) {
+        if (shouldLogRatChange) {
             logRatChange();
-
-            notifySignalStrength();
         }
 
         if (hasVoiceRegStateChanged || hasRilVoiceRadioTechnologyChanged) {
             notifyVoiceRegStateRilRadioTechnologyChanged();
         }
 
-        if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
-            notifyDataRegStateRilRadioTechnologyChanged();
-            mPhone.notifyDataConnection();
-        }
-
         if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) {
             logRoamingChange();
         }
@@ -4020,38 +4082,72 @@
 
     /**
      * Registration point for transition into DataConnection attached.
+     * @param transport Transport type
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
+    public void registerForDataConnectionAttached(int transport, Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
-        mAttachedRegistrants.add(r);
+        if (mAttachedRegistrants.get(transport) == null) {
+            mAttachedRegistrants.put(transport, new RegistrantList());
+        }
+        mAttachedRegistrants.get(transport).add(r);
 
-        if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
+        if (mSS != null) {
+            NetworkRegistrationState netRegState = mSS.getNetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, transport);
+            if (netRegState == null || netRegState.isInService()) {
+                r.notifyRegistrant();
+            }
         }
     }
-    public void unregisterForDataConnectionAttached(Handler h) {
-        mAttachedRegistrants.remove(h);
+
+    /**
+     * Unregister for data attached event
+     *
+     * @param transport Transport type
+     * @param h Handler to notify
+     */
+    public void unregisterForDataConnectionAttached(int transport, Handler h) {
+        if (mAttachedRegistrants.get(transport) != null) {
+            mAttachedRegistrants.get(transport).remove(h);
+        }
     }
 
     /**
      * Registration point for transition into DataConnection detached.
+     * @param transport Transport type
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
+    public void registerForDataConnectionDetached(int transport, Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
-        mDetachedRegistrants.add(r);
+        if (mDetachedRegistrants.get(transport) == null) {
+            mDetachedRegistrants.put(transport, new RegistrantList());
+        }
+        mDetachedRegistrants.get(transport).add(r);
 
-        if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
+        if (mSS != null) {
+            NetworkRegistrationState netRegState = mSS.getNetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, transport);
+            if (netRegState != null && !netRegState.isInService()) {
+                r.notifyRegistrant();
+            }
         }
     }
-    public void unregisterForDataConnectionDetached(Handler h) {
-        mDetachedRegistrants.remove(h);
+
+    /**
+     * Unregister for data detatched event
+     *
+     * @param transport Transport type
+     * @param h Handler to notify
+     */
+    public void unregisterForDataConnectionDetached(int transport, Handler h) {
+        if (mDetachedRegistrants.get(transport) != null) {
+            mDetachedRegistrants.get(transport).remove(h);
+        }
     }
 
     /**
@@ -4078,17 +4174,31 @@
      * new radio technology will be returned AsyncResult#result as an Integer Object.
      * The AsyncResult will be in the notification Message#obj.
      *
+     * @param transport Transport
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) {
+    public void registerForDataRegStateOrRatChanged(int transport, Handler h, int what,
+                                                    Object obj) {
         Registrant r = new Registrant(h, what, obj);
-        mDataRegStateOrRatChangedRegistrants.add(r);
-        notifyDataRegStateRilRadioTechnologyChanged();
+        if (mDataRegStateOrRatChangedRegistrants.get(transport) == null) {
+            mDataRegStateOrRatChangedRegistrants.put(transport, new RegistrantList());
+        }
+        mDataRegStateOrRatChangedRegistrants.get(transport).add(r);
+        notifyDataRegStateRilRadioTechnologyChanged(transport);
     }
-    public void unregisterForDataRegStateOrRatChanged(Handler h) {
-        mDataRegStateOrRatChangedRegistrants.remove(h);
+
+    /**
+     * Unregister for data registration state changed or RAT changed event
+     *
+     * @param transport Transport
+     * @param h The handler
+     */
+    public void unregisterForDataRegStateOrRatChanged(int transport, Handler h) {
+        if (mDataRegStateOrRatChangedRegistrants.get(transport) != null) {
+            mDataRegStateOrRatChangedRegistrants.get(transport).remove(h);
+        }
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/TelephonyTester.java b/src/java/com/android/internal/telephony/TelephonyTester.java
index 0ab6ec8..e054183 100644
--- a/src/java/com/android/internal/telephony/TelephonyTester.java
+++ b/src/java/com/android/internal/telephony/TelephonyTester.java
@@ -24,6 +24,7 @@
 import android.os.BadParcelableException;
 import android.os.Build;
 import android.os.Bundle;
+import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.ims.ImsCallProfile;
@@ -148,10 +149,12 @@
                 if (DBG) log("sIntentReceiver.onReceive: action=" + action);
                 if (action.equals(mPhone.getActionDetached())) {
                     log("simulate detaching");
-                    mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants();
+                    mPhone.getServiceStateTracker().mDetachedRegistrants.get(TransportType.WWAN)
+                            .notifyRegistrants();
                 } else if (action.equals(mPhone.getActionAttached())) {
                     log("simulate attaching");
-                    mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
+                    mPhone.getServiceStateTracker().mAttachedRegistrants.get(TransportType.WWAN)
+                            .notifyRegistrants();
                 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) {
                     log("inject simulated conference event package");
                     handleTestConferenceEventPackage(context,
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index 26d9ec7..d7f0ae3 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -625,6 +625,10 @@
             if (apnType != ApnSetting.TYPE_NONE) error = true;
             apnType = ApnSetting.TYPE_EMERGENCY;
         }
+        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MCX)) {
+            if (apnType != ApnSetting.TYPE_NONE) error = true;
+            apnType = ApnSetting.TYPE_MCX;
+        }
         if (error) {
             // TODO: If this error condition is removed, the framework's handling of
             // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for
diff --git a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
index ae69631..41b8dab 100644
--- a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
+++ b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
@@ -67,7 +67,7 @@
         private CellularDataServiceProvider(int slotId) {
             super(slotId);
 
-            mPhone = PhoneFactory.getPhone(getSlotId());
+            mPhone = PhoneFactory.getPhone(getSlotIndex());
 
             mHandlerThread = new HandlerThread(CellularDataService.class.getSimpleName());
             mHandlerThread.start();
@@ -125,10 +125,10 @@
         }
 
         @Override
-        public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming,
+        public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                                   boolean allowRoaming, int reason, LinkProperties linkProperties,
                                   DataServiceCallback callback) {
-            if (DBG) log("setupDataCall " + getSlotId());
+            if (DBG) log("setupDataCall " + getSlotIndex());
 
             Message message = null;
             // Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -138,13 +138,13 @@
                 mCallbackMap.put(message, callback);
             }
 
-            mPhone.mCi.setupDataCall(radioTechnology, dataProfile, isRoaming, allowRoaming, reason,
-                    linkProperties, message);
+            mPhone.mCi.setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming,
+                    reason, linkProperties, message);
         }
 
         @Override
         public void deactivateDataCall(int cid, int reason, DataServiceCallback callback) {
-            if (DBG) log("deactivateDataCall " + getSlotId());
+            if (DBG) log("deactivateDataCall " + getSlotIndex());
 
             Message message = null;
             // Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -160,7 +160,7 @@
         @Override
         public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
                                         DataServiceCallback callback) {
-            if (DBG) log("setInitialAttachApn " + getSlotId());
+            if (DBG) log("setInitialAttachApn " + getSlotIndex());
 
             Message message = null;
             // Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -176,7 +176,7 @@
         @Override
         public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
                                    DataServiceCallback callback) {
-            if (DBG) log("setDataProfile " + getSlotId());
+            if (DBG) log("setDataProfile " + getSlotIndex());
 
             Message message = null;
             // Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -191,7 +191,7 @@
 
         @Override
         public void getDataCallList(DataServiceCallback callback) {
-            if (DBG) log("getDataCallList " + getSlotId());
+            if (DBG) log("getDataCallList " + getSlotIndex());
 
             Message message = null;
             // Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -211,13 +211,13 @@
     }
 
     @Override
-    public DataServiceProvider createDataServiceProvider(int slotId) {
-        log("Cellular data service created for slot " + slotId);
-        if (!SubscriptionManager.isValidSlotIndex(slotId)) {
-            loge("Tried to cellular data service with invalid slotId " + slotId);
+    public DataServiceProvider onCreateDataServiceProvider(int slotIndex) {
+        log("Cellular data service created for slot " + slotIndex);
+        if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
+            loge("Tried to cellular data service with invalid slotId " + slotIndex);
             return null;
         }
-        return new CellularDataServiceProvider(slotId);
+        return new CellularDataServiceProvider(slotIndex);
     }
 
     private void log(String s) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 51dc0ee..a751bbc 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -41,6 +41,7 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.provider.Telephony;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.DataFailCause;
 import android.telephony.Rlog;
@@ -1125,6 +1126,10 @@
                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
                         break;
                     }
+                    case PhoneConstants.APN_TYPE_MCX: {
+                        result.addCapability(NetworkCapabilities.NET_CAPABILITY_MCX);
+                        break;
+                    }
                     default:
                 }
             }
@@ -1191,6 +1196,27 @@
     }
 
     /**
+     * @return {@code True} if 464xlat should be skipped.
+     */
+    @VisibleForTesting
+    public boolean shouldSkip464Xlat() {
+        switch (mApnSetting.getSkip464Xlat()) {
+            case Telephony.Carriers.SKIP_464XLAT_ENABLE:
+                return true;
+            case Telephony.Carriers.SKIP_464XLAT_DISABLE:
+                return false;
+            case Telephony.Carriers.SKIP_464XLAT_DEFAULT:
+            default:
+                break;
+        }
+
+        // As default, return true if ims and no internet
+        final NetworkCapabilities nc = getNetworkCapabilities();
+        return nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+                && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+    }
+
+    /**
      * @return {@code} true iff. {@code address} is a literal IPv4 or IPv6 address.
      */
     @VisibleForTesting
@@ -1358,7 +1384,8 @@
             if (DBG) log("DcDefaultState: enter");
 
             // Register for DRS or RAT change
-            mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(getHandler(),
+            mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
+                    mDataServiceManager.getTransportType(), getHandler(),
                     DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED, null);
 
             mPhone.getServiceStateTracker().registerForDataRoamingOn(getHandler(),
@@ -1374,7 +1401,8 @@
             if (DBG) log("DcDefaultState: exit");
 
             // Unregister for DRS or RAT change.
-            mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(getHandler());
+            mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(
+                    mDataServiceManager.getTransportType(), getHandler());
 
             mPhone.getServiceStateTracker().unregisterForDataRoamingOn(getHandler());
             mPhone.getServiceStateTracker().unregisterForDataRoamingOff(getHandler());
@@ -1803,6 +1831,9 @@
             }
             misc.subscriberId = mPhone.getSubscriberId();
 
+            // set skip464xlat if it is not default otherwise
+            misc.skip464xlat = shouldSkip464Xlat();
+
             mRestrictedNetworkOverride = shouldRestrictNetwork();
             mUnmeteredUseOnly = isUnmeteredUseOnly();
 
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 7debf56..db965f9 100755
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -66,6 +66,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellLocation;
 import android.telephony.DataFailCause;
+import android.telephony.NetworkRegistrationState;
 import android.telephony.PcoData;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
@@ -733,9 +734,9 @@
     }
 
     public void registerServiceStateTrackerEvents() {
-        mPhone.getServiceStateTracker().registerForDataConnectionAttached(this,
+        mPhone.getServiceStateTracker().registerForDataConnectionAttached(mTransportType, this,
                 DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);
-        mPhone.getServiceStateTracker().registerForDataConnectionDetached(this,
+        mPhone.getServiceStateTracker().registerForDataConnectionDetached(mTransportType, this,
                 DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);
         mPhone.getServiceStateTracker().registerForDataRoamingOn(this,
                 DctConstants.EVENT_ROAMING_ON, null);
@@ -745,18 +746,19 @@
                 DctConstants.EVENT_PS_RESTRICT_ENABLED, null);
         mPhone.getServiceStateTracker().registerForPsRestrictedDisabled(this,
                 DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
-        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(this,
+        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
                 DctConstants.EVENT_DATA_RAT_CHANGED, null);
     }
 
     public void unregisterServiceStateTrackerEvents() {
-        mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(this);
-        mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(this);
+        mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(mTransportType, this);
+        mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(mTransportType, this);
         mPhone.getServiceStateTracker().unregisterForDataRoamingOn(this);
         mPhone.getServiceStateTracker().unregisterForDataRoamingOff(this);
         mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
         mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
-        mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(this);
+        mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType,
+                this);
     }
 
     private void registerForAllEvents() {
@@ -969,7 +971,7 @@
                 com.android.internal.R.array.networkAttributes);
         for (String networkConfigString : networkConfigStrings) {
             NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
-            ApnContext apnContext = null;
+            ApnContext apnContext;
 
             switch (networkConfig.type) {
             case ConnectivityManager.TYPE_MOBILE:
@@ -1219,7 +1221,7 @@
         boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
         boolean radioStateFromCarrier = mPhone.getServiceStateTracker().getPowerStateFromCarrier();
         // TODO: Remove this hack added by ag/641832.
-        int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
+        int radioTech = getDataRat();
         if (radioTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
             desiredPowerState = true;
             radioStateFromCarrier = true;
@@ -1427,7 +1429,7 @@
                 apnContext.requestLog(str);
                 apnContext.setState(DctConstants.State.IDLE);
             }
-            int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
+            int radioTech = getDataRat();
             apnContext.setConcurrentVoiceAndDataAllowed(mPhone.getServiceStateTracker()
                     .isConcurrentVoiceAndDataAllowed());
             if (apnContext.getState() == DctConstants.State.IDLE) {
@@ -1674,7 +1676,7 @@
             log("fetchDunApns: net.tethering.noprovisioning=true ret: empty list");
             return new ArrayList<ApnSetting>(0);
         }
-        int bearer = mPhone.getServiceState().getRilDataRadioTechnology();
+        int bearer = getDataRat();
         ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
         ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>();
 
@@ -1765,7 +1767,7 @@
      */
     private boolean teardownForDun() {
         // CDMA always needs to do this the profile id is correct
-        final int rilRat = mPhone.getServiceState().getRilDataRadioTechnology();
+        final int rilRat = getDataRat();
         if (ServiceState.isCdma(rilRat)) return true;
 
         ArrayList<ApnSetting> apns = fetchDunApns();
@@ -1855,7 +1857,7 @@
         // On GSM/LTE we can share existing apn connections provided they support
         // this type.
         if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DUN)
-                || ServiceState.isGsm(mPhone.getServiceState().getRilDataRadioTechnology())) {
+                || ServiceState.isGsm(getDataRat())) {
             dataConnection = checkForCompatibleConnectedApnContext(apnContext);
             if (dataConnection != null) {
                 // Get the apn setting used by the data connection
@@ -2107,9 +2109,8 @@
         boolean retry = true;
         String reason = apnContext.getReason();
 
-        if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
-                (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())
-                 && isHigherPriorityApnContextActive(apnContext))) {
+        if (Phone.REASON_RADIO_TURNED_OFF.equals(reason) || (isOnlySingleDcAllowed(getDataRat())
+                && isHigherPriorityApnContextActive(apnContext))) {
             retry = false;
         }
         return retry;
@@ -2409,8 +2410,7 @@
             cleanUpConnectionInternal(true, releaseType, apnContext);
         }
 
-        if (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())
-                && !isHigherPriorityApnContextActive(apnContext)) {
+        if (isOnlySingleDcAllowed(getDataRat()) && !isHigherPriorityApnContextActive(apnContext)) {
             if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled");
             // If the highest priority APN is disabled and only single
             // data call is allowed, try to setup data call on other connectable APN.
@@ -2983,7 +2983,7 @@
             }
             apnContext.setApnSetting(null);
             apnContext.setDataConnection(null);
-            if (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())) {
+            if (isOnlySingleDcAllowed(getDataRat())) {
                 if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn");
                 setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
                         RetryFailures.ALWAYS);
@@ -3179,7 +3179,8 @@
             dest.isEnabled(), networkTypeBitmask, dest.getProfileId(),
             (dest.isPersistent() || src.isPersistent()), dest.getMaxConns(),
             dest.getWaitTime(), dest.getMaxConnsTime(), dest.getMtu(), dest.getMvnoType(),
-            dest.getMvnoMatchData(), dest.getApnSetId(), dest.getCarrierId());
+            dest.getMvnoMatchData(), dest.getApnSetId(), dest.getCarrierId(),
+            dest.getSkip464Xlat());
     }
 
     private DataConnection createDataConnection() {
@@ -3502,8 +3503,7 @@
                 break;
 
             case DctConstants.EVENT_DATA_RAT_CHANGED:
-                if (mPhone.getServiceState().getRilDataRadioTechnology()
-                        == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
+                if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
                     // unknown rat is an exception for data rat change. It's only received when out
                     // of service and is not applicable for apn bearer bitmask. We should bypass the
                     // check of waiting apn list and keep the data connection on, and no need to
@@ -4113,8 +4113,7 @@
         if (mAllApnSettings.isEmpty()) {
             cleanUpAllConnectionsInternal(detach, Phone.REASON_APN_CHANGED);
         } else {
-            int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
-            if (radioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
+            if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
                 // unknown rat is an exception for data rat change. Its only received when out of
                 // service and is not applicable for apn bearer bitmask. We should bypass the check
                 // of waiting apn list and keep the data connection on.
@@ -4123,8 +4122,7 @@
             for (ApnContext apnContext : mApnContexts.values()) {
                 ArrayList<ApnSetting> currentWaitingApns = apnContext.getWaitingApns();
                 ArrayList<ApnSetting> waitingApns = buildWaitingApns(
-                        apnContext.getApnType(),
-                        mPhone.getServiceState().getRilDataRadioTechnology());
+                        apnContext.getApnType(), getDataRat());
                 if (VDBG) log("new waitingApns:" + waitingApns);
                 if ((currentWaitingApns != null)
                         && ((waitingApns.size() != currentWaitingApns.size())
@@ -4737,4 +4735,14 @@
         }
         return "UNKNOWN";
     }
+
+    private int getDataRat() {
+        ServiceState ss = mPhone.getServiceState();
+        NetworkRegistrationState nrs = ss.getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, mTransportType);
+        if (nrs != null) {
+            return ServiceState.networkTypeToRilRadioTechnology(nrs.getAccessNetworkTechnology());
+        }
+        return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java b/src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java
index ffe4bac..fd00dff 100644
--- a/src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java
+++ b/src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java
@@ -131,6 +131,9 @@
         synchronized (RcsMessageStoreController.class) {
             if (sInstance == null) {
                 sInstance = new RcsMessageStoreController(context.getContentResolver());
+                if (ServiceManager.getService(RCS_SERVICE_NAME) == null) {
+                    ServiceManager.addService(RCS_SERVICE_NAME, sInstance);
+                }
             } else {
                 Rlog.e(TAG, "init() called multiple times! sInstance = " + sInstance);
             }
@@ -138,20 +141,8 @@
         return sInstance;
     }
 
-    private RcsMessageStoreController(ContentResolver contentResolver) {
-        mContentResolver = contentResolver;
-        mParticipantQueryHelper = new RcsParticipantQueryHelper(contentResolver);
-        mMessageQueryHelper = new RcsMessageQueryHelper(contentResolver);
-        mThreadQueryHelper = new RcsThreadQueryHelper(contentResolver, mParticipantQueryHelper);
-        mEventQueryHelper = new RcsEventQueryHelper(contentResolver);
-        mMessageStoreUtil = new RcsMessageStoreUtil(contentResolver);
-        if (ServiceManager.getService(RCS_SERVICE_NAME) == null) {
-            ServiceManager.addService(RCS_SERVICE_NAME, this);
-        }
-    }
-
     @VisibleForTesting
-    public RcsMessageStoreController(ContentResolver contentResolver, Void unused) {
+    public RcsMessageStoreController(ContentResolver contentResolver) {
         mContentResolver = contentResolver;
         mParticipantQueryHelper = new RcsParticipantQueryHelper(contentResolver);
         mMessageQueryHelper = new RcsMessageQueryHelper(contentResolver);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index ab39212..79322e5 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -272,10 +272,13 @@
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
         mWakeLock.setReferenceCounted(false);
 
-        if (mDefaultPhone.getServiceStateTracker() != null) {
-            mDefaultPhone.getServiceStateTracker()
-                    .registerForDataRegStateOrRatChanged(this,
-                            EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED, null);
+        if (mDefaultPhone.getServiceStateTracker() != null
+                && mDefaultPhone.getTransportManager() != null) {
+            for (int transport : mDefaultPhone.getTransportManager().getAvailableTransports()) {
+                mDefaultPhone.getServiceStateTracker()
+                        .registerForDataRegStateOrRatChanged(transport, this,
+                                EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED, null);
+            }
         }
         // Sets the Voice reg state to STATE_OUT_OF_SERVICE and also queries the data service
         // state. We don't ever need the voice reg state to be anything other than in or out of
@@ -301,8 +304,10 @@
 
         //Force all referenced classes to unregister their former registered events
         if (mDefaultPhone != null && mDefaultPhone.getServiceStateTracker() != null) {
-            mDefaultPhone.getServiceStateTracker().
-                    unregisterForDataRegStateOrRatChanged(this);
+            for (int transport : mDefaultPhone.getTransportManager().getAvailableTransports()) {
+                mDefaultPhone.getServiceStateTracker()
+                        .unregisterForDataRegStateOrRatChanged(transport, this);
+            }
             mDefaultPhone.unregisterForServiceStateChanged(this);
         }
     }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index de71add..74f4bd2 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -113,6 +113,7 @@
 import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Pattern;
@@ -499,8 +500,12 @@
 
 
     //***** Constructors
-
     public ImsPhoneCallTracker(ImsPhone phone) {
+        this(phone, phone.getContext().getMainExecutor());
+    }
+
+    @VisibleForTesting
+    public ImsPhoneCallTracker(ImsPhone phone, Executor executor) {
         this.mPhone = phone;
 
         mMetrics = TelephonyMetrics.getInstance();
@@ -523,6 +528,7 @@
         mVtDataUsageSnapshot = new NetworkStats(currentTime, 1);
         mVtDataUsageUidSnapshot = new NetworkStats(currentTime, 1);
 
+        // Allow the executor to be specified for testing.
         mImsManagerConnector = new ImsManager.Connector(phone.getContext(), phone.getPhoneId(),
                 new ImsManager.Connector.Listener() {
                     @Override
@@ -535,7 +541,7 @@
                     public void connectionUnavailable() {
                         stopListeningForCalls();
                     }
-                });
+                }, executor);
         mImsManagerConnector.connect();
     }
 
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 72f3a38..6f23b2a 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -38,6 +38,7 @@
 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;
 import android.telephony.ims.ImsSsInfo;
@@ -54,6 +55,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.uicc.IccRecords;
 
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -1531,15 +1533,17 @@
                 sb.append(getErrorMessage(ar));
             }
         } else {
-            ImsSsInfo[] infos = (ImsSsInfo[])ar.result;
-            if (infos.length == 0) {
+            List<ImsSsInfo> infos = (List<ImsSsInfo>) ar.result;
+            if (infos.size() == 0) {
                 sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
             } else {
-                for (int i = 0, s = infos.length; i < s ; i++) {
-                    if (infos[i].getIncomingCommunicationBarringNumber() != null) {
-                        sb.append("Num: " + infos[i].getIncomingCommunicationBarringNumber()
-                                + " status: " + infos[i].getStatus() + "\n");
-                    } else if (infos[i].getStatus() == 1) {
+                ImsSsInfo info;
+                for (int i = 0, s = infos.size(); i < s; i++) {
+                    info = infos.get(i);
+                    if (info.getIncomingCommunicationBarringNumber() != null) {
+                        sb.append("Num: " + info.getIncomingCommunicationBarringNumber()
+                                + " status: " + info.getStatus() + "\n");
+                    } else if (info.getStatus() == 1) {
                         sb.append(mContext.getText(com.android.internal
                                 .R.string.serviceEnabled));
                     } else {
@@ -1772,8 +1776,16 @@
                     onQueryClirComplete(new AsyncResult(null, clirInfo, ex));
                 } else if (ssData.isTypeCF()) {
                     Rlog.d(LOG_TAG, "CALL FORWARD INTERROGATION");
-                    onQueryCfComplete(new AsyncResult(null, mPhone
-                            .handleCfQueryResult(ssData.getCallForwardInfo()), ex));
+                    // Have to translate to an array, since the modem still returns it in the
+                    // ImsCallForwardInfo[] format.
+                    List<ImsCallForwardInfo> mCfInfos = ssData.getCallForwardInfo();
+                    ImsCallForwardInfo[] mCfInfosCompat = null;
+                    if (mCfInfos != null) {
+                        mCfInfosCompat = new ImsCallForwardInfo[mCfInfos.size()];
+                        mCfInfosCompat = mCfInfos.toArray(mCfInfosCompat);
+                    }
+                    onQueryCfComplete(new AsyncResult(null, mPhone.handleCfQueryResult(
+                            mCfInfosCompat), ex));
                 } else if (ssData.isTypeBarring()) {
                     onSuppSvcQueryComplete(new AsyncResult(null, ssData.getSuppServiceInfoCompat(),
                             ex));
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 23eabad..99f3aa5 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony.uicc;
 
+import static android.telephony.TelephonyManager.UNINITIALIZED_CARD_ID;
+import static android.telephony.TelephonyManager.UNSUPPORTED_CARD_ID;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -128,6 +131,8 @@
     // The array index is the card ID (int).
     // This mapping exists to expose card-based functionality without exposing the EID, which is
     // considered sensetive information.
+    // mCardStrings is populated using values from the IccSlotStatus and IccCardStatus. For
+    // HAL < 1.2, these do not contain the EID or the ICCID, so mCardStrings will be empty
     private ArrayList<String> mCardStrings;
 
     // This is the card ID of the default eUICC. It starts as UNINITIALIZED_CARD_ID.
@@ -213,7 +218,7 @@
 
         mLauncher = new UiccStateChangedLauncher(c, this);
         mCardStrings = loadCardStrings();
-        mDefaultEuiccCardId = TelephonyManager.UNINITIALIZED_CARD_ID;
+        mDefaultEuiccCardId = UNINITIALIZED_CARD_ID;
     }
 
     private int getSlotIdFromPhoneId(int phoneId) {
@@ -555,7 +560,8 @@
 
         if (eidIsNotSupported(status)) {
             // we will never get EID from the HAL, so set mDefaultEuiccCardId to UNSUPPORTED_CARD_ID
-            mDefaultEuiccCardId = TelephonyManager.UNSUPPORTED_CARD_ID;
+            if (DBG) log("eid is not supported");
+            mDefaultEuiccCardId = UNSUPPORTED_CARD_ID;
         }
         mPhoneIdToSlotId[index] = slotId;
 
@@ -589,7 +595,7 @@
         // EID may be unpopulated if RadioConfig<1.2
         // If so, just register for EID loaded and skip this stuff
         if (isEuicc && cardString == null
-                && mDefaultEuiccCardId != TelephonyManager.UNSUPPORTED_CARD_ID) {
+                && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) {
             ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index);
         }
 
@@ -633,18 +639,24 @@
      * to match to a card ID.
      *
      * @return the matching cardId, or UNINITIALIZED_CARD_ID if the card string does not map to a
-     * currently loaded cardId
+     * currently loaded cardId, or UNSUPPORTED_CARD_ID if the device does not support card IDs
      */
     public int convertToPublicCardId(String cardString) {
-        if (TextUtils.isEmpty(cardString)) {
-            return TelephonyManager.UNINITIALIZED_CARD_ID;
+        if (mDefaultEuiccCardId == UNSUPPORTED_CARD_ID) {
+            // even if cardString is not an EID, if EID is not supported (e.g. HAL < 1.2) we can't
+            // guarentee a working card ID implementation, so return UNSUPPORTED_CARD_ID
+            return UNSUPPORTED_CARD_ID;
         }
+        if (TextUtils.isEmpty(cardString)) {
+            return UNINITIALIZED_CARD_ID;
+        }
+
         if (cardString.length() < EID_LENGTH) {
             cardString = IccUtils.stripTrailingFs(cardString);
         }
         int id = mCardStrings.indexOf(cardString);
         if (id == -1) {
-            return TelephonyManager.UNINITIALIZED_CARD_ID;
+            return UNINITIALIZED_CARD_ID;
         } else {
             return id;
         }
@@ -916,7 +928,7 @@
         // set mCardStrings and the defaultEuiccCardId using the now available EID
         String eid = ((EuiccCard) card).getEid();
         addCardId(eid);
-        if (mDefaultEuiccCardId == TelephonyManager.UNINITIALIZED_CARD_ID) {
+        if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID) {
             // TODO(b/122738148) the default eUICC should not be removable
             mDefaultEuiccCardId = convertToPublicCardId(eid);
             log("onEidReady: eid=" + eid + " slot=" + slotId + " mDefaultEuiccCardId="
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
index 1eac933..fdefa1d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
@@ -207,7 +207,7 @@
         list.add(new CarrierIdentifier(MCC4, MNC4, null, null, null, null));
         list.add(new CarrierIdentifier(MCC5, MNC5, null, null, null, null));
 
-        List<Boolean> result = rules.isCarrierIdentifiersAllowed(list);
+        List<Boolean> result = rules.areCarrierIdentifiersAllowed(list);
 
         List<Boolean> expected =
                 Arrays.asList(true, true, true, true, true, true, true, true, true, true, true);
@@ -247,7 +247,7 @@
         list.add(new CarrierIdentifier(MCC4, MNC4, null, null, null, null));
         list.add(new CarrierIdentifier(MCC5, MNC5, null, null, null, null));
 
-        List<Boolean> result = rules.isCarrierIdentifiersAllowed(list);
+        List<Boolean> result = rules.areCarrierIdentifiersAllowed(list);
 
         List<Boolean> expected =
                 Arrays.asList(true, true, true, true, true, true, true,
@@ -282,7 +282,7 @@
         list.add(new CarrierIdentifier(MCC1, MNC3, null, null, null, null));
         list.add(new CarrierIdentifier(MCC1, MNC4, null, null, null, null));
 
-        List<Boolean> result = rules.isCarrierIdentifiersAllowed(list);
+        List<Boolean> result = rules.areCarrierIdentifiersAllowed(list);
 
         List<Boolean> expected = Arrays.asList(true, true, true, true, false, false);
         assertTrue(result.equals(expected));
@@ -309,7 +309,7 @@
         list.add(new CarrierIdentifier(MCC4, MNC4, null, null, null, null));
         list.add(new CarrierIdentifier(MCC5, MNC5, null, null, null, null));
 
-        List<Boolean> result = rules.isCarrierIdentifiersAllowed(list);
+        List<Boolean> result = rules.areCarrierIdentifiersAllowed(list);
 
         List<Boolean> expected = Arrays.asList(true, true, true, true);
         assertTrue(result.equals(expected));
@@ -335,7 +335,7 @@
         list.add(new CarrierIdentifier(MCC4, MNC4, null, null, null, null));
         list.add(new CarrierIdentifier(MCC5, MNC5, null, null, null, null));
 
-        List<Boolean> result = rules.isCarrierIdentifiersAllowed(list);
+        List<Boolean> result = rules.areCarrierIdentifiersAllowed(list);
 
         List<Boolean> expected = Arrays.asList(false, false, false);
         assertTrue(result.equals(expected));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 6ad5b8f..2f20579 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -903,7 +903,8 @@
 
         waitForMs(100);
 
-        sst.registerForDataConnectionAttached(mTestHandler, EVENT_DATA_CONNECTION_ATTACHED, null);
+        sst.registerForDataConnectionAttached(TransportType.WWAN, mTestHandler,
+                EVENT_DATA_CONNECTION_ATTACHED, null);
 
         // set service state in service and trigger events to post message on handler
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_ROAMING);
@@ -925,7 +926,7 @@
         waitForMs(100);
 
         // Unregister registrant
-        sst.unregisterForDataConnectionAttached(mTestHandler);
+        sst.unregisterForDataConnectionAttached(TransportType.WWAN, mTestHandler);
 
         // set service state in service
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_ROAMING);
@@ -949,7 +950,8 @@
 
         waitForMs(100);
 
-        sst.registerForDataConnectionAttached(mTestHandler, EVENT_DATA_CONNECTION_ATTACHED, null);
+        sst.registerForDataConnectionAttached(TransportType.WWAN, mTestHandler,
+                EVENT_DATA_CONNECTION_ATTACHED, null);
 
         // set service state in service and trigger events to post message on handler
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_ROAMING);
@@ -971,7 +973,7 @@
         waitForMs(100);
 
         // Unregister registrant
-        sst.unregisterForDataConnectionAttached(mTestHandler);
+        sst.unregisterForDataConnectionAttached(TransportType.WWAN, mTestHandler);
 
         // set service state in service
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_ROAMING);
@@ -993,7 +995,8 @@
         mSimulatedCommands.setDataRegState(NetworkRegistrationState.REG_STATE_ROAMING);
         mSimulatedCommands.notifyNetworkStateChanged();
 
-        sst.registerForDataConnectionDetached(mTestHandler, EVENT_DATA_CONNECTION_DETACHED, null);
+        sst.registerForDataConnectionDetached(TransportType.WWAN, mTestHandler,
+                EVENT_DATA_CONNECTION_DETACHED, null);
 
         // set service state out of service and trigger events to post message on handler
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_UNKNOWN);
@@ -1015,7 +1018,7 @@
         waitForMs(100);
 
         // Unregister registrant
-        sst.unregisterForDataConnectionDetached(mTestHandler);
+        sst.unregisterForDataConnectionDetached(TransportType.WWAN, mTestHandler);
 
         // set service state out of service
         mSimulatedCommands.setVoiceRegState(NetworkRegistrationState.REG_STATE_UNKNOWN);
@@ -1050,11 +1053,12 @@
     @Test
     @MediumTest
     public void testRegisterForDataRegStateOrRatChange() {
-        int drs = NetworkRegistrationState.REG_STATE_HOME;
+        int drs = ServiceState.STATE_IN_SERVICE;
         int rat = sst.mSS.RIL_RADIO_TECHNOLOGY_LTE;
         sst.mSS.setRilDataRadioTechnology(rat);
         sst.mSS.setDataRegState(drs);
-        sst.registerForDataRegStateOrRatChanged(mTestHandler, EVENT_DATA_RAT_CHANGED, null);
+        sst.registerForDataRegStateOrRatChanged(TransportType.WWAN, mTestHandler,
+                EVENT_DATA_RAT_CHANGED, null);
 
         waitForMs(100);
 
@@ -1062,7 +1066,8 @@
         ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong());
         assertEquals(EVENT_DATA_RAT_CHANGED, messageArgumentCaptor.getValue().what);
-        assertEquals(new Pair<Integer, Integer>(drs, rat),
+        assertEquals(new Pair<Integer, Integer>(ServiceState.STATE_IN_SERVICE,
+                        ServiceState.RIL_RADIO_TECHNOLOGY_LTE),
                 ((AsyncResult)messageArgumentCaptor.getValue().obj).result);
     }
 
@@ -1423,7 +1428,8 @@
 
         sst.registerForDataRoamingOff(mTestHandler, EVENT_DATA_ROAMING_OFF, null, true);
         sst.registerForVoiceRoamingOff(mTestHandler, EVENT_VOICE_ROAMING_OFF, null);
-        sst.registerForDataConnectionDetached(mTestHandler, EVENT_DATA_CONNECTION_DETACHED, null);
+        sst.registerForDataConnectionDetached(TransportType.WWAN, mTestHandler,
+                EVENT_DATA_CONNECTION_DETACHED, null);
 
         // Call functions which would trigger posting of message on test handler
         doReturn(false).when(mPhone).isPhoneTypeGsm();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index a18fb28..2b330db 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -45,6 +45,7 @@
 import android.provider.BlockedNumberContract;
 import android.provider.Settings;
 import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.NetworkRegistrationState;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -143,6 +144,8 @@
     @Mock
     protected ServiceState mServiceState;
     @Mock
+    protected NetworkRegistrationState mNetworkRegistrationState;
+    @Mock
     protected SimulatedCommandsVerifier mSimulatedCommandsVerifier;
     @Mock
     protected IDeviceIdleController mIDeviceIdleController;
@@ -491,6 +494,8 @@
         doReturn(TransportType.WWAN).when(mTransportManager).getCurrentTransport(anyInt());
         doReturn(true).when(mDataEnabledSettings).isDataEnabled();
         doReturn(true).when(mDataEnabledSettings).isInternalDataEnabled();
+        doReturn(mNetworkRegistrationState).when(mServiceState).getNetworkRegistrationState(
+                anyInt(), anyInt());
 
         //SIM
         doReturn(1).when(mTelephonyManager).getSimCount();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
index b4ce3e3..3be4104 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
@@ -129,6 +129,7 @@
         assertEquals(a1.getMvnoMatchData(), a2.getMvnoMatchData());
         assertEquals(a1.getNetworkTypeBitmask(), a2.getNetworkTypeBitmask());
         assertEquals(a1.getApnSetId(), a2.getApnSetId());
+        assertEquals(a1.getSkip464Xlat(), a2.getSkip464Xlat());
     }
 
     @Test
@@ -229,7 +230,7 @@
         expectedApn = ApnSetting.makeApnSetting(
                 -1, "12345", "Name", "apn", "", -1, null, "", -1, "", "", 0,
                 mmsTypesBitmask, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
-                0, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "testspn", 3, -1);
+                0, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "testspn", 3, -1, -1);
         assertApnSettingEqual(expectedApn, ApnSetting.fromString(testString));
 
         // A v6 string with carrierId=100
@@ -239,7 +240,17 @@
         expectedApn = ApnSetting.makeApnSetting(
             -1, "12345", "Name", "apn", "", -1, null, "", -1, "", "", 0,
             mmsTypesBitmask, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
-            0, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "testspn", 3, 100);
+            0, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "testspn", 3, 100, -1);
+        assertApnSettingEqual(expectedApn, ApnSetting.fromString(testString));
+
+        // A v7 string with skip_464xlat=1
+        testString =
+            "[ApnSettingV7] Name,apn,,,,,,,,,123,45,,mms|*,IPV6,IP,true,0,,,,,,,spn,testspn,0,3,"
+                + "-1, 1";
+        expectedApn = ApnSetting.makeApnSetting(
+            -1, "12345", "Name", "apn", "", -1, null, "", -1, "", "", 0,
+            mmsTypesBitmask, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
+            0, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "testspn", 3, -1, 1);
         assertApnSettingEqual(expectedApn, ApnSetting.fromString(testString));
 
         // Return no apn if insufficient fields given.
@@ -279,7 +290,7 @@
         expectedApns.add(ApnSetting.makeApnSetting(
                 -1, "12346", "Name1", "apn2", "", -1, null, "", -1, "", "", 0,
                 mmsTypesBitmask, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
-                0, 0, false, 0, 0, 0, 0, -1, "", 3, -1));
+                0, 0, false, 0, 0, 0, 0, -1, "", 3, -1, -1));
         assertApnSettingsEqual(expectedApns, ApnSetting.arrayFromString(testString));
     }
 
@@ -292,9 +303,9 @@
                 null, null, -1, "user", "password", 0,
                 ApnSetting.TYPE_DEFAULT, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
                 4096, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "");
-        String expected = "[ApnSettingV6] Name, 99, 12345, apn, null, "
+        String expected = "[ApnSettingV7] Name, 99, 12345, apn, null, "
                 + "null, null, null, 10, 0, hipri | default, "
-                + "IPV6, IP, true, 0, false, 0, 0, 0, 0, spn, , false, 4096, 0, -1";
+                + "IPV6, IP, true, 0, false, 0, 0, 0, 0, spn, , false, 4096, 0, -1, -1";
         assertEquals(expected, apn.toString());
 
         final int networkTypeBitmask = 1 << (14 - 1);
@@ -302,10 +313,10 @@
                 99, "12345", "Name", "apn", null, 10,
                 null, null, -1, "user", "password", 0,
                 ApnSetting.TYPE_DEFAULT, ApnSetting.PROTOCOL_IPV6, ApnSetting.PROTOCOL_IP, true,
-                networkTypeBitmask, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "", 3, -1);
-        expected = "[ApnSettingV6] Name, 99, 12345, apn, null, "
+                networkTypeBitmask, 0, false, 0, 0, 0, 0, ApnSetting.MVNO_TYPE_SPN, "", 3, -1, 1);
+        expected = "[ApnSettingV7] Name, 99, 12345, apn, null, "
                 + "null, null, null, 10, 0, hipri | default, "
-                + "IPV6, IP, true, 0, false, 0, 0, 0, 0, spn, , false, 8192, 3, -1";
+                + "IPV6, IP, true, 0, false, 0, 0, 0, 0, spn, , false, 8192, 3, -1, 1";
         assertEquals(expected, apn.toString());
     }
 
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 7fd6f35..6289e31 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -157,6 +157,93 @@
             -1,                     // mvno_type
             "");                    // mnvo_match_data
 
+    private ApnSetting mApn3 = ApnSetting.makeApnSetting(
+            2164,                   // id
+            "44010",                // numeric
+            "sp-mode",              // name
+            "spmode.ne.jp",         // apn
+            null,                   // proxy
+            -1,                     // port
+            null,                   // mmsc
+            null,                   // mmsproxy
+            -1,                     // mmsport
+            "",                     // user
+            "",                     // password
+            -1,                     // authtype
+            ApnSetting.TYPE_DEFAULT, // types
+            ApnSetting.PROTOCOL_IPV6, // protocol
+            ApnSetting.PROTOCOL_IP, // roaming_protocol
+            true,                   // carrier_enabled
+            0,                      // networktype_bitmask
+            0,                      // profile_id
+            false,                  // modem_cognitive
+            0,                      // max_conns
+            0,                      // wait_time
+            0,                      // max_conns_time
+            0,                      // mtu
+            -1,                     // mvno_type
+            "",                     // mnvo_match_data
+            0,                      // apn_set_id
+            -1,                     // carrier_id
+            1);                     // skip_464xlat
+
+    private ApnSetting mApn4 = ApnSetting.makeApnSetting(
+            2164,                   // id
+            "44010",                // numeric
+            "sp-mode",              // name
+            "spmode.ne.jp",         // apn
+            null,                   // proxy
+            -1,                     // port
+            null,                   // mmsc
+            null,                   // mmsproxy
+            -1,                     // mmsport
+            "",                     // user
+            "",                     // password
+            -1,                     // authtype
+            ApnSetting.TYPE_IMS,    // types
+            ApnSetting.PROTOCOL_IPV6, // protocol
+            ApnSetting.PROTOCOL_IP, // roaming_protocol
+            true,                   // carrier_enabled
+            0,                      // networktype_bitmask
+            0,                      // profile_id
+            false,                  // modem_cognitive
+            0,                      // max_conns
+            0,                      // wait_time
+            0,                      // max_conns_time
+            0,                      // mtu
+            -1,                     // mvno_type
+            "");                    // mnvo_match_data
+
+    private ApnSetting mApn5 = ApnSetting.makeApnSetting(
+            2164,                   // id
+            "44010",                // numeric
+            "sp-mode",              // name
+            "spmode.ne.jp",         // apn
+            null,                   // proxy
+            -1,                     // port
+            null,                   // mmsc
+            null,                   // mmsproxy
+            -1,                     // mmsport
+            "",                     // user
+            "",                     // password
+            -1,                     // authtype
+            ApnSetting.TYPE_IMS,    // types
+            ApnSetting.PROTOCOL_IPV6, // protocol
+            ApnSetting.PROTOCOL_IP, // roaming_protocol
+            true,                   // carrier_enabled
+            0,                      // networktype_bitmask
+            0,                      // profile_id
+            false,                  // modem_cognitive
+            0,                      // max_conns
+            0,                      // wait_time
+            0,                      // max_conns_time
+            0,                      // mtu
+            -1,                     // mvno_type
+            "",                     // mnvo_match_data
+            0,                      // apn_set_id
+            -1,                     // carrier_id
+            0);                     // skip_464xlat
+
     private class DataConnectionTestHandler extends HandlerThread {
 
         private DataConnectionTestHandler(String name) {
@@ -510,6 +597,44 @@
     }
 
     @Test
+    public void testShouldSkip464Xlat() throws Exception {
+        assertFalse(testShouldSkip464XlatEvent(mApn1));
+        disconnectEvent();
+
+        assertTrue(testShouldSkip464XlatEvent(mApn3));
+        disconnectEvent();
+
+        assertTrue(testShouldSkip464XlatEvent(mApn4));
+        disconnectEvent();
+
+        assertFalse(testShouldSkip464XlatEvent(mApn5));
+        disconnectEvent();
+    }
+
+    private boolean testShouldSkip464XlatEvent(ApnSetting apn) throws Exception {
+        Method method = DataConnection.class.getDeclaredMethod("shouldSkip464Xlat");
+        method.setAccessible(true);
+
+        doReturn(apn).when(mApnContext).getApnSetting();
+        connectEvent();
+        logd(getNetworkCapabilities().toString());
+
+        return (Boolean) method.invoke(mDc);
+    }
+
+    private void connectEvent() throws Exception {
+        mDc.sendMessage(DataConnection.EVENT_CONNECT, mCp);
+        waitForMs(200);
+        assertEquals("DcActiveState", getCurrentState().getName());
+    }
+
+    private void disconnectEvent() throws Exception {
+        mDc.sendMessage(DataConnection.EVENT_DISCONNECT, mDcp);
+        waitForMs(100);
+        assertEquals("DcInactiveState", getCurrentState().getName());
+    }
+
+    @Test
     @SmallTest
     public void testIsIpAddress() throws Exception {
         // IPv4
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 8d8a080..29fc9fa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -61,6 +61,7 @@
 import android.os.PersistableBundle;
 import android.provider.Settings;
 import android.provider.Telephony;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.CarrierConfigManager;
 import android.telephony.ServiceState;
@@ -229,7 +230,8 @@
                                     Telephony.Carriers.MVNO_MATCH_DATA,
                                     Telephony.Carriers.NETWORK_TYPE_BITMASK,
                                     Telephony.Carriers.APN_SET_ID,
-                                    Telephony.Carriers.CARRIER_ID});
+                                    Telephony.Carriers.CARRIER_ID,
+                                    Telephony.Carriers.SKIP_464XLAT});
 
                     mc.addRow(new Object[]{
                             2163,                   // id
@@ -260,7 +262,8 @@
                             "",                     // mnvo_match_data
                             NETWORK_TYPE_LTE_BITMASK, // network_type_bitmask
                             0,                      // apn_set_id
-                            -1                      // carrier_id
+                            -1,                     // carrier_id
+                            -1                      // skip_464xlat
                     });
 
                     mc.addRow(new Object[]{
@@ -292,7 +295,8 @@
                             "",                     // mnvo_match_data
                             NETWORK_TYPE_LTE_BITMASK, // network_type_bitmask
                             0,                      // apn_set_id
-                            -1                      // carrier_id
+                            -1,                     // carrier_id
+                            -1                      // skip_464xlat
                     });
 
                     mc.addRow(new Object[]{
@@ -324,7 +328,8 @@
                             "",                     // mnvo_match_data
                             0,                      // network_type_bitmask
                             0,                      // apn_set_id
-                            -1                      // carrier_id
+                            -1,                     // carrier_id
+                            -1                      // skip_464xlat
                     });
 
                     mc.addRow(new Object[]{
@@ -356,7 +361,8 @@
                             "",                     // mnvo_match_data
                             NETWORK_TYPE_EHRPD_BITMASK, // network_type_bitmask
                             0,                      // apn_set_id
-                            -1                      // carrier_id
+                            -1,                     // carrier_id
+                            -1                      // skip_464xlat
                     });
 
                     mc.addRow(new Object[]{
@@ -388,7 +394,8 @@
                             "",                     // mnvo_match_data
                             0,                      // network_type_bitmask
                             0,                      // apn_set_id
-                            -1                      // carrier_id
+                            -1,                     // carrier_id
+                            -1                      // skip_464xlat
                     });
 
                     return mc;
@@ -422,6 +429,8 @@
         doReturn("fake.action_attached").when(mPhone).getActionAttached();
         doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
                 .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
 
         mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
                 sNetworkAttributes);
@@ -443,6 +452,8 @@
 
         ((MockContentResolver) mContext.getContentResolver()).addProvider(
                 Telephony.Carriers.CONTENT_URI.getAuthority(), mApnSettingContentProvider);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
 
         doReturn(true).when(mSimRecords).getRecordsLoaded();
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
@@ -592,8 +603,7 @@
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -641,8 +651,7 @@
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -666,8 +675,7 @@
         dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -698,8 +706,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -752,8 +759,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -808,8 +814,7 @@
         waitForMs(200);
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);
@@ -859,7 +864,7 @@
         mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
         waitForMs(100);
 
-        verify(mSST, times(1)).registerForDataConnectionAttached(eq(mDct),
+        verify(mSST, times(1)).registerForDataConnectionAttached(eq(TransportType.WWAN), eq(mDct),
                 intArgumentCaptor.capture(), eq(null));
         // Ideally this should send EVENT_DATA_CONNECTION_ATTACHED");
         mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
@@ -878,7 +883,7 @@
         // The auto attach flag should be reset after update
         assertFalse(mDct.getAutoAttachOnCreation());
 
-        verify(mSST, times(1)).registerForDataConnectionDetached(eq(mDct),
+        verify(mSST, times(1)).registerForDataConnectionDetached(eq(TransportType.WWAN), eq(mDct),
                 intArgumentCaptor.capture(), eq(null));
         // Ideally this should send EVENT_DATA_CONNECTION_DETACHED
         mDct.sendMessage(mDct.obtainMessage(intArgumentCaptor.getValue(), null));
@@ -916,8 +921,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -959,8 +963,7 @@
         waitForMs(200);
 
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
+                eq(AccessNetworkType.EUTRAN), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
     }
@@ -1013,8 +1016,7 @@
         waitForMs(200);
 
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), any(DataProfile.class),
+                eq(AccessNetworkType.EUTRAN), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
     }
@@ -1135,8 +1137,8 @@
     @SmallTest
     public void testTrySetupDefaultOnIWLAN() throws Exception {
         initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
 
         mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                 new String[]{PhoneConstants.APN_TYPE_DEFAULT});
@@ -1188,8 +1190,8 @@
     @Test
     @SmallTest
     public void testUpdateWaitingApnListOnDataRatChange() throws Exception {
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_EHRPD).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
         mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                 new String[]{PhoneConstants.APN_TYPE_DEFAULT});
         mDct.enableApn(ApnSetting.TYPE_DEFAULT, DcTracker.REQUEST_TYPE_NORMAL, null);
@@ -1206,8 +1208,7 @@
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.CDMA2000), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
@@ -1215,8 +1216,8 @@
 
         //data rat change from ehrpd to lte
         logd("Sending EVENT_DATA_RAT_CHANGED");
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
         waitForMs(200);
 
@@ -1239,8 +1240,7 @@
 
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1308,8 +1308,8 @@
     @Test
     @SmallTest
     public void testDataRatChangeOOS() throws Exception {
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_EHRPD).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
         mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                 new String[]{PhoneConstants.APN_TYPE_DEFAULT});
         mDct.enableApn(ApnSetting.TYPE_DEFAULT, DcTracker.REQUEST_TYPE_NORMAL, null);
@@ -1326,8 +1326,7 @@
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         // Verify if RIL command was sent properly.
         verify(mSimulatedCommandsVerifier).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                        mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.CDMA2000), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
@@ -1335,8 +1334,8 @@
 
         // Data rat change from ehrpd to unknown due to OOS
         logd("Sending EVENT_DATA_RAT_CHANGED");
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
         waitForMs(200);
 
@@ -1346,8 +1345,8 @@
                 any(Message.class));
 
         // Data rat resume from unknown to ehrpd
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
-                .getRilDataRadioTechnology();
+        doReturn(TelephonyManager.NETWORK_TYPE_EHRPD).when(mNetworkRegistrationState)
+                .getAccessNetworkTechnology();
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
         waitForMs(200);
 
@@ -1434,9 +1433,6 @@
     @Test
     @SmallTest
     public void testNetworkStatusChangedRecoveryOFF() throws Exception {
-        ContentResolver resolver = mContext.getContentResolver();
-        Settings.Global.putInt(resolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
-
         mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                 new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
         mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_NORMAL, null);
@@ -1452,8 +1448,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1494,8 +1489,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, timeout(TEST_TIMEOUT).times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1511,10 +1505,6 @@
         waitForMs(200);
 
         verify(mSimulatedCommandsVerifier, times(1)).getDataCallList(any(Message.class));
-
-        // reset the setting at the end of this test
-        Settings.Global.putInt(resolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
-        waitForMs(200);
     }
 
     @FlakyTest
@@ -1541,8 +1531,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, timeout(TEST_TIMEOUT).times(2)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1556,10 +1545,6 @@
         verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                 eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                 any(Message.class));
-
-        // reset the setting at the end of this test
-        Settings.Global.putInt(resolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
-        waitForMs(200);
     }
 
 
@@ -1586,8 +1571,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1599,9 +1583,6 @@
 
         // expected to get preferred network type
         verify(mSST, times(1)).reRegisterNetwork(eq(null));
-
-        // reset the setting at the end of this test
-        Settings.Global.putInt(resolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
     }
 
     @Test
@@ -1627,8 +1608,7 @@
 
         ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
-                eq(ServiceState.rilRadioTechnologyToAccessNetworkType(
-                mServiceState.getRilDataRadioTechnology())), dpCaptor.capture(),
+                eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
@@ -1640,9 +1620,6 @@
 
         // expected to get preferred network type
         verify(mSST, times(1)).powerOffRadioSafely();
-
-        // reset the setting at the end of this test
-        Settings.Global.putInt(resolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
     }
 
     private void verifyDataEnabledChangedMessage(boolean enabled, int reason) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
index ab0d061..dff75b0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
@@ -34,7 +34,9 @@
 import android.telephony.ims.ImsMmTelManager;
 import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.stub.ImsConfigImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
@@ -44,10 +46,12 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 
 import java.util.Hashtable;
 
+@RunWith(AndroidJUnit4.class)
 public class ImsManagerTest extends TelephonyTest {
     private static final String UNSET_PROVISIONED_STRING = "unset";
     private static final boolean ENHANCED_4G_MODE_DEFAULT_VAL = true;
@@ -78,6 +82,8 @@
         super.setUp("ImsManagerTest");
         mPhoneId = mPhone.getPhoneId();
         mBundle = mContextFixture.getCarrierConfigBundle();
+        // Force MmTelFeatureConnection to create an executor using Looper.myLooper().
+        doReturn(null).when(mContext).getMainLooper();
 
         doReturn(mSubId).when(mSubscriptionController).getSubId(mPhoneId);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java
index 25cfb20..39ec048 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java
@@ -65,7 +65,7 @@
         mContentResolver = (MockContentResolver) mContext.getContentResolver();
         mContentResolver.addProvider("rcs", mFakeRcsProvider);
 
-        mRcsMessageStoreController = new RcsMessageStoreController(mContentResolver, null);
+        mRcsMessageStoreController = new RcsMessageStoreController(mContentResolver);
     }
 
     @After
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 755b06b..d1a33a0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -110,7 +110,7 @@
         }
         @Override
         public void onLooperPrepared() {
-            mCTUT = new ImsPhoneCallTracker(mImsPhone);
+            mCTUT = new ImsPhoneCallTracker(mImsPhone, Runnable::run);
             mCTUT.addReasonCodeRemapping(null, "Wifi signal lost.", ImsReasonInfo.CODE_WIFI_LOST);
             mCTUT.addReasonCodeRemapping(501, "Call answered elsewhere.",
                     ImsReasonInfo.CODE_ANSWERED_ELSEWHERE);
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 2555488..6432d05 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -285,7 +285,7 @@
         mImsPhoneUT.dispose();
         assertEquals(0, list.size());
         verify(mImsCT).dispose();
-        verify(mSST).unregisterForDataRegStateOrRatChanged(mImsPhoneUT);
+        verify(mSST, times(2)).unregisterForDataRegStateOrRatChanged(anyInt(), eq(mImsPhoneUT));
     }
 
     @Test
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 c95b91a..7cb6d78 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -109,8 +109,9 @@
                 mIccCardStatus.mImsSubscriptionAppIndex =
                         mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
         mSimulatedCommands.setIccCardStatus(mIccCardStatus);
-        // slotIndex should be invalid when testing with older versions (before 1.2) of hal
-        mIccCardStatus.physicalSlotIndex = UiccController.INVALID_SLOT_ID;
+        // for testing we pretend slotIndex is set. In reality it would be invalid on older versions
+        // (before 1.2) of hal
+        mIccCardStatus.physicalSlotIndex = 0;
         mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG);
         mUiccControllerHandlerThread.start();
         waitUntilReady();
@@ -235,6 +236,7 @@
         ics.atr = "abcdef0123456789abcdef";
         ics.iccid = "123451234567890";
         ics.eid = "A1B2C3D4";
+        ics.physicalSlotIndex = 0;
         AsyncResult ar = new AsyncResult(null, ics, null);
         Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_ICC_STATUS_DONE, ar);
         mUiccControllerUT.handleMessage(msg);
@@ -325,6 +327,7 @@
         ics.setUniversalPinState(3 /* disabled */);
         ics.atr = "abcdef0123456789abcdef";
         ics.iccid = "123451234567890";
+        ics.physicalSlotIndex = 0;
         AsyncResult ar = new AsyncResult(null, ics, null);
         Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_ICC_STATUS_DONE, ar);
         mUiccControllerUT.handleMessage(msg);