Merge "Fix a bug where the subtype is not initialized correctly"
diff --git a/src/java/com/android/internal/telephony/AppSmsManager.java b/src/java/com/android/internal/telephony/AppSmsManager.java
index f473c9a..ebd0891 100644
--- a/src/java/com/android/internal/telephony/AppSmsManager.java
+++ b/src/java/com/android/internal/telephony/AppSmsManager.java
@@ -144,7 +144,7 @@
      * Handle an incoming SMS_DELIVER_ACTION intent if it is an app-only SMS.
      */
     public boolean handleSmsReceivedIntent(Intent intent) {
-        // Sanity check the action.
+        // Correctness check the action.
         if (intent.getAction() != Intents.SMS_DELIVER_ACTION) {
             Log.wtf(LOG_TAG, "Got intent with incorrect action: " + intent.getAction());
             return false;
diff --git a/src/java/com/android/internal/telephony/CarrierSignalAgent.java b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
index ed7eb47..6b8271a 100644
--- a/src/java/com/android/internal/telephony/CarrierSignalAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
@@ -285,7 +285,7 @@
 
     /**
      * Broadcast the intents explicitly.
-     * Some sanity check will be applied before broadcasting.
+     * Some correctness checks will be applied before broadcasting.
      * - for non-wakeup(runtime) receivers, make sure the intent is not declared in their manifests
      * and apply FLAG_EXCLUDE_STOPPED_PACKAGES to avoid wake-up
      * - for wakeup(manifest) receivers, make sure there are matched receivers with registered
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 1d43378..6805591 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -790,7 +790,7 @@
         if (ar.exception == null) {
             polledCalls = (List)ar.result;
         } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
-            // just a dummy empty ArrayList to cause the loop
+            // just a placeholder empty ArrayList to cause the loop
             // to hang up all the calls
             polledCalls = new ArrayList();
         } else {
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 3a3b35b..c3c3968 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -3986,7 +3986,7 @@
     @Override
     public IccCard getIccCard() {
         // This function doesn't return null for backwards compatability purposes.
-        // To differentiate between cases where SIM is absent vs. unknown we return a dummy
+        // To differentiate between cases where SIM is absent vs. unknown we return a placeholder
         // IccCard with the sim state set.
         IccCard card = getUiccProfile();
         if (card != null) {
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index 9d0c8c6..b36a19e 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -62,7 +62,7 @@
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                 publicAlternatives = "There is no alternative for {@code MccTable.MccEntry.mIso}, "
                         + "but it was included in hidden APIs due to a static analysis false "
-                        + "positive and has been made greylist-max-q. Please file a bug if you "
+                        + "positive and has been made max Q. Please file a bug if you "
                         + "still require this API.")
         public final String mIso;
         final int mSmallestDigitsMnc;
@@ -253,7 +253,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "There is no alternative for {@code MccTable"
                     + ".smallestDigitsMccForMnc}, but it was included in hidden APIs due to a "
-                    + "static analysis false positive and has been made greylist-max-q. Please "
+                    + "static analysis false positive and has been made max Q. Please "
                     + "file a bug if you still require this API.")
     public static int smallestDigitsMccForMnc(int mcc) {
         MccEntry entry = entryForMcc(mcc);
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index 94ea9d0..8b03347 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -68,6 +68,7 @@
     private static final int CMD_INTERRUPT_NETWORK_SCAN = 6;
     private static final int EVENT_INTERRUPT_NETWORK_SCAN_DONE = 7;
     private static final int EVENT_MODEM_RESET = 8;
+    private static final int EVENT_RADIO_UNAVAILABLE = 9;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -102,6 +103,8 @@
                     mScheduler.interruptScanDone((AsyncResult) msg.obj);
                     break;
 
+                case EVENT_RADIO_UNAVAILABLE:
+                    // Fallthrough
                 case EVENT_MODEM_RESET:
                     AsyncResult ar = (AsyncResult) msg.obj;
                     mScheduler.deleteScanAndMayNotify(
@@ -564,6 +567,7 @@
                 nsri.mPhone.startNetworkScan(nsri.getRequest(),
                         mHandler.obtainMessage(EVENT_START_NETWORK_SCAN_DONE, nsri));
                 nsri.mPhone.mCi.registerForModemReset(mHandler, EVENT_MODEM_RESET, nsri);
+                nsri.mPhone.mCi.registerForNotAvailable(mHandler, EVENT_RADIO_UNAVAILABLE, nsri);
                 return true;
             }
             return false;
@@ -584,6 +588,7 @@
                     }
                 }
                 mLiveRequestInfo.mPhone.mCi.unregisterForModemReset(mHandler);
+                mLiveRequestInfo.mPhone.mCi.unregisterForNotAvailable(mHandler);
                 mLiveRequestInfo = null;
                 if (mPendingRequestInfo != null) {
                     startNewScan(mPendingRequestInfo);
@@ -598,8 +603,8 @@
      *
      * This method is similar to stopNetworkScan, since they both stops an ongoing scan. The
      * difference is that stopNetworkScan is only used by the callers to stop their own scans, so
-     * sanity check will be done to make sure the request is valid; while this method is only
-     * internally used by NetworkScanRequestTracker so sanity check is not needed.
+     * correctness check will be done to make sure the request is valid; while this method is only
+     * internally used by NetworkScanRequestTracker so correctness check is not needed.
      */
     private void interruptNetworkScan(int scanId) {
         // scanId will be stored at Message.arg1
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 448c586..14b38da 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -23,7 +23,6 @@
 import android.os.AsyncResult;
 import android.os.Message;
 import android.os.PersistableBundle;
-import android.provider.Settings;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation;
 import android.telephony.CarrierConfigManager;
@@ -89,14 +88,14 @@
     private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10;
     private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11;
-    private static final int EVENT_INIITIALIZE = 12;
+    private static final int EVENT_INITIALIZE = 12;
     // events that don't reset the timer
     private static final int[] ALL_EVENTS = { EVENT_DATA_RAT_CHANGED, EVENT_NR_STATE_CHANGED,
             EVENT_NR_FREQUENCY_CHANGED, EVENT_PHYSICAL_LINK_STATE_CHANGED,
             EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, EVENT_PRIMARY_TIMER_EXPIRED,
             EVENT_SECONDARY_TIMER_EXPIRED};
 
-    private static final String[] sEvents = new String[EVENT_PREFERRED_NETWORK_MODE_CHANGED + 1];
+    private static final String[] sEvents = new String[EVENT_INITIALIZE + 1];
     static {
         sEvents[EVENT_UPDATE] = "EVENT_UPDATE";
         sEvents[EVENT_QUIT] = "EVENT_QUIT";
@@ -111,11 +110,11 @@
         sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED";
         sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE";
         sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED";
+        sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE";
     }
 
     private final Phone mPhone;
     private final DisplayInfoController mDisplayInfoController;
-    private final SettingsObserver mSettingsObserver;
     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -135,6 +134,7 @@
     private boolean mIsPhysicalChannelConfigOn;
     private boolean mIsPrimaryTimerActive;
     private boolean mIsSecondaryTimerActive;
+    private boolean mIsTimerResetEnabledForLegacyStateRRCIdle;
     private String mPrimaryTimerState;
     private String mSecondaryTimerState;
     private String mPreviousState;
@@ -150,7 +150,6 @@
         super(TAG, displayInfoController);
         mPhone = phone;
         mDisplayInfoController = displayInfoController;
-        mSettingsObserver = new SettingsObserver(mPhone.getContext(), getHandler());
         mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
         mIsPhysicalChannelConfigOn = true;
         addState(mDefaultState);
@@ -160,7 +159,7 @@
         addState(mNrConnectedState, mDefaultState);
         setInitialState(mDefaultState);
         start();
-        sendMessage(EVENT_INIITIALIZE);
+        sendMessage(EVENT_INITIALIZE);
     }
 
     /**
@@ -174,6 +173,8 @@
     private void registerForAllEvents() {
         mPhone.registerForRadioOffOrNotAvailable(getHandler(),
                 EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
+        mPhone.registerForPreferredNetworkTypeChanged(getHandler(),
+                EVENT_PREFERRED_NETWORK_MODE_CHANGED, null);
         mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler(),
                 EVENT_DATA_RAT_CHANGED, null);
@@ -189,19 +190,17 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
-        mSettingsObserver.observe(Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE),
-                EVENT_PREFERRED_NETWORK_MODE_CHANGED);
     }
 
     private void unRegisterForAllEvents() {
         mPhone.unregisterForRadioOffOrNotAvailable(getHandler());
+        mPhone.unregisterForPreferredNetworkTypeChanged(getHandler());
         mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(
                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler());
         mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler());
         mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler());
         mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler());
         mPhone.getContext().unregisterReceiver(mIntentReceiver);
-        mSettingsObserver.unobserve();
     }
 
     private void parseCarrierConfigs() {
@@ -213,6 +212,9 @@
                 CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING);
         mLteEnhancedPattern = CarrierConfigManager.getDefaultConfig().getString(
                 CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
+        mIsTimerResetEnabledForLegacyStateRRCIdle =
+                CarrierConfigManager.getDefaultConfig().getBoolean(
+                        CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL);
 
         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -238,6 +240,8 @@
                     mLteEnhancedPattern = b.getString(
                             CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
                 }
+                mIsTimerResetEnabledForLegacyStateRRCIdle = b.getBoolean(
+                        CarrierConfigManager.KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL);
             }
         }
         createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule);
@@ -440,7 +444,7 @@
                     unRegisterForAllEvents();
                     quit();
                     break;
-                case EVENT_INIITIALIZE:
+                case EVENT_INITIALIZE:
                     // The reason that we do it here is because some of the works below requires
                     // other modules (e.g. DcTracker, ServiceStateTracker), which is not created
                     // yet when NetworkTypeController is created.
@@ -540,6 +544,10 @@
                         transitionWithTimerTo(isPhysicalLinkActive()
                                 ? mLteConnectedState : mIdleState);
                     } else {
+                        if (!isLte(rat)) {
+                            // Rat is 3G or 2G, and it doesn't need NR timer.
+                            resetAllTimers();
+                        }
                         updateOverrideNetworkType();
                     }
                     mIsNrRestricted = isNrRestricted();
@@ -558,6 +566,14 @@
                 case EVENT_NR_FREQUENCY_CHANGED:
                     // ignored
                     break;
+                case EVENT_PHYSICAL_LINK_STATE_CHANGED:
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    mPhysicalLinkState = (int) ar.result;
+                    if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
+                        resetAllTimers();
+                        updateOverrideNetworkType();
+                    }
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -872,9 +888,18 @@
         if (currentState.equals(STATE_CONNECTED_MMWAVE)) {
             resetAllTimers();
         }
+
+        int rat = mPhone.getServiceState().getDataNetworkType();
+        if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) {
+            // Rat is 3G or 2G, and it doesn't need NR timer.
+            resetAllTimers();
+        }
     }
 
     private void resetAllTimers() {
+        if (DBG) {
+            log("Remove all timers");
+        }
         removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
         removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
         mIsPrimaryTimerActive = false;
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 9ae3abb..76811db 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -405,6 +405,8 @@
 
     private final RegistrantList mOtaspRegistrants = new RegistrantList();
 
+    private final RegistrantList mPreferredNetworkTypeRegistrants = new RegistrantList();
+
     protected Registrant mPostDialHandler;
 
     protected final LocalLog mLocalLog;
@@ -2249,6 +2251,7 @@
                 + " filteredType = " + filteredType);
 
         mCi.setPreferredNetworkType(filteredType, response);
+        mPreferredNetworkTypeRegistrants.notifyRegistrants();
     }
 
     /**
@@ -2261,6 +2264,27 @@
     }
 
     /**
+     * Register for preferred network type changes
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    public void registerForPreferredNetworkTypeChanged(Handler h, int what, Object obj) {
+        checkCorrectThread(h);
+        mPreferredNetworkTypeRegistrants.addUnique(h, what, obj);
+    }
+
+    /**
+     * Unregister for preferred network type changes.
+     *
+     * @param h Handler that should be unregistered.
+     */
+    public void unregisterForPreferredNetworkTypeChanged(Handler h) {
+        mPreferredNetworkTypeRegistrants.remove(h);
+    }
+
+    /**
      * Get the cached value of the preferred network type setting
      */
     public int getCachedPreferredNetworkType() {
@@ -2503,9 +2527,16 @@
 
     /** Send notification with an updated PreciseDataConnectionState to all data connections */
     public void notifyAllActiveDataConnections() {
-        String types[] = getActiveApnTypes();
-        for (String apnType : types) {
-            mNotifier.notifyDataConnection(this, apnType, getPreciseDataConnectionState(apnType));
+        if (mTransportManager != null) {
+            for (int transportType : mTransportManager.getAvailableTransports()) {
+                DcTracker dct = getDcTracker(transportType);
+                if (dct != null) {
+                    for (String apnType : dct.getConnectedApnTypes()) {
+                        mNotifier.notifyDataConnection(
+                                this, apnType, getPreciseDataConnectionState(apnType));
+                    }
+                }
+            }
         }
     }
 
@@ -4142,7 +4173,8 @@
     public boolean areAllDataDisconnected() {
         if (mTransportManager != null) {
             for (int transport : mTransportManager.getAvailableTransports()) {
-                if (getDcTracker(transport) != null && !getDcTracker(transport).isDisconnected()) {
+                if (getDcTracker(transport) != null
+                        && !getDcTracker(transport).areAllDataDisconnected()) {
                     return false;
                 }
             }
@@ -4154,7 +4186,8 @@
         mAllDataDisconnectedRegistrants.addUnique(h, what, null);
         if (mTransportManager != null) {
             for (int transport : mTransportManager.getAvailableTransports()) {
-                if (getDcTracker(transport) != null && !getDcTracker(transport).isDisconnected()) {
+                if (getDcTracker(transport) != null
+                        && !getDcTracker(transport).areAllDataDisconnected()) {
                     getDcTracker(transport).registerForAllDataDisconnected(
                             this, EVENT_ALL_DATA_DISCONNECTED);
                 }
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 4a2e7da..2476fcd 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -2835,7 +2835,7 @@
             }
         } else {
             // OEM Hook service is disabled for P and later devices.
-            // Deprecated OEM Hook APIs will perform dummy before being removed.
+            // Deprecated OEM Hook APIs will perform no-op before being removed.
             if (RILJ_LOGD) riljLog("Radio Oem Hook Service is disabled for P and later devices. ");
         }
     }
@@ -2864,7 +2864,7 @@
             }
         } else {
             // OEM Hook service is disabled for P and later devices.
-            // Deprecated OEM Hook APIs will perform dummy before being removed.
+            // Deprecated OEM Hook APIs will perform no-op before being removed.
             if (RILJ_LOGD) riljLog("Radio Oem Hook Service is disabled for P and later devices. ");
         }
     }
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index d30f95f..64d828b 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -577,16 +577,18 @@
      * @hide
      */
     public SubscriptionInfo getSubscriptionInfo(int subId) {
-        // check cache for active subscriptions first, before querying db
-        for (SubscriptionInfo subInfo : mCacheActiveSubInfoList) {
-            if (subInfo.getSubscriptionId() == subId) {
-                return subInfo;
+        synchronized (mSubInfoListLock) {
+            // check cache for active subscriptions first, before querying db
+            for (SubscriptionInfo subInfo : mCacheActiveSubInfoList) {
+                if (subInfo.getSubscriptionId() == subId) {
+                    return subInfo;
+                }
             }
-        }
-        // check cache for opportunistic subscriptions too, before querying db
-        for (SubscriptionInfo subInfo : mCacheOpportunisticSubInfoList) {
-            if (subInfo.getSubscriptionId() == subId) {
-                return subInfo;
+            // check cache for opportunistic subscriptions too, before querying db
+            for (SubscriptionInfo subInfo : mCacheOpportunisticSubInfoList) {
+                if (subInfo.getSubscriptionId() == subId) {
+                    return subInfo;
+                }
             }
         }
 
@@ -1364,12 +1366,14 @@
         // validate the given info - does it exist in the active subscription list
         int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         int slotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
-        for (SubscriptionInfo info : mCacheActiveSubInfoList) {
-            if ((info.getSubscriptionType() == subscriptionType)
-                    && info.getIccId().equalsIgnoreCase(uniqueId)) {
-                subId = info.getSubscriptionId();
-                slotIndex = info.getSimSlotIndex();
-                break;
+        synchronized (mSubInfoListLock) {
+            for (SubscriptionInfo info : mCacheActiveSubInfoList) {
+                if ((info.getSubscriptionType() == subscriptionType)
+                        && info.getIccId().equalsIgnoreCase(uniqueId)) {
+                    subId = info.getSubscriptionId();
+                    slotIndex = info.getSimSlotIndex();
+                    break;
+                }
             }
         }
         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
@@ -2608,11 +2612,13 @@
     }
 
     private boolean isSubscriptionVisible(int subId) {
-        for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
-            if (info.getSubscriptionId() == subId) {
-                // If group UUID is null, it's stand alone opportunistic profile. So it's visible.
-                // otherwise, it's bundled opportunistic profile, and is not visible.
-                return info.getGroupUuid() == null;
+        synchronized (mSubInfoListLock) {
+            for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
+                if (info.getSubscriptionId() == subId) {
+                    // If group UUID is null, it's stand alone opportunistic profile. So it's
+                    // visible. Otherwise, it's bundled opportunistic profile, and is not visible.
+                    return info.getGroupUuid() == null;
+                }
             }
         }
 
@@ -3898,9 +3904,11 @@
     private boolean shouldDisableSubGroup(ParcelUuid groupUuid) {
         if (groupUuid == null) return false;
 
-        for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) {
-            if (!activeInfo.isOpportunistic() && groupUuid.equals(activeInfo.getGroupUuid())) {
-                return false;
+        synchronized (mSubInfoListLock) {
+            for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) {
+                if (!activeInfo.isOpportunistic() && groupUuid.equals(activeInfo.getGroupUuid())) {
+                    return false;
+                }
             }
         }
 
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index bea9a00..8663961 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1575,7 +1575,7 @@
                 }
 
                 for (InetAddress gateway : response.getGatewayAddresses()) {
-                    int mtu = gateway instanceof java.net.Inet6Address ? response.getMtuV6() 
+                    int mtu = gateway instanceof java.net.Inet6Address ? response.getMtuV6()
                             : response.getMtuV4();
                     // Allow 0.0.0.0 or :: as a gateway;
                     // this indicates a point-to-point interface.
@@ -1877,10 +1877,8 @@
                             DataConnection.this, mTransportType);
                     NetworkInfo networkInfo = mHandoverSourceNetworkAgent.getNetworkInfo();
                     if (networkInfo != null) {
-                        networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
-                                "dangling clean up", networkInfo.getExtraInfo());
-                        mHandoverSourceNetworkAgent.sendNetworkInfo(networkInfo,
-                                DataConnection.this);
+                        log("Cleared dangling network agent. " + mHandoverSourceNetworkAgent);
+                        mHandoverSourceNetworkAgent.unregister(DataConnection.this);
                     } else {
                         String str = "Failed to get network info.";
                         loge(str);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnectionReasons.java b/src/java/com/android/internal/telephony/dataconnection/DataConnectionReasons.java
index 6aaadf5..5cfc599 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnectionReasons.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnectionReasons.java
@@ -113,7 +113,12 @@
         UNDESIRED_POWER_STATE(true),
         INTERNAL_DATA_DISABLED(true),
         RADIO_DISABLED_BY_CARRIER(true),
-        APN_NOT_CONNECTABLE(true),
+        APN_NOT_CONNECTABLE(true),  // Not in the right state for data call setup.
+        DATA_IS_CONNECTING(true),   // Data is in connecting state. No need to send another setup
+                                    // request.
+        DATA_IS_DISCONNECTING(true),    // Data is being disconnected. Telephony will retry after
+                                        // disconnected.
+        DATA_ALREADY_CONNECTED(true),   // Data is already connected. No need to setup data again.
         ON_IWLAN(true),
         IN_ECBM(true),
         ON_OTHER_TRANSPORT(true);   // When data retry occurs, the given APN type's preferred
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index 4bd59fb..da13ee4 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony.dataconnection;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.net.KeepalivePacketData;
 import android.net.LinkProperties;
 import android.net.NattKeepalivePacketData;
@@ -32,6 +33,7 @@
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.AnomalyReporter;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 import android.util.LocalLog;
 import android.util.SparseArray;
 
@@ -45,8 +47,8 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.UUID;
 
 /**
@@ -62,6 +64,8 @@
 public class DcNetworkAgent extends NetworkAgent {
     private final String mTag;
 
+    private final int mId;
+
     private Phone mPhone;
 
     private int mTransportType;
@@ -76,10 +80,8 @@
 
     private NetworkInfo mNetworkInfo;
 
-    // For debugging IMS redundant network agent issue.
-    private static List<DcNetworkAgent> sNetworkAgents = new ArrayList<>();
-
-    private static int sRedundantTimes = 0;
+    // For interface duplicate detection. Key is the net id, value is the interface name in string.
+    private static Map<Integer, String> sInterfaceNames = new ArrayMap<>();
 
     DcNetworkAgent(DataConnection dc, Phone phone, NetworkInfo ni, int score,
             NetworkAgentConfig config, NetworkProvider networkProvider, int transportType) {
@@ -87,7 +89,8 @@
                 dc.getNetworkCapabilities(), dc.getLinkProperties(), score, config,
                 networkProvider);
         register();
-        mTag = "DcNetworkAgent" + "-" + getNetwork().netId;
+        mId = getNetwork().netId;
+        mTag = "DcNetworkAgent" + "-" + mId;
         mPhone = phone;
         mNetworkCapabilities = dc.getNetworkCapabilities();
         mTransportType = transportType;
@@ -95,29 +98,30 @@
         mNetworkInfo = new NetworkInfo(ni);
         setLegacySubtype(ni.getSubtype(), ni.getSubtypeName());
         setLegacyExtraInfo(ni.getExtraInfo());
-        // TODO: Remove after b/151487565 is fixed.
-        sNetworkAgents.add(this);
-        checkRedundantIms();
-        logd(mTag + " created for data connection " + dc.getName());
+        if (dc.getLinkProperties() != null) {
+            checkDuplicateInterface(mId, dc.getLinkProperties().getInterfaceName());
+            logd("created for data connection " + dc.getName() + ", "
+                    + dc.getLinkProperties().getInterfaceName());
+        } else {
+            loge("The connection does not have a valid link properties.");
+        }
     }
 
-    // This is a temp code to catch the multiple IMS network agents issue.
-    // TODO: Remove after b/151487565 is fixed.
-    private void checkRedundantIms() {
-        if (sNetworkAgents.stream()
-                .filter(n -> n.mNetworkCapabilities.hasCapability(
-                        NetworkCapabilities.NET_CAPABILITY_IMS))
-                .count() > 1) {
-            sRedundantTimes++;
-            if (sRedundantTimes == 5) { // When it occurs 5 times.
-                String message = "Multiple IMS network agents detected.";
-                log(message);
+    private void checkDuplicateInterface(int netId, @Nullable String interfaceName) {
+        for (Map.Entry<Integer, String> entry: sInterfaceNames.entrySet()) {
+            if (Objects.equals(interfaceName, entry.getValue())) {
+                String message = "Duplicate interface " + interfaceName
+                        + " is detected. DcNetworkAgent-" + entry.getKey()
+                        + " already used this interface name.";
+                loge(message);
                 // Using fixed UUID to avoid duplicate bugreport notification
                 AnomalyReporter.reportAnomaly(
-                        UUID.fromString("a5cf4881-75ae-4129-a25d-71bc4293f493"),
+                        UUID.fromString("02f3d3f6-4613-4415-b6cb-8d92c8a938a6"),
                         message);
+                return;
             }
         }
+        sInterfaceNames.put(netId, interfaceName);
     }
 
     /**
@@ -148,7 +152,7 @@
             loge("releaseOwnership called on no-owner DcNetworkAgent!");
             return;
         } else if (mDataConnection != dc) {
-            log("releaseOwnership: This agent belongs to "
+            loge("releaseOwnership: This agent belongs to "
                     + mDataConnection.getName() + ", ignored the request from " + dc.getName());
             return;
         }
@@ -257,9 +261,11 @@
      * @param linkProperties The link properties
      * @param dc The data connection that invokes this method.
      */
-    public synchronized void sendLinkProperties(LinkProperties linkProperties,
+    public synchronized void sendLinkProperties(@NonNull LinkProperties linkProperties,
                                                 DataConnection dc) {
         if (!isOwned(dc, "sendLinkProperties")) return;
+
+        sInterfaceNames.put(mId, dc.getLinkProperties().getInterfaceName());
         sendLinkProperties(linkProperties);
     }
 
@@ -275,6 +281,19 @@
     }
 
     /**
+     * Unregister the network agent from connectivity service.
+     *
+     * @param dc The data connection that invokes this method.
+     */
+    public synchronized void unregister(DataConnection dc) {
+        if (!isOwned(dc, "unregister")) return;
+
+        logd("Unregister from connectivity service. " + sInterfaceNames.get(mId) + " removed.");
+        sInterfaceNames.remove(mId);
+        super.unregister();
+    }
+
+    /**
      * Set the network info.
      *
      * @param networkInfo The network info.
@@ -293,9 +312,7 @@
         }
         if ((oldState == NetworkInfo.State.SUSPENDED || oldState == NetworkInfo.State.CONNECTED)
                 && state == NetworkInfo.State.DISCONNECTED) {
-            logd("Unregister from connectivity service");
-            sNetworkAgents.remove(this);
-            unregister();
+            unregister(dc);
         }
         mNetworkInfo = new NetworkInfo(networkInfo);
     }
@@ -338,11 +355,13 @@
 
     @Override
     public String toString() {
-        return "DcNetworkAgent:"
+        return "DcNetworkAgent-"
+                + mId
                 + " mDataConnection="
                 + ((mDataConnection != null) ? mDataConnection.getName() : null)
                 + " mTransportType="
                 + AccessNetworkConstants.transportTypeToString(mTransportType)
+                + " " + ((mDataConnection != null) ? mDataConnection.getLinkProperties() : null)
                 + " mNetworkCapabilities=" + mNetworkCapabilities;
     }
 
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 06e3dde..2f1f871 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -1091,6 +1091,18 @@
         return result.toArray(new String[0]);
     }
 
+    /**
+     * Get ApnTypes with connected data connections.  This is different than getActiveApnTypes()
+     * which returns apn types that with active apn contexts.
+     * @return apn types
+     */
+    public String[] getConnectedApnTypes() {
+        return mApnContexts.values().stream()
+                .filter(ac -> ac.getState() == DctConstants.State.CONNECTED)
+                .map(ApnContext::getApnType)
+                .toArray(String[]::new);
+    }
+
     @VisibleForTesting
     public Collection<ApnContext> getApnContexts() {
         return mPrioritySortedApnContexts;
@@ -1202,52 +1214,6 @@
         return false;
     }
 
-    // Return state of overall
-    public DctConstants.State getOverallState() {
-        boolean isConnecting = false;
-        boolean isFailed = true; // All enabled Apns should be FAILED.
-        boolean isAnyEnabled = false;
-
-        for (ApnContext apnContext : mApnContexts.values()) {
-            if (apnContext.isEnabled()) {
-                isAnyEnabled = true;
-                switch (apnContext.getState()) {
-                    case CONNECTED:
-                    case DISCONNECTING:
-                        if (VDBG) log("overall state is CONNECTED");
-                        return DctConstants.State.CONNECTED;
-                    case CONNECTING:
-                        isConnecting = true;
-                        isFailed = false;
-                        break;
-                    case IDLE:
-                    case RETRYING:
-                        isFailed = false;
-                        break;
-                    default:
-                        isAnyEnabled = true;
-                        break;
-                }
-            }
-        }
-
-        if (!isAnyEnabled) { // Nothing enabled. return IDLE.
-            if (VDBG) log( "overall state is IDLE");
-            return DctConstants.State.IDLE;
-        }
-
-        if (isConnecting) {
-            if (VDBG) log( "overall state is CONNECTING");
-            return DctConstants.State.CONNECTING;
-        } else if (!isFailed) {
-            if (VDBG) log( "overall state is IDLE");
-            return DctConstants.State.IDLE;
-        } else {
-            if (VDBG) log( "overall state is FAILED");
-            return DctConstants.State.FAILED;
-        }
-    }
-
     //****** Called from ServiceStateTracker
     /**
      * Invoked when ServiceStateTracker observes a transition from GPRS
@@ -1268,7 +1234,7 @@
     private void onDataConnectionAttached() {
         if (DBG) log("onDataConnectionAttached");
         mAttached.set(true);
-        if (getOverallState() == DctConstants.State.CONNECTED) {
+        if (isAnyDataConnected()) {
             if (DBG) log("onDataConnectionAttached: start polling notify attached");
             startNetStatPoll();
             startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
@@ -1363,7 +1329,16 @@
 
         // Step 3. Build disallowed reasons.
         if (apnContext != null && !apnContext.isConnectable()) {
-            reasons.add(DataDisallowedReasonType.APN_NOT_CONNECTABLE);
+            DctConstants.State state = apnContext.getState();
+            if (state == DctConstants.State.CONNECTED) {
+                reasons.add(DataDisallowedReasonType.DATA_ALREADY_CONNECTED);
+            } else if (state == DctConstants.State.DISCONNECTING) {
+                reasons.add(DataDisallowedReasonType.DATA_IS_DISCONNECTING);
+            } else if (state == DctConstants.State.CONNECTING) {
+                reasons.add(DataDisallowedReasonType.DATA_IS_CONNECTING);
+            } else {
+                reasons.add(DataDisallowedReasonType.APN_NOT_CONNECTABLE);
+            }
         }
 
         // In legacy mode, if RAT is IWLAN then don't allow default/IA PDP at all.
@@ -1816,6 +1791,19 @@
         ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
         ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>();
 
+        if (mPhone.getServiceState().getRoaming()) {
+            CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
+                    .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            if (configManager != null) {
+                PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
+                if (b != null) {
+                    if (b.getBoolean(CarrierConfigManager.KEY_DISABLE_DUN_APN_WHILE_ROAMING)) {
+                        return new ArrayList<>();
+                    }
+                }
+            }
+        }
+
         // Places to look for tether APN in order: TETHER_DUN_APN setting (to be deprecated soon),
         // APN database
         String apnData = Settings.Global.getString(mResolver, Settings.Global.TETHER_DUN_APN);
@@ -2127,10 +2115,6 @@
      * Handles changes to the APN database.
      */
     private void onApnChanged() {
-        DctConstants.State overallState = getOverallState();
-        boolean isDisconnected = (overallState == DctConstants.State.IDLE ||
-                overallState == DctConstants.State.FAILED);
-
         if (mPhone instanceof GsmCdmaPhone) {
             // The "current" may no longer be valid.  MMS depends on this to send properly. TBD
             ((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider();
@@ -2142,7 +2126,7 @@
         createAllApnList();
         setDataProfilesAsNeeded();
         setInitialAttachApn();
-        cleanUpConnectionsOnUpdatedApns(!isDisconnected, Phone.REASON_APN_CHANGED);
+        cleanUpConnectionsOnUpdatedApns(isAnyDataConnected(), Phone.REASON_APN_CHANGED);
 
         // FIXME: See bug 17426028 maybe no conditional is needed.
         if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
@@ -2742,7 +2726,7 @@
             log("onRadioAvailable: We're on the simulator; assuming data is connected");
         }
 
-        if (getOverallState() != DctConstants.State.IDLE) {
+        if (!areAllDataDisconnected()) {
             cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, null);
         }
     }
@@ -3046,7 +3030,7 @@
         }
         // if all data connection are gone, check whether Airplane mode request was
         // pending.
-        if (isDisconnected()) {
+        if (areAllDataDisconnected()) {
             if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
                 if (DBG) log("onDisconnectDone: radio will be turned off, no retries");
                 // Radio will be turned off. No need to retry data setup
@@ -3110,7 +3094,8 @@
     private void onVoiceCallStarted() {
         if (DBG) log("onVoiceCallStarted");
         mInVoiceCall = true;
-        if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
+        if (isAnyDataConnected()
+                && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
             if (DBG) log("onVoiceCallStarted stop polling");
             stopNetStatPoll();
             stopDataStallAlarm();
@@ -3121,7 +3106,7 @@
     protected void onVoiceCallEnded() {
         if (DBG) log("onVoiceCallEnded");
         mInVoiceCall = false;
-        if (isConnected()) {
+        if (isAnyDataConnected()) {
             if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
                 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
@@ -3134,26 +3119,28 @@
         // reset reconnect timer
         setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);
     }
-
-    protected boolean isConnected() {
-        for (ApnContext apnContext : mApnContexts.values()) {
-            if (apnContext.getState() == DctConstants.State.CONNECTED) {
-                // At least one context is connected, return true
+    /**
+     * @return {@code true} if there is any data in connected state.
+     */
+    @VisibleForTesting
+    public boolean isAnyDataConnected() {
+        for (DataConnection dc : mDataConnections.values()) {
+            if (dc.isActive()) {
                 return true;
             }
         }
-        // There are not any contexts connected, return false
         return false;
     }
 
-    public boolean isDisconnected() {
-        for (ApnContext apnContext : mApnContexts.values()) {
-            if (!apnContext.isDisconnected()) {
-                // At least one context was not disconnected return false
+    /**
+     * @return {@code true} if all data connections are in disconnected state.
+     */
+    public boolean areAllDataDisconnected() {
+        for (DataConnection dc : mDataConnections.values()) {
+            if (!dc.isInactive()) {
                 return false;
             }
         }
-        // All contexts were disconnected so return true
         return true;
     }
 
@@ -3557,7 +3544,7 @@
                  */
                 if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
                 mIsPsRestricted  = false;
-                if (isConnected()) {
+                if (isAnyDataConnected()) {
                     startNetStatPoll();
                     startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
                 } else {
@@ -3740,7 +3727,7 @@
 
                     mDataStallNoRxEnabled = !enabled;
                     if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled()
-                            && (getOverallState() == DctConstants.State.CONNECTED)
+                            && isAnyDataConnected()
                             && (!mInVoiceCall ||
                                     mPhone.getServiceStateTracker()
                                         .isConcurrentVoiceAndDataAllowed())) {
@@ -3991,7 +3978,7 @@
     public void registerForAllDataDisconnected(Handler h, int what) {
         mAllDataDisconnectedRegistrants.addUnique(h, what, null);
 
-        if (isDisconnected()) {
+        if (areAllDataDisconnected()) {
             log("notify All Data Disconnected");
             notifyAllDataDisconnected();
         }
@@ -4248,7 +4235,7 @@
         pw.println(" mReregisterOnReconnectFailure=" + mReregisterOnReconnectFailure);
         pw.println(" canSetPreferApn=" + mCanSetPreferApn);
         pw.println(" mApnObserver=" + mApnObserver);
-        pw.println(" getOverallState=" + getOverallState());
+        pw.println(" isAnyDataConnected=" + isAnyDataConnected());
         pw.println(" mAttached=" + mAttached.get());
         mDataEnabledSettings.dump(fd, pw, args);
         pw.flush();
@@ -4408,7 +4395,7 @@
             }
         }
 
-        if (!isConnected()) {
+        if (!isAnyDataConnected()) {
             stopNetStatPoll();
             stopDataStallAlarm();
         }
@@ -4431,8 +4418,7 @@
     }
 
     protected void startNetStatPoll() {
-        if (getOverallState() == DctConstants.State.CONNECTED
-                && mNetStatPollEnabled == false) {
+        if (isAnyDataConnected() && !mNetStatPollEnabled) {
             if (DBG) {
                 log("startNetStatPoll");
             }
@@ -4710,7 +4696,7 @@
         }
 
         public void doRecovery() {
-            if (getOverallState() == DctConstants.State.CONNECTED) {
+            if (isAnyDataConnected()) {
                 // Go through a series of recovery steps, each action transitions to the next action
                 @RecoveryAction final int recoveryAction = getRecoveryAction();
                 final int signalStrength = mPhone.getSignalStrength().getLevel();
@@ -4874,8 +4860,7 @@
     protected void startDataStallAlarm(boolean suspectedStall) {
         int delayInMs;
 
-        if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled()
-                && getOverallState() == DctConstants.State.CONNECTED) {
+        if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled() && isAnyDataConnected()) {
             // If screen is on or data stall is currently suspected, set the alarm
             // with an aggressive timeout.
             if (mIsScreenOn || suspectedStall || mDsRecoveryHandler.isAggressiveRecovery()) {
@@ -4921,7 +4906,7 @@
     }
 
     private void restartDataStallAlarm() {
-        if (isConnected() == false) return;
+        if (!isAnyDataConnected()) return;
         // To be called on screen status change.
         // Do not cancel the alarm if it is set with aggressive timeout.
         if (mDsRecoveryHandler.isAggressiveRecovery()) {
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 8cfde1f..3b55008 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -59,7 +59,6 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
@@ -80,7 +79,9 @@
     private static final String EMERGENCY_NUMBER_DB_OTA_FILE_NAME = "emergency_number_db";
     private static final String EMERGENCY_NUMBER_DB_OTA_FILE_PATH =
             "misc/emergencynumberdb/" + EMERGENCY_NUMBER_DB_OTA_FILE_NAME;
-    private FileInputStream mEmergencyNumberDbOtaFileInputStream = null;
+
+    /** Used for storing overrided (non-default) OTA database file path */
+    private ParcelFileDescriptor mOverridedOtaDbParcelFileDescriptor = null;
 
     /** @hide */
     public static boolean DBG = false;
@@ -170,13 +171,6 @@
         mPhone = phone;
         mCi = ci;
 
-        try {
-            mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
-                    new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
-        } catch (FileNotFoundException ex) {
-            loge("Initialize ota emergency database file input failure: " + ex);
-        }
-
         if (mPhone != null) {
             CarrierConfigManager configMgr = (CarrierConfigManager)
                     mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -488,6 +482,7 @@
     }
 
     private int cacheOtaEmergencyNumberDatabase() {
+        FileInputStream fileInputStream = null;
         BufferedInputStream inputStream = null;
         ProtobufEccData.AllInfo allEccMessages = null;
         int otaDatabaseVersion = INVALID_DATABASE_VERSION;
@@ -496,11 +491,16 @@
         List<EmergencyNumber> updatedOtaEmergencyNumberList = new ArrayList<>();
         try {
             // If OTA File partition is not available, try to reload the default one.
-            if (mEmergencyNumberDbOtaFileInputStream == null) {
-                mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
-                      new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
+            if (mOverridedOtaDbParcelFileDescriptor == null) {
+                fileInputStream = new FileInputStream(
+                        new File(Environment.getDataDirectory(),
+                                EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
+            } else {
+                File file = ParcelFileDescriptor
+                        .getFile(mOverridedOtaDbParcelFileDescriptor.getFileDescriptor());
+                fileInputStream = new FileInputStream(new File(file.getAbsolutePath()));
             }
-            inputStream = new BufferedInputStream(mEmergencyNumberDbOtaFileInputStream);
+            inputStream = new BufferedInputStream(fileInputStream);
             allEccMessages = ProtobufEccData.AllInfo.parseFrom(readInputStreamToByteArray(
                     new GZIPInputStream(inputStream)));
             logd(mCountryIso + " ota emergency database is loaded. Ver: " + otaDatabaseVersion);
@@ -517,7 +517,7 @@
         } catch (IOException ex) {
             loge("Cache ota emergency database IOException: " + ex);
         } finally {
-            // close quietly by catching non-runtime exceptions.
+            // Close quietly by catching non-runtime exceptions.
             if (inputStream != null) {
                 try {
                     inputStream.close();
@@ -526,6 +526,14 @@
                 } catch (Exception ignored) {
                 }
             }
+            if (fileInputStream != null) {
+                try {
+                    fileInputStream.close();
+                } catch (RuntimeException rethrown) {
+                    throw rethrown;
+                } catch (Exception ignored) {
+                }
+            }
         }
 
         // Use a valid database that has higher version.
@@ -606,17 +614,7 @@
     private void overrideOtaEmergencyNumberDbFilePath(
             ParcelFileDescriptor otaParcelableFileDescriptor) {
         logd("overrideOtaEmergencyNumberDbFilePath:" + otaParcelableFileDescriptor);
-        try {
-            if (otaParcelableFileDescriptor == null) {
-                mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
-                    new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
-            } else {
-                mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
-                    otaParcelableFileDescriptor.getFileDescriptor());
-            }
-        } catch (FileNotFoundException ex) {
-            loge("Override ota emergency database failure: " + ex);
-        }
+        mOverridedOtaDbParcelFileDescriptor = otaParcelableFileDescriptor;
     }
 
     private void updateOtaEmergencyNumberListDatabaseAndNotify() {
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index ff7c087..a0ede7f 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -335,10 +335,10 @@
                     "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to check if the country is supported");
         }
         if (mSupportedCountries == null || mSupportedCountries.isEmpty()) {
-            Log.i(TAG, "Using blacklist unsupportedCountries=" + mUnsupportedCountries);
+            Log.i(TAG, "Using deny list unsupportedCountries=" + mUnsupportedCountries);
             return !isEsimUnsupportedCountry(countryIso);
         } else {
-            Log.i(TAG, "Using whitelist supportedCountries=" + mSupportedCountries);
+            Log.i(TAG, "Using allow list supportedCountries=" + mSupportedCountries);
             return isEsimSupportedCountry(countryIso);
         }
     }
diff --git a/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index f6fc069..b7c69b1 100755
--- a/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/src/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -287,12 +287,12 @@
     private void buildType1EmailList(int recId) {
         /**
          * If this is type 1, the number of records in EF_EMAIL would be same as the record number
-         * in the master/reference file.
+         * in the main/reference file.
          */
         if (mPbrRecords.get(recId) == null)
             return;
 
-        int numRecs = mPbrRecords.get(recId).mMasterFileRecordNum;
+        int numRecs = mPbrRecords.get(recId).mMainFileRecordNum;
         log("Building type 1 email list. recId = "
                 + recId + ", numRecs = " + numRecs);
 
@@ -359,15 +359,15 @@
         if (mPbrRecords.get(recId) == null)
             return false;
 
-        int numRecs = mPbrRecords.get(recId).mMasterFileRecordNum;
+        int numRecs = mPbrRecords.get(recId).mMainFileRecordNum;
         log("Building type 2 email list. recId = "
                 + recId + ", numRecs = " + numRecs);
 
         /**
          * 3GPP TS 31.102 4.4.2.1 EF_PBR (Phone Book Reference file) table 4.1
 
-         * The number of records in the IAP file is same as the number of records in the master
-         * file (e.g EF_ADN). The order of the pointers in an EF_IAP shall be the same as the
+         * The number of records in the IAP file is same as the number of records in the EF_ADN
+         * file. The order of the pointers in an EF_IAP shall be the same as the
          * order of file IDs that appear in the TLV object indicated by Tag 'A9' in the
          * reference file record (e.g value of mEmailTagNumberInIap)
          */
@@ -492,7 +492,7 @@
          * The recent added ADN record # would be the reference record size
          * for the rest of EFs associated within this PBR.
          */
-        mPbrRecords.get(recId).mMasterFileRecordNum = mPhoneBookRecords.size() - previousSize;
+        mPbrRecords.get(recId).mMainFileRecordNum = mPhoneBookRecords.size() - previousSize;
     }
 
     // Create the phonebook reference file based on EF_PBR
@@ -581,10 +581,10 @@
         /**
          * 3GPP TS 31.102 4.4.2.1 EF_PBR (Phone Book Reference file)
          * If this is type 1 files, files that contain as many records as the
-         * reference/master file (EF_ADN, EF_ADN1) and are linked on record number
-         * bases (Rec1 -> Rec1). The master file record number is the reference.
+         * reference/main file (EF_ADN, EF_ADN1) and are linked on record number
+         * bases (Rec1 -> Rec1). The EF_ADN/EF_ADN1 file record number is the reference.
          */
-        private int mMasterFileRecordNum;
+        private int mMainFileRecordNum;
 
         PbrRecord(byte[] record) {
             mFileIds = new SparseArray<File>();
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index 2d293a1..fdd97eb 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -98,7 +98,7 @@
     public static final String METADATA_MMTEL_FEATURE = "android.telephony.ims.MMTEL_FEATURE";
     @VisibleForTesting
     public static final String METADATA_RCS_FEATURE = "android.telephony.ims.RCS_FEATURE";
-    // Overrides the sanity permission check of android.permission.BIND_IMS_SERVICE for any
+    // Overrides the correctness permission check of android.permission.BIND_IMS_SERVICE for any
     // ImsService that is connecting to the platform.
     // This should ONLY be used for testing and should not be used in production ImsServices.
     private static final String METADATA_OVERRIDE_PERM_CHECK = "override_bind_check";
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 4047511..0e54e86 100755
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -2783,6 +2783,17 @@
                 }
                 mMetrics.writeOnImsCallStartFailed(mPhone.getPhoneId(), imsCall.getCallSession(),
                         reasonInfo);
+            } else if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
+                    && mForegroundCall.getState() == ImsPhoneCall.State.ALERTING) {
+                if (DBG) log("onCallStartFailed: Initiated call by silent redial"
+                        + " under ALERTING state.");
+                ImsPhoneConnection conn = findConnection(imsCall);
+                if (conn != null) {
+                    mForegroundCall.detach(conn);
+                    removeConnection(conn);
+                }
+                updatePhoneState();
+                mPhone.initiateSilentRedial();
             }
         }
 
diff --git a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
index ceeed34..51d0126 100644
--- a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
@@ -675,7 +675,7 @@
 
     /**
      * Returns the root path of the EF file.
-     * i.e returns MasterFile + DFfile as a string.
+     * i.e returns MainFile + DFfile as a string.
      * Ex: For EF_ADN on a SIM, it will return "3F007F10"
      * This function handles only EFids that are common to
      * RUIM, SIM, USIM and other types of Icc cards.
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index db88025..d566b45 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -311,7 +311,7 @@
 
                 mIccLockEnabled = (ints[0] != 0);
 
-                // Sanity check: we expect mPin1State to match mIccLockEnabled.
+                // Correctness check: we expect mPin1State to match mIccLockEnabled.
                 // When mPin1State is DISABLED mIccLockEanbled should be false.
                 // When mPin1State is ENABLED mIccLockEnabled should be true.
                 //
@@ -522,7 +522,7 @@
                     mPin1State == PinState.PINSTATE_ENABLED_BLOCKED ||
                     mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
                 loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!");
-                // Don't notify if application is in insane state
+                // Don't notify if application is in an invalid state
                 return;
             }
             if (r == null) {
@@ -570,7 +570,7 @@
             if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED ||
                     mPin1State == PinState.PINSTATE_DISABLED) {
                 loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!");
-                //Don't notify if application is in insane state
+                //Don't notify if application is in an invalid state
                 return;
             }
             if (r == null) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
index e1bc0b7..f99a4a1 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
@@ -111,9 +111,9 @@
     private static final int STATE_LOADED   = 1;
     private static final int STATE_ERROR    = 2;
 
-    // Max number of retries for open logical channel, interval is 10s.
-    private static final int MAX_RETRY = 1;
-    private static final int RETRY_INTERVAL_MS = 10000;
+    // Max number of retries for open logical channel, interval is 5s.
+    private static final int MAX_RETRY = 2;
+    private static final int RETRY_INTERVAL_MS = 5000;
     private static final int STATUS_CODE_CONDITION_NOT_SATISFIED = 0x6985;
     private static final int STATUS_CODE_APPLET_SELECT_FAILED = 0x6999;
 
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 235bf43..3a76a1b 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -943,7 +943,7 @@
             if (isActive) {
                 numActiveSlots++;
 
-                // sanity check: logicalSlotIndex should be valid for an active slot
+                // Correctness check: logicalSlotIndex should be valid for an active slot
                 if (!isValidPhoneIndex(iss.logicalSlotIndex)) {
                     Rlog.e(LOG_TAG, "Skipping slot " + i + " as phone " + iss.logicalSlotIndex
                                + " is not available to communicate with this slot");
@@ -1052,13 +1052,13 @@
 
         if (VDBG) logPhoneIdToSlotIdMapping();
 
-        // sanity check: number of active slots should be valid
+        // Correctness check: number of active slots should be valid
         if (numActiveSlots != mPhoneIdToSlotId.length) {
             Rlog.e(LOG_TAG, "Number of active slots " + numActiveSlots
                        + " does not match the number of Phones" + mPhoneIdToSlotId.length);
         }
 
-        // sanity check: slotIds should be unique in mPhoneIdToSlotId
+        // Correctness check: slotIds should be unique in mPhoneIdToSlotId
         Set<Integer> slotIds = new HashSet<>();
         for (int slotId : mPhoneIdToSlotId) {
             if (slotIds.contains(slotId)) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 5feeec1..8eb2608 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -134,7 +134,8 @@
 
     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
 
-    private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
+    @VisibleForTesting
+    public int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
     private UiccCardApplication mUiccApplication = null;
     private IccRecords mIccRecords = null;
     private IccCardConstants.State mExternalState = IccCardConstants.State.UNKNOWN;
@@ -352,7 +353,7 @@
                 mCurrentAppType = UiccController.APP_FAM_3GPP;
             } else {
                 UiccCardApplication newApp = getApplication(UiccController.APP_FAM_3GPP2);
-                if(newApp != null) {
+                if (newApp != null || getApplication(UiccController.APP_FAM_3GPP) == null) {
                     mCurrentAppType = UiccController.APP_FAM_3GPP2;
                 } else {
                     mCurrentAppType = UiccController.APP_FAM_3GPP;
@@ -1319,13 +1320,13 @@
     }
 
     private Set<String> getUninstalledCarrierPackages() {
-        String whitelistSetting = Settings.Global.getString(
+        String allowListSetting = Settings.Global.getString(
                 mContext.getContentResolver(),
                 Settings.Global.CARRIER_APP_WHITELIST);
-        if (TextUtils.isEmpty(whitelistSetting)) {
+        if (TextUtils.isEmpty(allowListSetting)) {
             return Collections.emptySet();
         }
-        Map<String, String> certPackageMap = parseToCertificateToPackageMap(whitelistSetting);
+        Map<String, String> certPackageMap = parseToCertificateToPackageMap(allowListSetting);
         if (certPackageMap.isEmpty()) {
             return Collections.emptySet();
         }
@@ -1350,11 +1351,11 @@
      * @hide
      */
     @VisibleForTesting
-    public static Map<String, String> parseToCertificateToPackageMap(String whitelistSetting) {
+    public static Map<String, String> parseToCertificateToPackageMap(String allowListSetting) {
         final String pairDelim = "\\s*;\\s*";
         final String keyValueDelim = "\\s*:\\s*";
 
-        List<String> keyValuePairList = Arrays.asList(whitelistSetting.split(pairDelim));
+        List<String> keyValuePairList = Arrays.asList(allowListSetting.split(pairDelim));
 
         if (keyValuePairList.isEmpty()) {
             return Collections.emptyMap();
@@ -1367,7 +1368,7 @@
             if (keyValue.length == 2) {
                 map.put(keyValue[0].toUpperCase(), keyValue[1]);
             } else {
-                loge("Incorrect length of key-value pair in carrier app whitelist map.  "
+                loge("Incorrect length of key-value pair in carrier app allow list map.  "
                         + "Length should be exactly 2");
             }
         }
diff --git a/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java b/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java
index 2e256ff..1acd593 100644
--- a/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java
+++ b/src/java/com/android/internal/telephony/vendor/dataconnection/VendorDcTracker.java
@@ -17,32 +17,17 @@
 package com.android.internal.telephony.vendor.dataconnection;
 
 import android.app.AlertDialog;
-import android.view.WindowManager;
-
 import android.telephony.AccessNetworkConstants;
-import android.telephony.Annotation.DataFailureCause;
-import android.telephony.CarrierConfigManager;
 import android.telephony.DataFailCause;
-import android.telephony.data.ApnSetting;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
+import android.view.WindowManager;
 
+import com.android.internal.telephony.DctConstants;
+import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.dataconnection.ApnContext;
 import com.android.internal.telephony.dataconnection.DcTracker;
-import com.android.internal.telephony.DctConstants;
-import com.android.internal.telephony.GsmCdmaPhone;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.uicc.IccRecords;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.AsyncChannel;
-
-import android.database.Cursor;
-import android.content.Context;
-import android.os.PersistableBundle;
-import android.provider.Telephony;
 
 import java.util.HashSet;
 import java.util.Iterator;
@@ -115,7 +100,7 @@
     protected void onVoiceCallEnded() {
         if (DBG) log("onVoiceCallEnded");
         mInVoiceCall = false;
-        if (isConnected()) {
+        if (isAnyDataConnected()) {
             if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
                 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/BarringInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/BarringInfoTest.java
index 6720b41..7718774 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/BarringInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/BarringInfoTest.java
@@ -49,12 +49,12 @@
             BarringInfo.BARRING_SERVICE_TYPE_SMS,
     };
 
-    /** Return a dummy set of barring info */
+    /** Return a placeholder set of barring info */
     private static SparseArray<BarringServiceInfo> getBarringServiceInfos() {
         return getBarringServiceInfos(false);
     }
 
-    /** Return a dummy set of barring info
+    /** Return a placeholder set of barring info
      *
      * @param isConditionallyBarred set the flag for whether the conditionally barred service has
      *        been evaluated and is actually barred based on the conditional barring parameters.
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index a301c00..f827055 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -1107,7 +1107,7 @@
     @Test
     @SmallTest
     public void testGetIccCardUnknownAndAbsent() {
-        // If UiccSlot.isStateUnknown is true, we should return a dummy IccCard with the state
+        // If UiccSlot.isStateUnknown is true, we should return a placeholder IccCard with the state
         // set to UNKNOWN
         doReturn(null).when(mUiccController).getUiccProfileForPhone(anyInt());
         UiccSlot mockSlot = mock(UiccSlot.class);
@@ -1117,7 +1117,7 @@
         IccCard iccCard = mPhoneUT.getIccCard();
         assertEquals(IccCardConstants.State.UNKNOWN, iccCard.getState());
 
-        // if isStateUnknown is false, we should return a dummy IccCard with the state set to
+        // if isStateUnknown is false, we should return a placeholder IccCard with the state set to
         // ABSENT
         doReturn(false).when(mockSlot).isStateUnknown();
         iccCard = mPhoneUT.getIccCard();
@@ -1131,7 +1131,7 @@
 
         IccCard iccCard = mPhoneUT.getIccCard();
 
-        // The iccCard should be a dummy object, not null.
+        // The iccCard should be a placeholder object, not null.
         assertTrue(!(iccCard instanceof UiccProfile));
 
         assertTrue(iccCard != null);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
index a6fb620..ee75826 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
@@ -40,7 +40,7 @@
     private static final int ALL_FLAGS_SET = FLAG_START_UPDATE_CALLED | FLAG_ADD_RANGE_CALLED |
             FLAG_FINISH_UPDATE_CALLED;
 
-    /** Dummy IntRangeManager for testing. */
+    /** IntRangeManager for testing. */
     class TestIntRangeManager extends IntRangeManager {
         ArrayList<SmsBroadcastConfigInfo> mConfigList =
                 new ArrayList<SmsBroadcastConfigInfo>();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 95ec5cd..001ba39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -57,6 +57,7 @@
     private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10;
     private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11;
+    private static final int EVENT_INITIALIZE = 12;
 
     private NetworkTypeController mNetworkTypeController;
     private PersistableBundle mBundle;
@@ -348,6 +349,7 @@
 
     @Test
     public void testPrimaryTimerExpire() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
                 "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
@@ -377,6 +379,7 @@
 
     @Test
     public void testPrimaryTimerReset() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
                 "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
@@ -411,6 +414,7 @@
 
     @Test
     public void testPrimaryTimerExpireMmwave() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
@@ -442,6 +446,7 @@
 
     @Test
     public void testPrimaryTimerResetMmwave() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
@@ -477,6 +482,7 @@
 
     @Test
     public void testSecondaryTimerExpire() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
                 "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
@@ -517,6 +523,7 @@
 
     @Test
     public void testSecondaryTimerReset() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
                 "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
@@ -562,6 +569,7 @@
 
     @Test
     public void testSecondaryTimerExpireMmwave() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
@@ -603,6 +611,7 @@
 
     @Test
     public void testSecondaryTimerResetMmwave() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
@@ -646,4 +655,39 @@
         assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
                 mNetworkTypeController.getOverrideNetworkType());
     }
+
+    @Test
+    public void testNrTimerResetIn3g() throws Exception {
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+        doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+        doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+        mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+                "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+        mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+                "connected_mmwave,any,30");
+        broadcastCarrierConfigs();
+
+        assertEquals("connected_mmwave", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+                mNetworkTypeController.getOverrideNetworkType());
+
+        // should trigger 10 second primary timer
+        doReturn(ServiceState.FREQUENCY_RANGE_LOW).when(mServiceState).getNrFrequencyRange();
+        mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+        processAllMessages();
+
+        assertEquals("connected", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
+                mNetworkTypeController.getOverrideNetworkType());
+
+        // rat is UMTS, should stop timer
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mServiceState).getDataNetworkType();
+        doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+        mNetworkTypeController.sendMessage(EVENT_DATA_RAT_CHANGED);
+        processAllMessages();
+
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+                mNetworkTypeController.getOverrideNetworkType());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index 72bc43f..54549fb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doReturn;
@@ -60,7 +59,7 @@
         doReturn(true).when(mSubscriptionController).isActiveSubId(0, TAG, FEATURE_ID);
         doReturn(true).when(mSubscriptionController).isActiveSubId(1, TAG, FEATURE_ID);
         doReturn(new int[]{0, 1}).when(mSubscriptionManager)
-                .getActiveSubscriptionIdList(anyBoolean());
+                .getCompleteActiveSubscriptionIdList();
 
         mServiceManagerMockedServices.put("isub", mSubscriptionController);
         doReturn(mSubscriptionController).when(mSubscriptionController)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 1ab990e..86201cd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -229,7 +229,7 @@
         doReturn(mIwlanNetworkServiceStub).when(mIwlanNetworkServiceStub).asBinder();
         addNetworkService();
 
-        doReturn(true).when(mDcTracker).isDisconnected();
+        doReturn(true).when(mDcTracker).areAllDataDisconnected();
 
         doReturn(new ServiceState()).when(mPhone).getServiceState();
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index 0673b51..f61c6ea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -105,8 +104,8 @@
                 mMockSubscriptionManager);
         when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
                 mMockDevicePolicyManager);
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList(anyBoolean())).thenReturn(
-                new int[]{SUB_ID});
+        when(mMockSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(
+                new int[] {SUB_ID});
 
         // By default, assume we have no permissions or app-ops bits.
         doThrow(new SecurityException()).when(mMockContext)
@@ -354,7 +353,7 @@
     @Test
     public void testCheckReadDeviceIdentifiers_hasCarrierPrivilegesOnOtherSubscription()
             throws Exception {
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList(anyBoolean())).thenReturn(
+        when(mMockSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(
                 new int[]{SUB_ID, SUB_ID_2});
         when(mTelephonyManagerMock.createForSubscriptionId(eq(SUB_ID_2))).thenReturn(
                 mTelephonyManagerMockForSub2);
@@ -368,9 +367,7 @@
     @Test
     public void testCheckReadDeviceIdentifiers_hasCarrierPrivilegesOnInvisibleSubscription()
             throws Exception {
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList(true)).thenReturn(
-                new int[]{SUB_ID});
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList(false)).thenReturn(
+        when(mMockSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(
                 new int[]{SUB_ID, SUB_ID_2});
         when(mTelephonyManagerMock.createForSubscriptionId(eq(SUB_ID_2))).thenReturn(
                 mTelephonyManagerMockForSub2);
@@ -387,7 +384,8 @@
         // SubscriptionManager returns a null array for the active subscription IDs this check can
         // still proceed to check if the calling package has the appop and any subsequent checks
         // without a NullPointerException.
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(null);
+        when(mMockSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(
+                new int[]{});
         when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
                 PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
         assertTrue(
@@ -454,7 +452,7 @@
         when(mMockContext.checkPermission(
                 eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
                 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
-        when(mMockSubscriptionManager.getActiveSubscriptionIdList(anyBoolean())).thenReturn(
+        when(mMockSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(
                 new int[]{SUB_ID, SUB_ID_2});
         when(mTelephonyManagerMock.createForSubscriptionId(eq(SUB_ID_2))).thenReturn(
                 mTelephonyManagerMockForSub2);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
index 3d707da..0dc9647 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -65,7 +65,7 @@
         msg.isServicePresent = true;
         msg.serviceCategory = serviceCategory;
 
-        // dummy address (RIL may generate a different dummy address for broadcasts)
+        // placeholder address (RIL may generate a different placeholder address for broadcasts)
         msg.address.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
         msg.address.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
         msg.address.numberType = CdmaSmsAddress.TON_UNKNOWN;
@@ -601,7 +601,7 @@
         msg.isServicePresent = false;
         msg.serviceCategory = 0;
 
-        // dummy address (RIL may generate a different dummy address for broadcasts)
+        // placeholder address (RIL may generate a different placeholder address for broadcasts)
         msg.address.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
         msg.address.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
         msg.address.numberType = CdmaSmsAddress.TON_UNKNOWN;
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 45dff96..6dd37fd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -599,7 +599,7 @@
         assertEquals(apnSetting, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
         assertArrayEquals(new String[]{PhoneConstants.APN_TYPE_DEFAULT}, mDct.getActiveApnTypes());
 
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
         assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
 
         LinkProperties linkProperties = mDct.getLinkProperties(PhoneConstants.APN_TYPE_DEFAULT);
@@ -793,7 +793,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                 eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                 any(Message.class));
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
         assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
         assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
     }
@@ -904,7 +904,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                 eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                 any(Message.class));
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
         assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
         assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
 
@@ -942,7 +942,7 @@
                 any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);
 
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
         assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
         assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
 
@@ -990,7 +990,7 @@
                 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);
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
 
         AsyncResult ar = new AsyncResult(null,
                 new Pair<>(false, DataEnabledSettings.REASON_DATA_ENABLED_BY_CARRIER), null);
@@ -1003,7 +1003,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                 eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                 any(Message.class));
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
         assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
     }
 
@@ -1283,7 +1283,7 @@
                 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);
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
 
         //data rat change from ehrpd to lte
         logd("Sending EVENT_DATA_RAT_CHANGED");
@@ -1321,7 +1321,7 @@
                 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);
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
     }
 
     // Test for fetchDunApns()
@@ -1380,6 +1380,26 @@
         assertTrue(dunApnExpected.equals(dunApns.get(0)));
     }
 
+    @Test
+    @SmallTest
+    public void testFetchDunApnWhileRoaming() {
+        doReturn(true).when(mServiceState).getRoaming();
+        mBundle.putBoolean(CarrierConfigManager.KEY_DISABLE_DUN_APN_WHILE_ROAMING, true);
+
+        sendInitializationEvents();
+
+        String dunApnString = "[ApnSettingV3]HOT mobile PC,pc.hotm,,,,,,,,,440,10,,DUN,,,true,"
+                + "0,,,,,,,,";
+
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.TETHER_DUN_APN, dunApnString);
+        // Expect empty DUN APN list
+        assertEquals(0, mDct.fetchDunApns().size());
+
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.TETHER_DUN_APN, null);
+    }
+
     // Test oos
     @Test
     @SmallTest
@@ -1405,7 +1425,7 @@
                 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);
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
 
         // Data rat change from ehrpd to unknown due to OOS
         logd("Sending EVENT_DATA_RAT_CHANGED");
@@ -1437,7 +1457,7 @@
 
         // Verify the same data connection
         assertEquals(FAKE_APN4, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
-        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
+        assertTrue(mDct.isAnyDataConnected());
     }
 
     // Test provisioning
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
index 23a7ec9..5ff4aed 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
@@ -78,8 +78,8 @@
 
     @Test
     @SmallTest
-    public void tesUiccCartdInfoSanity() {
-        /* before update sanity test */
+    public void testUiccCartdInfoCorrectness() {
+        /* before update correctness test */
         assertEquals(0, mUiccCard.getNumApplications());
         assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUiccCard.getCardState());
         assertNull(mUiccCard.getUniversalPinState());
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 61a5e13..0118f74 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
@@ -37,6 +37,7 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
+import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -135,21 +136,21 @@
 
     @Test
     @SmallTest
-    public void testParseWhitelistMapFromString() {
-        String whitelist = "";
-        Map<String, String> parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
+    public void testParseAllowListMapFromString() {
+        String allowList = "";
+        Map<String, String> parsedMap = UiccProfile.parseToCertificateToPackageMap(allowList);
         assertTrue(parsedMap.isEmpty());
 
-        whitelist = "nokey;value;separation";
-        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
+        allowList = "nokey;value;separation";
+        parsedMap = UiccProfile.parseToCertificateToPackageMap(allowList);
         assertTrue(parsedMap.isEmpty());
 
-        whitelist = "KEY1:value1";
-        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
+        allowList = "KEY1:value1";
+        parsedMap = UiccProfile.parseToCertificateToPackageMap(allowList);
         assertEquals("value1", parsedMap.get("KEY1"));
 
-        whitelist = "KEY1:value1;   KEY2:value2  ;KEY3:value3";
-        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
+        allowList = "KEY1:value1;   KEY2:value2  ;KEY3:value3";
+        parsedMap = UiccProfile.parseToCertificateToPackageMap(allowList);
         assertEquals("value1", parsedMap.get("KEY1"));
         assertEquals("value2", parsedMap.get("KEY2"));
         assertEquals("value3", parsedMap.get("KEY3"));
@@ -606,4 +607,44 @@
         assertTrue(mUiccProfile.isEmptyProfile());
 
     }
+
+    private void testUpdateUiccProfileApplicationNoCsim() {
+        /* update app status and index */
+        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
+                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
+                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA1");
+        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
+                IccCardApplicationStatus.AppType.APPTYPE_USIM,
+                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
+        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{imsApp, umtsApp};
+        mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
+        mIccCardStatus.mImsSubscriptionAppIndex = 0;
+        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 1;
+        logd("Update UICC Profile Applications");
+        mUiccProfile.update(mContext, mSimulatedCommands, mIccCardStatus);
+        processAllMessages();
+
+        assertEquals(2, mUiccProfile.getNumApplications());
+        assertFalse(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_CSIM));
+        assertTrue(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_ISIM));
+        assertTrue(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_USIM));
+    }
+
+    @Test
+    @SmallTest
+    public void testSetVoiceRadioTech() {
+        // if voice rat is GSM, mCurrentAppType should be 3gpp
+        mUiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
+        assertEquals(UiccController.APP_FAM_3GPP, mUiccProfile.mCurrentAppType);
+
+        // if voice rat is CDMA, mCurrentAppType should be 3gpp2
+        mUiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
+        assertEquals(UiccController.APP_FAM_3GPP2, mUiccProfile.mCurrentAppType);
+
+        // if voice rat is CDMA, there is no CSIM app, and there is a SIM/USIM app, then
+        // mCurrentAppType should be 3gpp
+        testUpdateUiccProfileApplicationNoCsim();
+        mUiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
+        assertEquals(UiccController.APP_FAM_3GPP, mUiccProfile.mCurrentAppType);
+    }
 }