Merge "Check data connection status on non-DDS SUB clearly"
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index 853b85f..d5e7e0c 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -31,7 +31,7 @@
 public abstract class BaseCommands implements CommandsInterface {
     //***** Instance Variables
     protected Context mContext;
-    protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+    protected int mState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
     protected Object mStateMonitor = new Object();
 
     protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
@@ -117,7 +117,7 @@
     //***** CommandsInterface implementation
 
     @Override
-    public RadioState getRadioState() {
+    public @TelephonyManager.RadioPowerState int getRadioState() {
         return mState;
     }
 
@@ -154,7 +154,7 @@
         synchronized (mStateMonitor) {
             mOnRegistrants.add(r);
 
-            if (mState.isOn()) {
+            if (mState == TelephonyManager.RADIO_POWER_ON) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -174,7 +174,7 @@
         synchronized (mStateMonitor) {
             mAvailRegistrants.add(r);
 
-            if (mState.isAvailable()) {
+            if (mState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -194,7 +194,7 @@
         synchronized (mStateMonitor) {
             mNotAvailRegistrants.add(r);
 
-            if (!mState.isAvailable()) {
+            if (mState == TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -214,7 +214,8 @@
         synchronized (mStateMonitor) {
             mOffOrNotAvailRegistrants.add(r);
 
-            if (mState == RadioState.RADIO_OFF || !mState.isAvailable()) {
+            if (mState == TelephonyManager.RADIO_POWER_OFF
+                    || mState == TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -791,12 +792,13 @@
      *
      * RadioState has 3 values : RADIO_OFF, RADIO_UNAVAILABLE, RADIO_ON.
      *
-     * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
+     * @param newState new radio power state decoded from RIL_UNSOL_RADIO_STATE_CHANGED
      * @param forceNotifyRegistrants boolean indicating if registrants should be notified even if
      * there is no change in state
      */
-    protected void setRadioState(RadioState newState, boolean forceNotifyRegistrants) {
-        RadioState oldState;
+    protected void setRadioState(@TelephonyManager.RadioPowerState int newState,
+                                 boolean forceNotifyRegistrants) {
+        int oldState;
 
         synchronized (mStateMonitor) {
             oldState = mState;
@@ -809,21 +811,24 @@
 
             mRadioStateChangedRegistrants.notifyRegistrants();
 
-            if (mState.isAvailable() && !oldState.isAvailable()) {
+            if (mState != TelephonyManager.RADIO_POWER_UNAVAILABLE
+                    && oldState == TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                 mAvailRegistrants.notifyRegistrants();
             }
 
-            if (!mState.isAvailable() && oldState.isAvailable()) {
+            if (mState == TelephonyManager.RADIO_POWER_UNAVAILABLE
+                    && oldState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                 mNotAvailRegistrants.notifyRegistrants();
             }
 
-            if (mState.isOn() && !oldState.isOn()) {
+            if (mState == TelephonyManager.RADIO_POWER_ON
+                    && oldState != TelephonyManager.RADIO_POWER_ON) {
                 mOnRegistrants.notifyRegistrants();
             }
 
-            if ((!mState.isOn() || !mState.isAvailable())
-                && !((!oldState.isOn() || !oldState.isAvailable()))
-            ) {
+            if ((mState == TelephonyManager.RADIO_POWER_OFF
+                    || mState == TelephonyManager.RADIO_POWER_UNAVAILABLE)
+                    && (oldState == TelephonyManager.RADIO_POWER_ON)) {
                 mOffOrNotAvailRegistrants.notifyRegistrants();
             }
         }
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 6657d27..24db534 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -25,6 +25,7 @@
 import android.telephony.ClientRequestStats;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.TelephonyManager;
 import android.telephony.data.DataProfile;
 
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
@@ -37,19 +38,6 @@
  * {@hide}
  */
 public interface CommandsInterface {
-    enum RadioState {
-        RADIO_OFF,         /* Radio explicitly powered off (eg CFUN=0) */
-        RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */
-        RADIO_ON;          /* Radio is on */
-
-        public boolean isOn() /* and available...*/ {
-            return this == RADIO_ON;
-        }
-
-        public boolean isAvailable() {
-            return this != RADIO_UNAVAILABLE;
-        }
-    }
 
     //***** Constants
 
@@ -121,7 +109,12 @@
     static final int CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM           = 96;
 
     //***** Methods
-    RadioState getRadioState();
+
+    /**
+     * get latest radio power state from modem
+     * @return
+     */
+    @TelephonyManager.RadioPowerState int getRadioState();
 
     /**
      * response.obj.result is an int[2]
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index a69865d..7587292 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -353,6 +353,15 @@
         }
     }
 
+    @Override
+    public void notifyRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
+        try {
+            mRegistry.notifyRadioPowerStateChanged(state);
+        } catch (RemoteException ex) {
+            // system process is dead
+        }
+    }
+
     /**
      * Convert the {@link Phone.DataActivityState} enum into the TelephonyManager.DATA_* constants
      * for the public API.
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 025e31c..abd09a5 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -620,7 +620,7 @@
         String disableCall = SystemProperties.get(
                 TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
 
-        if (!mCi.getRadioState().isOn()) {
+        if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_ON) {
             throw new CallStateException(CallStateException.ERROR_POWER_OFF,
                     "Modem not powered");
         }
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 58eb4e7..f8edbcf 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -261,6 +261,7 @@
         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mCi.registerForOn(this, EVENT_RADIO_ON, null);
+        mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
 
         //GSM
@@ -396,14 +397,14 @@
         onUpdateIccAvailability();
         mCT.updatePhoneType();
 
-        CommandsInterface.RadioState radioState = mCi.getRadioState();
-        if (radioState.isAvailable()) {
+        int radioState = mCi.getRadioState();
+        if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
             handleRadioAvailable();
-            if (radioState.isOn()) {
+            if (radioState == TelephonyManager.RADIO_POWER_ON) {
                 handleRadioOn();
             }
         }
-        if (!radioState.isAvailable() || !radioState.isOn()) {
+        if (radioState != TelephonyManager.RADIO_POWER_ON) {
             handleRadioOffOrNotAvailable();
         }
     }
@@ -2221,6 +2222,11 @@
         mRadioOffOrNotAvailableRegistrants.notifyRegistrants();
     }
 
+    private void handleRadioPowerStateChange() {
+        Rlog.d(LOG_TAG, "handleRadioPowerStateChange, state= " + mCi.getRadioState());
+        mNotifier.notifyRadioPowerStateChanged(mCi.getRadioState());
+    }
+
     @Override
     public void handleMessage(Message msg) {
         AsyncResult ar;
@@ -2474,6 +2480,12 @@
                 break;
             }
 
+            case EVENT_RADIO_STATE_CHANGED: {
+                logd("EVENT EVENT_RADIO_STATE_CHANGED");
+                handleRadioPowerStateChange();
+                break;
+            }
+
             case EVENT_SSN:
                 logd("Event EVENT_SSN Received");
                 if (isPhoneTypeGsm()) {
@@ -3288,6 +3300,14 @@
         }
     }
 
+    //return true if either CSIM or RUIM app is present
+    private boolean isCdmaSubscriptionAppPresent(){
+        UiccCardApplication cdmaApplication =
+                mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
+        return cdmaApplication != null && (cdmaApplication.getType() == AppType.APPTYPE_CSIM ||
+                cdmaApplication.getType() == AppType.APPTYPE_RUIM);
+    }
+
     private void phoneObjectUpdater(int newVoiceRadioTech) {
         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
 
@@ -3301,7 +3321,10 @@
                 int volteReplacementRat =
                         b.getInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT);
                 logd("phoneObjectUpdater: volteReplacementRat=" + volteReplacementRat);
-                if (volteReplacementRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
+                if (volteReplacementRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN &&
+                           //In cdma case, replace rat only if csim or ruim app present
+                           (ServiceState.isGsm(volteReplacementRat) ||
+                           isCdmaSubscriptionAppPresent())) {
                     newVoiceRadioTech = volteReplacementRat;
                 }
             } else {
@@ -3361,7 +3384,7 @@
 
         boolean oldPowerState = false; // old power state to off
         if (mResetModemOnRadioTechnologyChange) {
-            if (mCi.getRadioState().isOn()) {
+            if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
                 oldPowerState = true;
                 logd("phoneObjectUpdater: Setting Radio Power to Off");
                 mCi.setRadioPower(false, null);
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index f09b386..048fd5d 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -199,8 +199,10 @@
     protected static final int EVENT_SET_ROAMING_PREFERENCE_DONE    = 44;
     protected static final int EVENT_MODEM_RESET                    = 45;
     protected static final int EVENT_VRS_OR_RAT_CHANGED             = 46;
+    // Radio state change
+    protected static final int EVENT_RADIO_STATE_CHANGED            = 47;
 
-    protected static final int EVENT_LAST                       = EVENT_VRS_OR_RAT_CHANGED;
+    protected static final int EVENT_LAST                       = EVENT_RADIO_STATE_CHANGED;
 
     // For shared prefs.
     private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
@@ -3317,17 +3319,24 @@
     }
 
     /**
+     * @return returns the latest radio state from the modem
+     */
+    public int getRadioPowerState() {
+        return mCi.getRadioState();
+    }
+
+    /**
      * Is Radio Present on the device and is it accessible
      */
     public boolean isRadioAvailable() {
-        return mCi.getRadioState().isAvailable();
+        return mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE;
     }
 
     /**
      * Is Radio turned on
      */
     public boolean isRadioOn() {
-        return mCi.getRadioState().isOn();
+        return mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON;
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index 6829322..40a2915 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -20,6 +20,7 @@
 import android.telephony.CellLocation;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
+import android.telephony.TelephonyManager;
 import android.telephony.VoLteServiceState;
 
 import java.util.List;
@@ -75,4 +76,6 @@
     public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData);
 
     public void notifyPhoneCapabilityChanged(PhoneCapability capability);
+
+    void notifyRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state);
 }
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 638fa31..66e2d51 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -32,7 +32,7 @@
 import android.hardware.radio.V1_0.CellInfoTdscdma;
 import android.hardware.radio.V1_0.CellInfoType;
 import android.hardware.radio.V1_0.CellInfoWcdma;
-import android.hardware.radio.V1_0.DataProfileInfo;
+import android.hardware.radio.V1_0.DataProfileId;
 import android.hardware.radio.V1_0.Dial;
 import android.hardware.radio.V1_0.GsmBroadcastSmsConfigInfo;
 import android.hardware.radio.V1_0.GsmSmsMessage;
@@ -353,7 +353,7 @@
         // increment the cookie so that death notification can be ignored
         mRadioProxyCookie.incrementAndGet();
 
-        setRadioState(RadioState.RADIO_UNAVAILABLE, true /* forceNotifyRegistrants */);
+        setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, true /* forceNotifyRegistrants */);
 
         RILRequest.resetSerial();
         // Clear request list on close
@@ -1156,12 +1156,14 @@
     }
 
     /**
-     * Convert to DataProfileInfo defined in types.hal
+     * Convert to DataProfileInfo defined in radio/1.0/types.hal
      * @param dp Data profile
      * @return A converted data profile
      */
-    private static DataProfileInfo convertToHalDataProfile(DataProfile dp) {
-        DataProfileInfo dpi = new DataProfileInfo();
+    private static android.hardware.radio.V1_0.DataProfileInfo convertToHalDataProfile10(
+            DataProfile dp) {
+        android.hardware.radio.V1_0.DataProfileInfo dpi =
+                new android.hardware.radio.V1_0.DataProfileInfo();
 
         dpi.profileId = dp.getProfileId();
         dpi.apn = dp.getApn();
@@ -1178,8 +1180,41 @@
         dpi.supportedApnTypesBitmap = dp.getSupportedApnTypesBitmap();
         dpi.bearerBitmap = dp.getBearerBitmap();
         dpi.mtu = dp.getMtu();
-        dpi.mvnoType = convertToHalMvnoType(dp.getMvnoType());
-        dpi.mvnoMatchData = dp.getMvnoMatchData();
+        dpi.mvnoType = MvnoType.NONE;
+        dpi.mvnoMatchData = "";
+
+        return dpi;
+    }
+
+    /**
+     * Convert to DataProfileInfo defined in radio/1.3/types.hal
+     * @param dp Data profile
+     * @return A converted data profile
+     */
+    private static android.hardware.radio.V1_3.DataProfileInfo convertToHalDataProfile13(
+            DataProfile dp) {
+        android.hardware.radio.V1_3.DataProfileInfo dpi =
+                new android.hardware.radio.V1_3.DataProfileInfo();
+
+        dpi.apn = dp.getApn();
+        dpi.protocol = dp.getProtocol();
+        dpi.roamingProtocol = dp.getRoamingProtocol();
+        dpi.authType = dp.getAuthType();
+        dpi.user = dp.getUserName();
+        dpi.password = dp.getPassword();
+        dpi.type = dp.getType();
+        dpi.maxConnsTime = dp.getMaxConnsTime();
+        dpi.maxConns = dp.getMaxConns();
+        dpi.waitTime = dp.getWaitTime();
+        dpi.enabled = dp.isEnabled();
+        dpi.supportedApnTypesBitmap = dp.getSupportedApnTypesBitmap();
+        dpi.bearerBitmap = dp.getBearerBitmap();
+        dpi.mtu = dp.getMtu();
+        dpi.persistent = dp.isPersistent();
+        dpi.preferred = dp.isPreferred();
+
+        // profile id is only meaningful when it's persistent on the modem.
+        dpi.profileId = (dpi.persistent) ? dp.getProfileId() : DataProfileId.INVALID;
 
         return dpi;
     }
@@ -1209,54 +1244,36 @@
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
                               Message result) {
 
-        IRadio radioProxy = getRadioProxy(result);
+        IRadio radioProxy10 = getRadioProxy(result);
 
-        if (radioProxy != null) {
+        if (radioProxy10 != null) {
 
             RILRequest rr = obtainRequest(RIL_REQUEST_SETUP_DATA_CALL, result,
                     mRILDefaultWorkSource);
 
-            // Convert to HAL data profile
-            DataProfileInfo dpi = convertToHalDataProfile(dataProfile);
+            android.hardware.radio.V1_3.IRadio radioProxy13 =
+                    android.hardware.radio.V1_3.IRadio.castFrom(radioProxy10);
 
-            android.hardware.radio.V1_2.IRadio radioProxy12 =
-                    android.hardware.radio.V1_2.IRadio.castFrom(radioProxy);
+            ArrayList<String> addresses = new ArrayList<>();
+            ArrayList<String> dnses = new ArrayList<>();
+            if (linkProperties != null) {
+                for (InetAddress address : linkProperties.getAddresses()) {
+                    addresses.add(address.getHostAddress());
+                }
+                for (InetAddress dns : linkProperties.getDnsServers()) {
+                    dnses.add(dns.getHostAddress());
+                }
+            }
+
             try {
-                if (radioProxy12 == null) {
-                    // IRadio V1.0
+                // Note that we should always try the highest version first. If the vendor IRadio
+                // is v1.3, both radioProxy13 and radioProxy12 will be non-null.
+                if (radioProxy13 != null) {
+                    // IRadio V1.3
 
-                    // Getting data RAT here is just a workaround to support the older 1.0 vendor
-                    // RIL. The new data service interface passes access network type instead of
-                    // RAT for setup data request. It is impossible to convert access network
-                    // type back to RAT here, so we directly get the data RAT from phone.
-                    int dataRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
-                    Phone phone = PhoneFactory.getPhone(mPhoneId);
-                    if (phone != null) {
-                        ServiceState ss = phone.getServiceState();
-                        if (ss != null) {
-                            dataRat = ss.getRilDataRadioTechnology();
-                        }
-                    }
-                    if (RILJ_LOGD) {
-                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                                + ",dataRat=" + dataRat + ",isRoaming=" + isRoaming
-                                + ",allowRoaming=" + allowRoaming + "," + dataProfile);
-                    }
-
-                    radioProxy.setupDataCall(rr.mSerial, dataRat, dpi,
-                            dataProfile.isModemCognitive(), allowRoaming, isRoaming);
-                } else {
-                    // IRadio V1.2
-                    ArrayList<String> addresses = new ArrayList<>();
-                    ArrayList<String> dnses = new ArrayList<>();
-                    if (linkProperties != null) {
-                        for (InetAddress address : linkProperties.getAddresses()) {
-                            addresses.add(address.getHostAddress());
-                        }
-                        for (InetAddress dns : linkProperties.getDnsServers()) {
-                            dnses.add(dns.getHostAddress());
-                        }
-                    }
+                    // Convert to HAL data profile
+                    android.hardware.radio.V1_3.DataProfileInfo dpi =
+                            convertToHalDataProfile13(dataProfile);
 
                     if (RILJ_LOGD) {
                         riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -1265,9 +1282,57 @@
                                 + ",addresses=" + addresses + ",dnses=" + dnses);
                     }
 
-                    radioProxy12.setupDataCall_1_2(rr.mSerial, accessNetworkType, dpi,
-                            dataProfile.isModemCognitive(), allowRoaming, isRoaming, reason,
-                            addresses, dnses);
+                    radioProxy13.setupDataCall_1_3(rr.mSerial, accessNetworkType, dpi, allowRoaming,
+                            reason, addresses, dnses);
+                } else {
+                    android.hardware.radio.V1_2.IRadio radioProxy12 =
+                            android.hardware.radio.V1_2.IRadio.castFrom(radioProxy10);
+                    if (radioProxy12 != null) {
+                        // IRadio V1.2
+
+                        // Convert to HAL data profile
+                        android.hardware.radio.V1_0.DataProfileInfo dpi =
+                                convertToHalDataProfile10(dataProfile);
+
+                        if (RILJ_LOGD) {
+                            riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                    + ",accessNetworkType=" + accessNetworkType + ",isRoaming="
+                                    + isRoaming + ",allowRoaming=" + allowRoaming + ","
+                                    + dataProfile + ",addresses=" + addresses + ",dnses=" + dnses);
+                        }
+
+                        radioProxy12.setupDataCall_1_2(rr.mSerial, accessNetworkType, dpi,
+                                dataProfile.isPersistent(), allowRoaming, isRoaming, reason,
+                                addresses, dnses);
+                    } else {
+                        // IRadio V1.0 and IRadio V1.1
+
+                        // Convert to HAL data profile
+                        android.hardware.radio.V1_0.DataProfileInfo dpi =
+                                convertToHalDataProfile10(dataProfile);
+
+                        // Getting data RAT here is just a workaround to support the older 1.0
+                        // vendor RIL. The new data service interface passes access network type
+                        // instead of RAT for setup data request. It is impossible to convert access
+                        // network type back to RAT here, so we directly get the data RAT from
+                        // phone.
+                        int dataRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
+                        Phone phone = PhoneFactory.getPhone(mPhoneId);
+                        if (phone != null) {
+                            ServiceState ss = phone.getServiceState();
+                            if (ss != null) {
+                                dataRat = ss.getRilDataRadioTechnology();
+                            }
+                        }
+                        if (RILJ_LOGD) {
+                            riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                    + ",dataRat=" + dataRat + ",isRoaming=" + isRoaming
+                                    + ",allowRoaming=" + allowRoaming + "," + dataProfile);
+                        }
+
+                        radioProxy10.setupDataCall(rr.mSerial, dataRat, dpi,
+                                dataProfile.isPersistent(), allowRoaming, isRoaming);
+                    }
                 }
             } catch (RemoteException | RuntimeException e) {
                 handleRadioProxyExceptionForRR(rr, "setupDataCall", e);
@@ -3029,8 +3094,8 @@
     @Override
     public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message result) {
 
-        IRadio radioProxy = getRadioProxy(result);
-        if (radioProxy != null) {
+        IRadio radioProxy10 = getRadioProxy(result);
+        if (radioProxy10 != null) {
             RILRequest rr = obtainRequest(RIL_REQUEST_SET_INITIAL_ATTACH_APN, result,
                     mRILDefaultWorkSource);
 
@@ -3038,9 +3103,23 @@
                 riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + dataProfile);
             }
 
+            android.hardware.radio.V1_3.IRadio radioProxy13 =
+                    android.hardware.radio.V1_3.IRadio.castFrom(radioProxy10);
+
             try {
-                radioProxy.setInitialAttachApn(rr.mSerial, convertToHalDataProfile(dataProfile),
-                        dataProfile.isModemCognitive(), isRoaming);
+                // Note that we should always try the highest version first. If the vendor IRadio
+                // is v1.3, both radioProxy13 and radioProxy10 will be non-null.
+                if (radioProxy13 != null) {
+                    // v1.3
+                    radioProxy13.setInitialAttachApn_1_3(rr.mSerial,
+                            convertToHalDataProfile13(dataProfile));
+                } else {
+                    // v1.2, v1.1, and v1.0
+                    radioProxy10.setInitialAttachApn(rr.mSerial,
+                            convertToHalDataProfile10(dataProfile), dataProfile.isPersistent(),
+                            isRoaming);
+                }
+
             } catch (RemoteException | RuntimeException e) {
                 handleRadioProxyExceptionForRR(rr, "setInitialAttachApn", e);
             }
@@ -3424,26 +3503,61 @@
     @Override
     public void setDataProfile(DataProfile[] dps, boolean isRoaming, Message result) {
 
-        IRadio radioProxy = getRadioProxy(result);
-        if (radioProxy != null) {
-            RILRequest rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result,
-                    mRILDefaultWorkSource);
+        IRadio radioProxy10 = getRadioProxy(result);
+        if (radioProxy10 != null) {
+            android.hardware.radio.V1_3.IRadio radioProxy13 =
+                    android.hardware.radio.V1_3.IRadio.castFrom(radioProxy10);
 
-            if (RILJ_LOGD) {
-                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                        + " with data profiles : ");
-                for (DataProfile profile : dps) {
-                    riljLog(profile.toString());
-                }
-            }
-
-            ArrayList<DataProfileInfo> dpis = new ArrayList<>();
-            for (DataProfile dp : dps) {
-                dpis.add(convertToHalDataProfile(dp));
-            }
-
+            RILRequest rr = null;
             try {
-                radioProxy.setDataProfile(rr.mSerial, dpis, isRoaming);
+                // Note that we should always try the highest version first. If the vendor IRadio
+                // is v1.3, both radioProxy13 and radioProxy10 will be non-null.
+                if (radioProxy13 != null) {
+                    // V1.3
+                    rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result,
+                            mRILDefaultWorkSource);
+
+                    ArrayList<android.hardware.radio.V1_3.DataProfileInfo> dpis = new ArrayList<>();
+                    for (DataProfile dp : dps) {
+                        dpis.add(convertToHalDataProfile13(dp));
+                    }
+
+                    if (RILJ_LOGD) {
+                        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                + " with data profiles : ");
+                        for (DataProfile profile : dps) {
+                            riljLog(profile.toString());
+                        }
+                    }
+
+                    radioProxy13.setDataProfile_1_3(rr.mSerial, dpis);
+                } else {
+                    // V1.0, 1.1, and 1.2
+                    ArrayList<android.hardware.radio.V1_0.DataProfileInfo> dpis = new ArrayList<>();
+                    for (DataProfile dp : dps) {
+                        // For v1.0 to v1.2, we only send data profiles that has the persistent
+                        // (a.k.a modem cognitive) bit set to true.
+                        if (dp.isPersistent()) {
+                            dpis.add(convertToHalDataProfile10(dp));
+                        }
+                    }
+
+                    if (!dpis.isEmpty()) {
+                        rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result,
+                                mRILDefaultWorkSource);
+
+                        if (RILJ_LOGD) {
+                            riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                                    + " with data profiles : ");
+                            for (DataProfile profile : dps) {
+                                riljLog(profile.toString());
+                            }
+                        }
+
+                        radioProxy10.setDataProfile(rr.mSerial, dpis, isRoaming);
+                    }
+
+                }
             } catch (RemoteException | RuntimeException e) {
                 handleRadioProxyExceptionForRR(rr, "setDataProfile", e);
             }
@@ -4188,7 +4302,8 @@
                 }
                 break;
             case RIL_REQUEST_SHUTDOWN:
-                setRadioState(RadioState.RADIO_UNAVAILABLE, false /* forceNotifyRegistrants */);
+                setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE,
+                        false /* forceNotifyRegistrants */);
                 break;
         }
 
diff --git a/src/java/com/android/internal/telephony/RadioIndication.java b/src/java/com/android/internal/telephony/RadioIndication.java
index ae76ef3..764c4ea 100644
--- a/src/java/com/android/internal/telephony/RadioIndication.java
+++ b/src/java/com/android/internal/telephony/RadioIndication.java
@@ -91,6 +91,7 @@
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.SignalStrength;
 import android.telephony.SmsMessage;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.cdma.CdmaInformationRecords;
@@ -120,13 +121,13 @@
     public void radioStateChanged(int indicationType, int radioState) {
         mRil.processIndication(indicationType);
 
-        CommandsInterface.RadioState newState = getRadioStateFromInt(radioState);
+        int state = getRadioStateFromInt(radioState);
         if (RIL.RILJ_LOGD) {
             mRil.unsljLogMore(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, "radioStateChanged: " +
-                    newState);
+                    state);
         }
 
-        mRil.setRadioState(newState, false /* forceNotifyRegistrants */);
+        mRil.setRadioState(state, false /* forceNotifyRegistrants */);
     }
 
     public void callStateChanged(int indicationType) {
@@ -904,18 +905,22 @@
         mRil.mNattKeepaliveStatusRegistrants.notifyRegistrants(new AsyncResult(null, ks, null));
     }
 
-    private CommandsInterface.RadioState getRadioStateFromInt(int stateInt) {
-        CommandsInterface.RadioState state;
+    /**
+     * @param stateInt
+     * @return {@link TelephonyManager.RadioPowerState RadioPowerState}
+     */
+    private @TelephonyManager.RadioPowerState int getRadioStateFromInt(int stateInt) {
+        int state;
 
         switch(stateInt) {
             case android.hardware.radio.V1_0.RadioState.OFF:
-                state = CommandsInterface.RadioState.RADIO_OFF;
+                state = TelephonyManager.RADIO_POWER_OFF;
                 break;
             case android.hardware.radio.V1_0.RadioState.UNAVAILABLE:
-                state = CommandsInterface.RadioState.RADIO_UNAVAILABLE;
+                state = TelephonyManager.RADIO_POWER_UNAVAILABLE;
                 break;
             case android.hardware.radio.V1_0.RadioState.ON:
-                state = CommandsInterface.RadioState.RADIO_ON;
+                state = TelephonyManager.RADIO_POWER_ON;
                 break;
             default:
                 throw new RuntimeException("Unrecognized RadioState: " + stateInt);
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 2840d31..cc3e207 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1042,7 +1042,8 @@
 
             case EVENT_RADIO_POWER_OFF_DONE:
                 if (DBG) log("EVENT_RADIO_POWER_OFF_DONE");
-                if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) {
+                if (mDeviceShuttingDown && mCi.getRadioState()
+                        != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
                     // during shutdown the modem may not send radio state changed event
                     // as a result of radio power request
                     // Hence, issuing shut down regardless of radio power response
@@ -1066,7 +1067,7 @@
             case EVENT_RADIO_STATE_CHANGED:
             case EVENT_PHONE_TYPE_SWITCHED:
                 if(!mPhone.isPhoneTypeGsm() &&
-                        mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON) {
+                        mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
                     handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
 
                     // Signal strength polling stops when radio is off.
@@ -1086,7 +1087,7 @@
                 // This callback is called when signal strength is polled
                 // all by itself
 
-                if (!(mCi.getRadioState().isOn())) {
+                if (!(mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)) {
                     // Polling will continue when radio turns back on
                     return;
                 }
@@ -2448,7 +2449,7 @@
 
                 String originalPlmn = plmn.trim();
                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
-            } else if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+            } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
                 // todo: temporary hack; should have a better fix. This is to avoid using operator
                 // name from ServiceState (populated in resetServiceStateInIwlanMode()) until
                 // wifi calling is actually enabled
@@ -2518,9 +2519,10 @@
 
         // If we want it on and it's off, turn it on
         if (mDesiredPowerState && !mRadioDisabledByCarrier
-                && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+                && mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
             mCi.setRadioPower(true, null);
-        } else if ((!mDesiredPowerState || mRadioDisabledByCarrier) && mCi.getRadioState().isOn()) {
+        } else if ((!mDesiredPowerState || mRadioDisabledByCarrier) && mCi.getRadioState()
+                == TelephonyManager.RADIO_POWER_ON) {
             // If it's on and available and we want it off gracefully
             if (mPhone.isPhoneTypeGsm() && mPowerOffDelayNeed) {
                 if (mImsRegistrationOnOff && !mAlarmSwitch) {
@@ -2543,7 +2545,8 @@
                 DcTracker dcTracker = mPhone.mDcTracker;
                 powerOffRadioSafely(dcTracker);
             }
-        } else if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) {
+        } else if (mDeviceShuttingDown
+                && (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE)) {
             mCi.requestShutdown(null);
         }
     }
@@ -2660,7 +2663,7 @@
     }
 
     public boolean isRadioOn() {
-        return mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON;
+        return mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON;
     }
 
     /**
@@ -2690,7 +2693,7 @@
         log("pollState: modemTriggered=" + modemTriggered);
 
         switch (mCi.getRadioState()) {
-            case RADIO_UNAVAILABLE:
+            case TelephonyManager.RADIO_POWER_UNAVAILABLE:
                 mNewSS.setStateOutOfService();
                 mNewCellIdentity = null;
                 setSignalStrengthDefaultValues();
@@ -2698,7 +2701,7 @@
                 pollStateDone();
                 break;
 
-            case RADIO_OFF:
+            case TelephonyManager.RADIO_POWER_OFF:
                 mNewSS.setStateOff();
                 mNewCellIdentity = null;
                 setSignalStrengthDefaultValues();
@@ -3114,7 +3117,8 @@
 
     private void updateOperatorNameFromEri() {
         if (mPhone.isPhoneTypeCdma()) {
-            if ((mCi.getRadioState().isOn()) && (!mIsSubscriptionFromRuim)) {
+            if ((mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
+                    && (!mIsSubscriptionFromRuim)) {
                 String eriText;
                 // Now the Phone sees the new ServiceState so it can get the new ERI text
                 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
@@ -3130,10 +3134,11 @@
         } else if (mPhone.isPhoneTypeCdmaLte()) {
             boolean hasBrandOverride = mUiccController.getUiccCard(getPhoneId()) != null &&
                     mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null;
-            if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) &&
-                    (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology()) ||
-                            mPhone.getContext().getResources().getBoolean(com.android.internal.R.
-                                    bool.config_LTE_eri_for_network_name))) {
+            if (!hasBrandOverride && (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
+                    && (mPhone.isEriFileLoaded())
+                    && (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology())
+                    || mPhone.getContext().getResources().getBoolean(com.android.internal.R
+                    .bool.config_LTE_eri_for_network_name))) {
                 // Only when CDMA is in service, ERI will take effect
                 String eriText = mSS.getOperatorAlpha();
                 // Now the Phone sees the new ServiceState so it can get the new ERI text
@@ -4723,7 +4728,7 @@
      * causes state to go to OUT_OF_SERVICE state instead of STATE_OFF
      */
     protected void resetServiceStateInIwlanMode() {
-        if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+        if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
             boolean resetIwlanRatVal = false;
             log("set service state as POWER_OFF");
             if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index b304e5b..d59e601 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -535,7 +535,8 @@
         Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
         msg.obj = cp;
 
-        DataProfile dp = DcTracker.createDataProfile(mApnSetting, cp.mProfileId);
+        DataProfile dp = DcTracker.createDataProfile(mApnSetting, cp.mProfileId,
+                mApnSetting.equals(mDct.getPreferredApn()));
 
         // We need to use the actual modem roaming state instead of the framework roaming state
         // here. This flag is only passed down to ril_service for picking the correct protocol (for
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 5faf169..9a682e0 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -18,6 +18,9 @@
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
+import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
+import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
+
 import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -536,19 +539,7 @@
 
     private int mDisconnectPendingCount = 0;
 
-    /** Indicate if metered APNs are disabled.
-     *  set to block all the metered APNs from continuously sending requests, which causes
-     *  undesired network load */
-    private boolean mMeteredApnDisabled = false;
-
-    /**
-     * int to remember whether has setDataProfiles and with roaming or not.
-     * 0: default, has never set data profile
-     * 1: has set data profile with home protocol
-     * 2: has set data profile with roaming protocol
-     * This is not needed once RIL command is updated to support both home and roaming protocol.
-     */
-    private int mSetDataProfileStatus = 0;
+    private ArrayList<DataProfile> mLastDataProfileList = new ArrayList<>();
 
     /**
      * Handles changes to the APN db.
@@ -1919,9 +1910,13 @@
             return false;
         }
 
-        int profileId = apnSetting.getProfileId();
-        if (profileId == 0) {
-            profileId = getApnProfileID(apnContext.getApnType());
+        // profile id is only meaningful when the profile is persistent on the modem.
+        int profileId = DATA_PROFILE_INVALID;
+        if (apnSetting.isPersistent()) {
+            profileId = apnSetting.getProfileId();
+            if (profileId == DATA_PROFILE_DEFAULT) {
+                profileId = getApnProfileID(apnContext.getApnType());
+            }
         }
 
         // On CDMA, if we're explicitly asking for DUN, we need have
@@ -2053,7 +2048,8 @@
         } else {
             if (DBG) log("setInitialAttachApn: X selected Apn=" + initialAttachApnSetting);
 
-            mDataServiceManager.setInitialAttachApn(createDataProfile(initialAttachApnSetting),
+            mDataServiceManager.setInitialAttachApn(createDataProfile(initialAttachApnSetting,
+                            initialAttachApnSetting.equals(getPreferredApn())),
                     mPhone.getServiceState().getDataRoamingFromRegistration(), null);
         }
     }
@@ -2232,7 +2228,7 @@
         createAllApnList();
         setDataProfilesAsNeeded();
         setInitialAttachApn();
-        if (mPhone.mCi.getRadioState().isOn()) {
+        if (mPhone.mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
             if (DBG) log("onRecordsLoadedOrSubIdChanged: notifying data availability");
             notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
         }
@@ -3218,17 +3214,22 @@
     private void setDataProfilesAsNeeded() {
         if (DBG) log("setDataProfilesAsNeeded");
 
-        ArrayList<DataProfile> dps = new ArrayList<DataProfile>();
+        ArrayList<DataProfile> dataProfileList = new ArrayList<>();
+
         for (ApnSetting apn : mAllApnSettings) {
-            if (apn.getModemCognitive()) {
-                DataProfile dp = createDataProfile(apn);
-                if (!dps.contains(dp)) {
-                    dps.add(dp);
-                }
+            DataProfile dp = createDataProfile(apn, apn.equals(getPreferredApn()));
+            if (!dataProfileList.contains(dp)) {
+                dataProfileList.add(dp);
             }
         }
-        if (dps.size() > 0) {
-            mDataServiceManager.setDataProfile(dps,
+
+        // Check if the data profiles we are sending are same as we did last time. We don't want to
+        // send the redundant profiles to the modem. Also if there the list is empty, we don't
+        // send it to the modem.
+        if (!dataProfileList.isEmpty()
+                && (dataProfileList.size() != mLastDataProfileList.size()
+                || !mLastDataProfileList.containsAll(dataProfileList))) {
+            mDataServiceManager.setDataProfile(dataProfileList,
                     mPhone.getServiceState().getDataRoamingFromRegistration(), null);
         }
     }
@@ -3339,7 +3340,7 @@
             dest.getApnName(), proxy, port, mmsc, mmsProxy, mmsPort, dest.getUser(),
             dest.getPassword(), dest.getAuthType(), resultApnType, protocol, roamingProtocol,
             dest.isEnabled(), networkTypeBitmask, dest.getProfileId(),
-            (dest.getModemCognitive() || src.getModemCognitive()), dest.getMaxConns(),
+            (dest.isPersistent() || src.isPersistent()), dest.getMaxConns(),
             dest.getWaitTime(), dest.getMaxConnsTime(), dest.getMtu(), dest.getMvnoType(),
             dest.getMvnoMatchData(), dest.getApnSetId());
     }
@@ -3527,7 +3528,7 @@
         }
     }
 
-    private ApnSetting getPreferredApn() {
+    ApnSetting getPreferredApn() {
         if (mAllApnSettings == null || mAllApnSettings.isEmpty()) {
             log("getPreferredApn: mAllApnSettings is empty");
             return null;
@@ -4755,16 +4756,16 @@
         }
     }
 
-    private static DataProfile createDataProfile(ApnSetting apn) {
-        return createDataProfile(apn, apn.getProfileId());
+    private static DataProfile createDataProfile(ApnSetting apn, boolean isPreferred) {
+        return createDataProfile(apn, apn.getProfileId(), isPreferred);
     }
 
     @VisibleForTesting
-    public static DataProfile createDataProfile(ApnSetting apn, int profileId) {
+    public static DataProfile createDataProfile(ApnSetting apn, int profileId,
+                                                boolean isPreferred) {
         int profileType;
 
-        int bearerBitmap = 0;
-        bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+        int bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
                 apn.getNetworkTypeBitmask());
 
         if (bearerBitmap == 0) {
@@ -4776,12 +4777,11 @@
         }
 
         return new DataProfile(profileId, apn.getApnName(),
-            ApnSetting.getProtocolStringFromInt(apn.getProtocol()), apn.getAuthType(),
-            apn.getUser(), apn.getPassword(), profileType, apn.getMaxConnsTime(),
-            apn.getMaxConns(), apn.getWaitTime(), apn.isEnabled(), apn.getApnTypeBitmask(),
-            ApnSetting.getProtocolStringFromInt(apn.getRoamingProtocol()), bearerBitmap,
-            apn.getMtu(), ApnSetting.getMvnoTypeStringFromInt(apn.getMvnoType()),
-            apn.getMvnoMatchData(), apn.getModemCognitive());
+                ApnSetting.getProtocolStringFromInt(apn.getProtocol()), apn.getAuthType(),
+                apn.getUser(), apn.getPassword(), profileType, apn.getMaxConnsTime(),
+                apn.getMaxConns(),  apn.getWaitTime(), apn.isEnabled(), apn.getApnTypeBitmask(),
+                ApnSetting.getProtocolStringFromInt(apn.getRoamingProtocol()), bearerBitmap,
+                apn.getMtu(), apn.isPersistent(), isPreferred);
     }
 
     private void onDataServiceBindingChanged(boolean bound) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 82f4702..99847ad 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -2744,9 +2744,20 @@
         @Override
         public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
             ImsReasonInfo reasonInfo) {
+            // Check with the DCTracker to see if data is enabled; there may be a case when
+            // ImsPhoneCallTracker isn't being informed of the right data enabled state via its
+            // registration, so we'll refresh now.
+            boolean isDataEnabled = mPhone.getDefaultPhone().mDcTracker.isDataEnabled();
             if (DBG) {
-                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech=" +
-                        targetAccessTech + ", reasonInfo=" + reasonInfo);
+                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech="
+                        + targetAccessTech + ", reasonInfo=" + reasonInfo + ", dataEnabled="
+                        + mIsDataEnabled + "/" + isDataEnabled + ", dataMetered="
+                        + mIsViLteDataMetered);
+            }
+            if (mIsDataEnabled != isDataEnabled) {
+                loge("onCallHandover: data enabled state doesn't match! (was=" + mIsDataEnabled
+                        + ", actually=" + isDataEnabled);
+                mIsDataEnabled = isDataEnabled;
             }
 
             // Only consider it a valid handover to WIFI if the source radio tech is known.
@@ -2791,7 +2802,7 @@
                         conn.setLocalVideoCapable(mIsDataEnabled);
                     }
 
-                    if (mNotifyHandoverVideoFromWifiToLTE &&    mIsDataEnabled) {
+                    if (mNotifyHandoverVideoFromWifiToLTE && mIsDataEnabled) {
                         if (conn.getDisconnectCause() == DisconnectCause.NOT_DISCONNECTED) {
                             log("onCallHandover :: notifying of WIFI to LTE handover.");
                             conn.onConnectionEvent(
@@ -2808,6 +2819,7 @@
                     if (!mIsDataEnabled && mIsViLteDataMetered) {
                         // Call was downgraded from WIFI to LTE and data is metered; downgrade the
                         // call now.
+                        log("onCallHandover :: data is not enabled; attempt to downgrade.");
                         downgradeVideoCall(ImsReasonInfo.CODE_WIFI_LOST, conn);
                     }
                 }
@@ -3889,16 +3901,21 @@
                     Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
                             Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)
                             && !mSupportPauseVideo) {
-
+                log("downgradeVideoCall :: callId=" + conn.getTelecomCallId()
+                        + " Downgrade to audio");
                 // If the carrier supports downgrading to voice, then we can simply issue a
                 // downgrade to voice instead of terminating the call.
                 modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
             } else if (mSupportPauseVideo && reasonCode != ImsReasonInfo.CODE_WIFI_LOST) {
                 // The carrier supports video pause signalling, so pause the video if we didn't just
                 // lose wifi; in that case just disconnect.
+                log("downgradeVideoCall :: callId=" + conn.getTelecomCallId()
+                        + " Pause audio");
                 mShouldUpdateImsConfigOnDisconnect = true;
                 conn.pauseVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
             } else {
+                log("downgradeVideoCall :: callId=" + conn.getTelecomCallId()
+                        + " Disconnect call.");
                 // At this point the only choice we have is to terminate the call.
                 try {
                     imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index e3c147b..be05cbd 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -39,6 +39,7 @@
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
 
@@ -158,7 +159,7 @@
 
         simulatedCallState = new SimulatedGsmCallState(looper);
 
-        setRadioState(RadioState.RADIO_ON, false /* forceNotifyRegistrants */);
+        setRadioState(TelephonyManager.RADIO_POWER_ON, false /* forceNotifyRegistrants */);
         mSimLockedState = INITIAL_LOCK_STATE;
         mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
         mPinCode = DEFAULT_SIM_PIN_CODE;
@@ -505,7 +506,7 @@
     @Override
     public void getCurrentCalls (Message result) {
         SimulatedCommandsVerifier.getInstance().getCurrentCalls(result);
-        if ((mState == RadioState.RADIO_ON) && !isSimLocked()) {
+        if ((mState == TelephonyManager.RADIO_POWER_ON) && !isSimLocked()) {
             //Rlog.i("GSM", "[SimCmds] getCurrentCalls");
             resultSuccess(result, simulatedCallState.getDriverCalls());
         } else {
@@ -1241,9 +1242,9 @@
         }
 
         if(on) {
-            setRadioState(RadioState.RADIO_ON, false /* forceNotifyRegistrants */);
+            setRadioState(TelephonyManager.RADIO_POWER_ON, false /* forceNotifyRegistrants */);
         } else {
-            setRadioState(RadioState.RADIO_OFF, false /* forceNotifyRegistrants */);
+            setRadioState(TelephonyManager.RADIO_POWER_OFF, false /* forceNotifyRegistrants */);
         }
         resultSuccess(result, null);
     }
@@ -1599,7 +1600,7 @@
     @Override
     public void
     shutdown() {
-        setRadioState(RadioState.RADIO_UNAVAILABLE, false /* forceNotifyRegistrants */);
+        setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, false /* forceNotifyRegistrants */);
         Looper looper = mHandlerThread.getLooper();
         if (looper != null) {
             looper.quit();
@@ -2024,7 +2025,7 @@
 
     @Override
     public void requestShutdown(Message result) {
-        setRadioState(RadioState.RADIO_UNAVAILABLE, false /* forceNotifyRegistrants */);
+        setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, false /* forceNotifyRegistrants */);
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java b/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
index 12e27e1..4460489 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
@@ -22,6 +22,7 @@
 import android.os.Message;
 import android.telephony.ImsiEncryptionInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.TelephonyManager;
 import android.telephony.data.DataProfile;
 
 import com.android.internal.telephony.CommandsInterface;
@@ -45,8 +46,8 @@
     }
 
     @Override
-    public RadioState getRadioState() {
-        return null;
+    public int getRadioState() {
+        return TelephonyManager.RADIO_POWER_UNAVAILABLE;
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 0656831..af01a90 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -115,7 +115,6 @@
     private UiccSlot[] mUiccSlots;
     private int[] mPhoneIdToSlotId;
     private boolean mIsSlotStatusSupported = true;
-    private boolean mIsCdmaSupported = true;
 
     private static final Object mLock = new Object();
     private static UiccController mInstance;
@@ -183,11 +182,6 @@
         }
 
         mLauncher = new UiccStateChangedLauncher(c, this);
-
-        // set mIsCdmaSupported based on PackageManager.FEATURE_TELEPHONY_CDMA
-        PackageManager packageManager = c.getPackageManager();
-        mIsCdmaSupported =
-                packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
     }
 
     private int getSlotIdFromPhoneId(int phoneId) {
@@ -702,8 +696,16 @@
         mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index));
     }
 
-    public boolean isCdmaSupported() {
-        return mIsCdmaSupported;
+    /**
+     * static method to return whether CDMA is supported on the device
+     * @param context object representative of the application that is calling this method
+     * @return true if CDMA is supported by the device
+     */
+    public static boolean isCdmaSupported(Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        boolean isCdmaSupported =
+                packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
+        return isCdmaSupported;
     }
 
     private boolean isValidPhoneIndex(int index) {
@@ -733,7 +735,7 @@
         }
         pw.println();
         pw.flush();
-        pw.println(" mIsCdmaSupported=" + mIsCdmaSupported);
+        pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext));
         pw.println(" mUiccSlots: size=" + mUiccSlots.length);
         for (int i = 0; i < mUiccSlots.length; i++) {
             if (mUiccSlots[i] == null) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 5a293da..94af660 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -960,7 +960,7 @@
         // TODO: 2/15/18 Add check to see if ISIM app will go to READY state, and if yes, check for
         // ISIM also (currently ISIM is considered as not supported in this function)
         if (app.getType() == AppType.APPTYPE_USIM || app.getType() == AppType.APPTYPE_SIM
-                || (UiccController.getInstance().isCdmaSupported()
+                || (UiccController.isCdmaSupported(mContext)
                 && (app.getType() == AppType.APPTYPE_CSIM
                 || app.getType() == AppType.APPTYPE_RUIM))) {
             return true;
@@ -1109,6 +1109,7 @@
 
     private void promptInstallCarrierApp(String pkgName) {
         Intent showDialogIntent = InstallCarrierAppTrampolineActivity.get(mContext, pkgName);
+        showDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         mContext.startActivity(showDialogIntent);
     }
 
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index 0fa71c3..405085d 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -27,11 +27,11 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
 import android.view.WindowManager;
 
 import com.android.internal.R;
 import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.CommandsInterface.RadioState;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
 import com.android.internal.telephony.uicc.euicc.EuiccCard;
@@ -57,7 +57,7 @@
     private Context mContext;
     private CommandsInterface mCi;
     private UiccCard mUiccCard;
-    private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE;
+    private int mLastRadioState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
     private boolean mIsEuicc;
     private String mIccId;
     private AnswerToReset mAtr;
@@ -86,7 +86,7 @@
             parseAtr(ics.atr);
             mCi = ci;
 
-            RadioState radioState = mCi.getRadioState();
+            int radioState = mCi.getRadioState();
             if (DBG) {
                 log("update: radioState=" + radioState + " mLastRadioState=" + mLastRadioState);
             }
@@ -100,7 +100,8 @@
             } else if ((oldState == null || oldState == CardState.CARDSTATE_ABSENT
                     || mUiccCard == null) && mCardState != CardState.CARDSTATE_ABSENT) {
                 // No notifications while radio is off or we just powering up
-                if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
+                if (radioState == TelephonyManager.RADIO_POWER_ON
+                        && mLastRadioState == TelephonyManager.RADIO_POWER_ON) {
                     if (DBG) log("update: notify card added");
                     sendMessage(obtainMessage(EVENT_CARD_ADDED, null));
                 }
@@ -141,7 +142,7 @@
                 // even if it's inactive.
                 if (mActive) {
                     mActive = false;
-                    mLastRadioState = RadioState.RADIO_UNAVAILABLE;
+                    mLastRadioState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
                     mPhoneId = INVALID_PHONE_ID;
                     if (mUiccCard != null) mUiccCard.dispose();
                     nullifyUiccCard(true /* sim state is unknown */);
@@ -165,10 +166,11 @@
     }
 
     private void updateCardStateAbsent() {
-        RadioState radioState =
-                (mCi == null) ? RadioState.RADIO_UNAVAILABLE : mCi.getRadioState();
+        int radioState =
+                (mCi == null) ? TelephonyManager.RADIO_POWER_UNAVAILABLE : mCi.getRadioState();
         // No notifications while radio is off or we just powering up
-        if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
+        if (radioState == TelephonyManager.RADIO_POWER_ON
+                && mLastRadioState == TelephonyManager.RADIO_POWER_ON) {
             if (DBG) log("update: notify card removed");
             sendMessage(obtainMessage(EVENT_CARD_REMOVED, null));
         }
@@ -366,7 +368,7 @@
         }
 
         mCardState = CardState.CARDSTATE_ABSENT;
-        mLastRadioState = RadioState.RADIO_UNAVAILABLE;
+        mLastRadioState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
     }
 
     private void log(String msg) {
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java b/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
index 636aa1c..b5083a1 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/EuiccCard.java
@@ -83,7 +83,8 @@
     // Error code for no result available when retrieving notifications.
     private static final int CODE_NO_RESULT_AVAILABLE = 1;
 
-    private static final EuiccSpecVersion SGP_2_0 = new EuiccSpecVersion(2, 0, 0);
+    private static final EuiccSpecVersion SGP22_V_2_0 = new EuiccSpecVersion(2, 0, 0);
+    private static final EuiccSpecVersion SGP22_V_2_1 = new EuiccSpecVersion(2, 1, 0);
 
     // Device capabilities.
     private static final String DEV_CAP_GSM = "gsm";
@@ -982,10 +983,69 @@
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected byte[] getDeviceId() {
-        byte[] imeiBytes = new byte[8];
         Phone phone = PhoneFactory.getPhone(getPhoneId());
-        if (phone != null) {
-            IccUtils.bcdToBytes(phone.getDeviceId(), imeiBytes);
+        if (phone == null) {
+            return new byte[8];
+        }
+        return getDeviceId(phone.getDeviceId(), mSpecVersion);
+    }
+
+    /**
+     * Different versions of SGP.22 specify different encodings of the device's IMEI, so we handle
+     * those differences here.
+     *
+     * @param imei The IMEI of the device. Assumed to be 15 decimal digits.
+     * @param specVersion The SGP.22 version which we're encoding the IMEI for.
+     * @return A byte string representing the given IMEI according to the specified SGP.22 version.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public static byte[] getDeviceId(String imei, EuiccSpecVersion specVersion) {
+        byte[] imeiBytes = new byte[8];
+        // The IMEI's encoding is version-dependent.
+        if (specVersion.compareTo(SGP22_V_2_1) >= 0) {
+            /*
+             * In SGP.22 v2.1, a clarification was added to clause 4.2 that requires the nibbles of
+             * the last byte to be swapped from normal TBCD encoding (so put back in normal order):
+             *
+             * The IMEI (including the check digit) SHALL be represented as a string of 8 octets
+             * that is coded as a Telephony Binary Coded Decimal String as defined in 3GPP TS 29.002
+             * [63], except that the last octet contains the check digit (in high nibble) and an 'F'
+             * filler (in low nibble). It SHOULD be present if the Device contains a non-removable
+             * eUICC.
+             *
+             * 3GPP TS 29.002 clause 17.7.8 in turn says this:
+             *
+             * TBCD-STRING ::= OCTET STRING
+             * This type (Telephony Binary Coded Decimal String) is used to represent several digits
+             * from 0 through 9, *, #, a, b, c, two digits per octet, each digit encoded 0000 to
+             * 1001 (0 to 9), 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used as
+             * filler when there is an odd number of digits.
+             * Bits 8765 of octet n encoding digit 2n
+             * Bits 4321 of octet n encoding digit 2(n-1) + 1
+             */
+            // Since the IMEI is always just decimal digits, we can still use BCD encoding (which
+            // correctly swaps digit ordering within bytes), but we have to manually pad a 0xF value
+            // instead of 0.
+            imei += 'F';
+            IccUtils.bcdToBytes(imei, imeiBytes);
+            // And now the funky last byte flip (this is not normal TBCD, the GSMA added it on top
+            // just for the IMEI for some reason). Bitwise operations promote to int first, so we
+            // have to do some extra masking.
+            byte last = imeiBytes[7];
+            imeiBytes[7] = (byte) ((last & 0xFF) << 4 | ((last & 0xFF) >>> 4));
+        } else {
+            /*
+             * Prior to SGP.22 v2.1, clause 4.2 reads as follows:
+             *
+             * The IMEI (including the check digit) SHALL be represented as a string of 8 octets
+             * that is BCD coded as defined in 3GPP TS 23.003 [35]. It SHOULD be present if the
+             * Device contains a non-removable eUICC.
+             *
+             * It appears that 3GPP TS 23.003 doesn't define anything about BCD encoding, it just
+             * defines what IMEI and a few other telephony identifiers are. We default to normal BCD
+             * encoding since the spec is unclear here.
+             */
+            IccUtils.bcdToBytes(imei, imeiBytes);
         }
         return imeiBytes;
     }
@@ -1002,7 +1062,7 @@
                 throw new EuiccCardException("Cannot get eUICC spec version.");
             }
             try {
-                if (ver.compareTo(SGP_2_0) < 0) {
+                if (ver.compareTo(SGP22_V_2_0) < 0) {
                     throw new EuiccCardException("eUICC spec version is unsupported: " + ver);
                 }
                 builder.build(requestBuilder);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
index 358fa61..2dc5c66 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
@@ -168,7 +168,7 @@
         mSpyCarrierSST.getContentObserver().dispatchChange(false,
                 Settings.Global.getUriFor(prefNetworkMode));
         waitForMs(500);
-        verify(mNotificationManager).notify(
+        verify(mNotificationManager, atLeast(1)).notify(
                 eq(CarrierServiceStateTracker.NOTIFICATION_PREF_NETWORK), isA(Notification.class));
 
         Settings.Global.putInt(mContext.getContentResolver(), prefNetworkMode,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 6bdb23b..4fcc20b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -229,7 +229,7 @@
     private static final int MTU = 1234;
     private static final String MVNO_TYPE = "";
     private static final String MVNO_MATCH_DATA = "";
-    private static final boolean MODEM_COGNITIVE = true;
+    private static final boolean PERSISTENT = true;
 
     private class RILTestHandler extends HandlerThread {
 
@@ -704,7 +704,7 @@
                 null, null, -1, "", "", 0, ApnSetting.TYPE_DUN, ApnSetting.PROTOCOL_IP,
                 ApnSetting.PROTOCOL_IP, true, 0, 0, false, 0, 0, 0, 0, -1, "");
         DataProfile dataProfile = DcTracker.createDataProfile(
-                apnSetting, apnSetting.getProfileId());
+                apnSetting, apnSetting.getProfileId(), false);
         boolean isRoaming = false;
 
         mRILUnderTest.setInitialAttachApn(dataProfile, isRoaming, obtainMessage());
@@ -715,7 +715,7 @@
                         "convertToHalDataProfile",
                         new Class<?>[] {DataProfile.class},
                         new Object[] {dataProfile})),
-                eq(dataProfile.isModemCognitive()),
+                eq(dataProfile.isPersistent()),
                 eq(isRoaming));
         verifyRILResponse(
                 mRILUnderTest, mSerialNumberCaptor.getValue(), RIL_REQUEST_SET_INITIAL_ATTACH_APN);
@@ -1727,7 +1727,7 @@
 
         DataProfile dp = new DataProfile(PROFILE_ID, APN, PROTOCOL, AUTH_TYPE, USER_NAME, PASSWORD,
                 TYPE, MAX_CONNS_TIME, MAX_CONNS, WAIT_TIME, APN_ENABLED, SUPPORTED_APNT_YPES_BITMAP,
-                ROAMING_PROTOCOL, BEARER_BITMAP, MTU, MVNO_TYPE, MVNO_MATCH_DATA, MODEM_COGNITIVE);
+                ROAMING_PROTOCOL, BEARER_BITMAP, MTU, PERSISTENT, false);
         mRILUnderTest.setupDataCall(AccessNetworkConstants.AccessNetworkType.EUTRAN, dp, false,
                 false, 0, null, obtainMessage());
         ArgumentCaptor<DataProfileInfo> dpiCaptor = ArgumentCaptor.forClass(DataProfileInfo.class);
@@ -1752,7 +1752,5 @@
         assertEquals(ROAMING_PROTOCOL, dpi.protocol);
         assertEquals(BEARER_BITMAP, dpi.bearerBitmap);
         assertEquals(MTU, dpi.mtu);
-        assertEquals(0, dpi.mvnoType);
-        assertEquals(MVNO_MATCH_DATA, dpi.mvnoMatchData);
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index e631269..1913544 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -58,6 +58,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.Telephony;
 import android.support.test.filters.FlakyTest;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CarrierConfigManager;
@@ -209,10 +210,11 @@
     @Test
     @MediumTest
     public void testSetRadioPower() {
-        boolean oldState = mSimulatedCommands.getRadioState().isOn();
+        boolean oldState = (mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
         sst.setRadioPower(!oldState);
         waitForMs(100);
-        assertTrue(oldState != mSimulatedCommands.getRadioState().isOn());
+        assertTrue(oldState
+                != (mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON));
     }
 
     @Test
@@ -233,21 +235,23 @@
         // Carrier disable radio power
         sst.setRadioPowerFromCarrier(false);
         waitForMs(100);
-        assertFalse(mSimulatedCommands.getRadioState().isOn());
+        assertFalse(mSimulatedCommands.getRadioState()
+                == TelephonyManager.RADIO_POWER_ON);
         assertTrue(sst.getDesiredPowerState());
         assertFalse(sst.getPowerStateFromCarrier());
 
         // User toggle radio power will not overrides carrier settings
         sst.setRadioPower(true);
         waitForMs(100);
-        assertFalse(mSimulatedCommands.getRadioState().isOn());
+        assertFalse(mSimulatedCommands.getRadioState()
+                == TelephonyManager.RADIO_POWER_ON);
         assertTrue(sst.getDesiredPowerState());
         assertFalse(sst.getPowerStateFromCarrier());
 
         // Carrier re-enable radio power
         sst.setRadioPowerFromCarrier(true);
         waitForMs(100);
-        assertTrue(mSimulatedCommands.getRadioState().isOn());
+        assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
         assertTrue(sst.getDesiredPowerState());
         assertTrue(sst.getPowerStateFromCarrier());
 
@@ -255,7 +259,8 @@
         sst.setRadioPower(false);
         sst.setRadioPowerFromCarrier(true);
         waitForMs(100);
-        assertFalse(mSimulatedCommands.getRadioState().isOn());
+        assertFalse(mSimulatedCommands.getRadioState()
+                == TelephonyManager.RADIO_POWER_ON);
         assertFalse(sst.getDesiredPowerState());
         assertTrue(sst.getPowerStateFromCarrier());
     }
@@ -1593,7 +1598,8 @@
 
         sst.requestShutdown();
         waitForMs(100);
-        assertFalse(mSimulatedCommands.getRadioState().isAvailable());
+        assertFalse(mSimulatedCommands.getRadioState()
+                != TelephonyManager.RADIO_POWER_UNAVAILABLE);
     }
 
     @Test
@@ -1606,10 +1612,11 @@
         mSimulatedCommands.setRadioPowerFailResponse(true);
         sst.setRadioPower(false);
         waitForMs(100);
-        assertTrue(mSimulatedCommands.getRadioState().isOn());
+        assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
         sst.requestShutdown();
         waitForMs(100);
-        assertFalse(mSimulatedCommands.getRadioState().isAvailable());
+        assertFalse(mSimulatedCommands.getRadioState()
+                != TelephonyManager.RADIO_POWER_UNAVAILABLE);
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 2cf880b..ad7adcb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -383,6 +383,8 @@
         doReturn(mServiceState).when(mPhone).getServiceState();
         doReturn(mServiceState).when(mImsPhone).getServiceState();
         doReturn(mPhone).when(mImsPhone).getDefaultPhone();
+        mPhone.mDcTracker = mDcTracker;
+        doReturn(true).when(mDcTracker).isDataEnabled();
         doReturn(true).when(mPhone).isPhoneTypeGsm();
         doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
         doReturn(mCT).when(mPhone).getCallTracker();
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 b9738e5..86d2a0b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
@@ -120,7 +120,7 @@
         assertEquals(a1.getApnTypeBitmask(), a2.getApnTypeBitmask());
         assertEquals(a1.isEnabled(), a2.isEnabled());
         assertEquals(a1.getProfileId(), a2.getProfileId());
-        assertEquals(a1.getModemCognitive(), a2.getModemCognitive());
+        assertEquals(a1.isPersistent(), a2.isPersistent());
         assertEquals(a1.getMaxConns(), a2.getMaxConns());
         assertEquals(a1.getWaitTime(), a2.getWaitTime());
         assertEquals(a1.getMaxConnsTime(), a2.getMaxConnsTime());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataProfileTest.java
index 97fcc75..d657cf8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataProfileTest.java
@@ -110,7 +110,7 @@
 
     @SmallTest
     public void testCreateFromApnSetting() throws Exception {
-        DataProfile dp = DcTracker.createDataProfile(mApn1, mApn1.getProfileId());
+        DataProfile dp = DcTracker.createDataProfile(mApn1, mApn1.getProfileId(), false);
         assertEquals(mApn1.getProfileId(), dp.getProfileId());
         assertEquals(mApn1.getApnName(), dp.getApn());
         assertEquals(ApnSetting.getProtocolStringFromInt(mApn1.getProtocol()), dp.getProtocol());
@@ -118,15 +118,15 @@
         assertEquals(mApn1.getUser(), dp.getUserName());
         assertEquals(mApn1.getPassword(), dp.getPassword());
         assertEquals(0, dp.getType());  // TYPE_COMMON
-        assertEquals(mApn1.getMaxConnsTime(), dp.getMaxConnsTime());
-        assertEquals(mApn1.getMaxConns(), dp.getMaxConns());
         assertEquals(mApn1.getWaitTime(), dp.getWaitTime());
         assertEquals(mApn1.isEnabled(), dp.isEnabled());
+        assertFalse(dp.isPersistent());
+        assertFalse(dp.isPreferred());
     }
 
     @SmallTest
     public void testCreateFromApnSettingWithNetworkTypeBitmask() throws Exception {
-        DataProfile dp = DcTracker.createDataProfile(mApn3, mApn3.getProfileId());
+        DataProfile dp = DcTracker.createDataProfile(mApn3, mApn3.getProfileId(), false);
         assertEquals(mApn3.getProfileId(), dp.getProfileId());
         assertEquals(mApn3.getApnName(), dp.getApn());
         assertEquals(ApnSetting.getProtocolStringFromInt(mApn3.getProtocol()), dp.getProtocol());
@@ -134,8 +134,6 @@
         assertEquals(mApn3.getUser(), dp.getUserName());
         assertEquals(mApn3.getPassword(), dp.getPassword());
         assertEquals(2, dp.getType());  // TYPE_3GPP2
-        assertEquals(mApn3.getMaxConnsTime(), dp.getMaxConnsTime());
-        assertEquals(mApn3.getMaxConns(), dp.getMaxConns());
         assertEquals(mApn3.getWaitTime(), dp.getWaitTime());
         assertEquals(mApn3.isEnabled(), dp.isEnabled());
         int expectedBearerBitmap =
@@ -146,11 +144,11 @@
 
     @SmallTest
     public void testEquals() throws Exception {
-        DataProfile dp1 = DcTracker.createDataProfile(mApn1, mApn1.getProfileId());
-        DataProfile dp2 = DcTracker.createDataProfile(mApn1, mApn1.getProfileId());
+        DataProfile dp1 = DcTracker.createDataProfile(mApn1, mApn1.getProfileId(), false);
+        DataProfile dp2 = DcTracker.createDataProfile(mApn1, mApn1.getProfileId(), false);
         assertEquals(dp1, dp2);
 
-        dp2 = DcTracker.createDataProfile(mApn2, mApn2.getProfileId());
+        dp2 = DcTracker.createDataProfile(mApn2, mApn2.getProfileId(), false);
         assertFalse(dp1.equals(dp2));
     }
 }
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 8015315..ae1a4dd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -255,7 +255,7 @@
                             ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer
                             0,                      // bearer_bitmask
                             0,                      // profile_id
-                            0,                      // modem_cognitive
+                            1,                      // modem_cognitive
                             0,                      // max_conns
                             0,                      // wait_time
                             0,                      // max_conns_time
@@ -286,7 +286,7 @@
                             ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer,
                             0,                      // bearer_bitmask
                             0,                      // profile_id
-                            0,                      // modem_cognitive
+                            1,                      // modem_cognitive
                             0,                      // max_conns
                             0,                      // wait_time
                             0,                      // max_conns_time
@@ -317,7 +317,7 @@
                             0,                      // bearer
                             0,                      // bearer_bitmask
                             0,                      // profile_id
-                            0,                      // modem_cognitive
+                            1,                      // modem_cognitive
                             0,                      // max_conns
                             0,                      // wait_time
                             0,                      // max_conns_time
@@ -348,7 +348,7 @@
                             ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD, // bearer
                             0,                      // bearer_bitmask
                             0,                      // profile_id
-                            0,                      // modem_cognitive
+                            1,                      // modem_cognitive
                             0,                      // max_conns
                             0,                      // wait_time
                             0,                      // max_conns_time
@@ -379,7 +379,7 @@
                             0,                      // bearer
                             0,                      // bearer_bitmask
                             0,                      // profile_id
-                            0,                      // modem_cognitive
+                            1,                      // modem_cognitive
                             0,                      // max_conns
                             0,                      // wait_time
                             0,                      // max_conns_time
@@ -518,17 +518,14 @@
         assertEquals("", dp.getUserName());
         assertEquals("", dp.getPassword());
         assertEquals(type, dp.getType());
-        assertEquals(0, dp.getMaxConnsTime());
-        assertEquals(0, dp.getMaxConns());
         assertEquals(0, dp.getWaitTime());
         assertTrue(dp.isEnabled());
         assertEquals(supportedApnTypesBitmap, dp.getSupportedApnTypesBitmap());
         assertEquals("IP", dp.getRoamingProtocol());
         assertEquals(bearerBitmask, dp.getBearerBitmap());
         assertEquals(0, dp.getMtu());
-        assertEquals("", dp.getMvnoType());
-        assertEquals("", dp.getMvnoMatchData());
-        assertFalse(dp.isModemCognitive());
+        assertTrue(dp.isPersistent());
+        assertFalse(dp.isPreferred());
     }
 
     private void verifyDataConnected(final String apnSetting) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
index 24f8cbc..58527d3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
@@ -412,4 +412,9 @@
     public void notifyPhoneCapabilityChanged(PhoneCapability capability) {
         throw new RuntimeException("Not implemented");
     }
+
+    @Override
+    public void notifyRadioPowerStateChanged(int state) {
+        throw new RuntimeException("Not implemented");
+    }
 }
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 756015d..0c3bcee 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -30,6 +30,7 @@
 import android.os.HandlerThread;
 import android.os.Message;
 import android.support.test.filters.SmallTest;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.TelephonyTest;
@@ -143,8 +144,7 @@
         mSimulatedCommands.requestShutdown(null);
         waitForMs(50);
         assertNull(mUiccControllerUT.getUiccCard(0));
-        assertEquals(CommandsInterface.RadioState.RADIO_UNAVAILABLE,
-                mSimulatedCommands.getRadioState());
+        assertEquals(TelephonyManager.RADIO_POWER_UNAVAILABLE, mSimulatedCommands.getRadioState());
     }
 
     @Test@SmallTest
@@ -152,7 +152,7 @@
         mSimulatedCommands.setRadioPower(true, null);
         waitForMs(500);
         assertNotNull(mUiccControllerUT.getUiccCard(0));
-        assertEquals(CommandsInterface.RadioState.RADIO_ON, mSimulatedCommands.getRadioState());
+        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
     }
 
     @Test @SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
index b76f2cf..e99a4e5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -551,7 +552,8 @@
     @SmallTest
     public void testUpdateUiccProfileApplicationCdmaSupported() {
         // CDMA supported
-        doReturn(true).when(mUiccController).isCdmaSupported();
+        doReturn(true)
+            .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
 
         testWithCsimApp();
 
@@ -562,8 +564,9 @@
     @Test
     @SmallTest
     public void testUpdateUiccProfileApplicationCdmaNotSupported() {
-        // CDMA supported
-        doReturn(false).when(mUiccController).isCdmaSupported();
+        // CDMA not supported
+        doReturn(false)
+            .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
 
         testWithCsimApp();
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
index 6f488a8..40e113a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
@@ -984,6 +984,22 @@
         assertFalse(node.hasChild(Tags.TAG_CTX_0));
     }
 
+    @Test
+    public void testGetDeviceId() {
+        // Unclear v2.0 definition
+        assertArrayEquals(
+                new byte[] {0x21, 0x43, 0x65, (byte) 0x87, 0x09, 0x21, 0x43, 0x05},
+                EuiccCard.getDeviceId("123456789012345", new EuiccSpecVersion(2, 0, 0)));
+        // Clarified v2.1+ definition
+        assertArrayEquals(
+                new byte[] {0x21, 0x43, 0x65, (byte) 0x87, 0x09, 0x21, 0x43, 0x5F},
+                EuiccCard.getDeviceId("123456789012345", new EuiccSpecVersion(2, 1, 0)));
+        // Same definition on v2.2
+        assertArrayEquals(
+                new byte[] {0x21, 0x43, 0x65, (byte) 0x87, 0x09, 0x21, 0x43, 0x5F},
+                EuiccCard.getDeviceId("123456789012345", new EuiccSpecVersion(2, 2, 0)));
+    }
+
     private void verifyStoreData(int channel, String command) {
         verify(mMockCi, times(1))
                 .iccTransmitApduLogicalChannel(eq(channel), eq(0x80 | channel), eq(0xE2), eq(0x91),