Merge "Clean CHerrypick - Displaying '4G' instead of 'LTE' when the config_show4GForLTE enabled."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7773af6..de14389 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1074,8 +1074,8 @@
     <!-- Label for the "No service" notification item, when expanded. -->
     <string name="notification_network_selection_title">No service</string>
     <!-- Label for the expanded "No service" notification item, including the
-         operator name set by user -->
-    <string name="notification_network_selection_text">Selected network (<xliff:g id="operator_name">%s</xliff:g>) unavailable</string>
+         operator name set by user. No space after "network", appended in nonempty value. -->
+    <string name="notification_network_selection_text">Selected network<xliff:g id="operator_name">%s</xliff:g> unavailable</string>
 
     <!-- In-call screen: call failure message displayed in an error dialog. [CHAR_LIMIT=NONE] -->
     <string name="incall_error_power_off" product="watch">Turn on mobile network, turn off airplane mode or turn off battery saver mode to make a call.</string>
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index bfeee7a..bdffb26 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -76,6 +76,11 @@
         mReplaceInvalidCFNumber = replaceInvalidCFNumber;
     }
 
+    void restoreCallForwardInfo(CallForwardInfo cf) {
+        handleCallForwardResult(cf);
+        updateSummaryText();
+    }
+
     @Override
     protected void onBindDialogView(View view) {
         // default the button clicked to be the cancel button.
@@ -100,7 +105,15 @@
             int action = (isToggled() || (mButtonClicked == DialogInterface.BUTTON_POSITIVE)) ?
                     CommandsInterface.CF_ACTION_REGISTRATION :
                     CommandsInterface.CF_ACTION_DISABLE;
-            int time = (reason != CommandsInterface.CF_REASON_NO_REPLY) ? 0 : 20;
+            int time = 0;
+            if (reason == CommandsInterface.CF_REASON_NO_REPLY) {
+                PersistableBundle carrierConfig = PhoneGlobals.getInstance()
+                        .getCarrierConfigForSubId(mPhone.getSubId());
+                if (carrierConfig.getBoolean(
+                        CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
+                    time = 20;
+                }
+            }
             final String number = getPhoneNumber();
 
             Log.d(LOG_TAG, "callForwardInfo=" + callForwardInfo);
@@ -137,7 +150,7 @@
         }
     }
 
-    void handleCallForwardResult(CallForwardInfo cf) {
+    private void handleCallForwardResult(CallForwardInfo cf) {
         callForwardInfo = cf;
         Log.d(LOG_TAG, "handleGetCFResponse done, callForwardInfo=" + callForwardInfo);
         // In some cases, the network can send call forwarding URIs for voicemail that violate the
diff --git a/src/com/android/phone/CdmaOptions.java b/src/com/android/phone/CdmaOptions.java
index 70744e5..9c713ef 100644
--- a/src/com/android/phone/CdmaOptions.java
+++ b/src/com/android/phone/CdmaOptions.java
@@ -39,6 +39,7 @@
 public class CdmaOptions {
     private static final String LOG_TAG = "CdmaOptions";
 
+    private CarrierConfigManager mCarrierConfigManager;
     private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
     private CdmaSubscriptionListPreference mButtonCdmaSubscription;
     private RestrictedPreference mButtonAPNExpand;
@@ -59,6 +60,7 @@
         mPrefFragment = prefFragment;
         mPrefScreen = prefScreen;
         mPrefFragment.addPreferencesFromResource(R.xml.cdma_options);
+        mCarrierConfigManager = new CarrierConfigManager(prefFragment.getContext());
 
         // Initialize preferences.
         mButtonCdmaSystemSelect = (CdmaSystemSelectListPreference) mPrefScreen
@@ -77,8 +79,7 @@
         int phoneType = TelephonyManager.from(mPrefFragment.getContext())
                 .createForSubscriptionId(mSubId).getPhoneType();
 
-        PersistableBundle carrierConfig =
-                PhoneGlobals.getInstance().getCarrierConfigForSubId(mSubId);
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
         // Some CDMA carriers want the APN settings.
         boolean addAPNExpand = shouldAddApnExpandPreference(phoneType, carrierConfig);
         boolean addCdmaSubscription =
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
index e562e46..6d80621 100644
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
@@ -31,6 +31,7 @@
     private static final String KEY_TOGGLE = "toggle";
     private static final String KEY_STATUS = "status";
     private static final String KEY_NUMBER = "number";
+    private static final String KEY_ENABLE = "enable";
 
     private CallForwardEditPreference mButtonCFU;
     private CallForwardEditPreference mButtonCFB;
@@ -112,11 +113,12 @@
                 for (CallForwardEditPreference pref : mPreferences) {
                     Bundle bundle = mIcicle.getParcelable(pref.getKey());
                     pref.setToggled(bundle.getBoolean(KEY_TOGGLE));
+                    pref.setEnabled(bundle.getBoolean(KEY_ENABLE));
                     CallForwardInfo cf = new CallForwardInfo();
                     cf.number = bundle.getString(KEY_NUMBER);
                     cf.status = bundle.getInt(KEY_STATUS);
                     pref.init(this, mPhone, mReplaceInvalidCFNumbers);
-                    pref.handleCallForwardResult(cf);
+                    pref.restoreCallForwardInfo(cf);
                 }
             }
             mFirstResume = false;
@@ -131,6 +133,7 @@
         for (CallForwardEditPreference pref : mPreferences) {
             Bundle bundle = new Bundle();
             bundle.putBoolean(KEY_TOGGLE, pref.isToggled());
+            bundle.putBoolean(KEY_ENABLE, pref.isEnabled());
             if (pref.callForwardInfo != null) {
                 bundle.putString(KEY_NUMBER, pref.callForwardInfo.number);
                 bundle.putInt(KEY_STATUS, pref.callForwardInfo.status);
diff --git a/src/com/android/phone/GsmUmtsOptions.java b/src/com/android/phone/GsmUmtsOptions.java
index 19cd3ef..a3f5cfb 100644
--- a/src/com/android/phone/GsmUmtsOptions.java
+++ b/src/com/android/phone/GsmUmtsOptions.java
@@ -16,6 +16,7 @@
 
 package com.android.phone;
 
+import android.content.Context;
 import android.content.Intent;
 import android.os.PersistableBundle;
 import android.preference.Preference;
@@ -23,6 +24,7 @@
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -36,6 +38,7 @@
 public class GsmUmtsOptions {
     private static final String LOG_TAG = "GsmUmtsOptions";
 
+    private CarrierConfigManager mCarrierConfigManager;
     private RestrictedPreference mButtonAPNExpand;
     private Preference mCategoryAPNExpand;
     Preference mCarrierSettingPref;
@@ -52,8 +55,10 @@
 
     public GsmUmtsOptions(PreferenceFragment prefFragment, PreferenceScreen prefScreen,
             final int subId, INetworkQueryService queryService) {
+        final Context context = prefFragment.getContext();
         mPrefFragment = prefFragment;
         mPrefScreen = prefScreen;
+        mCarrierConfigManager = new CarrierConfigManager(context);
         mPrefFragment.addPreferencesFromResource(R.xml.gsm_umts_options);
         mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
         mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
@@ -72,16 +77,17 @@
         boolean addAPNExpand = true;
         boolean addNetworkOperatorsCategory = true;
         boolean addCarrierSettings = true;
+        final TelephonyManager telephonyManager = TelephonyManager.from(mPrefFragment.getContext())
+                .createForSubscriptionId(subId);
         Phone phone = PhoneGlobals.getPhone(subId);
         if (phone == null) return;
-        if (phone.getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
+        if (telephonyManager.getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
             log("Not a GSM phone");
             addAPNExpand = false;
             mNetworkOperator.setEnabled(false);
         } else {
             log("Not a CDMA phone");
-            PersistableBundle carrierConfig =
-                    PhoneGlobals.getInstance().getCarrierConfigForSubId(subId);
+            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
 
             // Determine which options to display. For GSM these are defaulted to true in
             // CarrierConfigManager, but they maybe overriden by DefaultCarrierConfigService or a
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 7a795ed..c4f91ca 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -239,15 +239,16 @@
      * doesn't set {@link CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL} to false.
      */
     public static boolean hideEnhanced4gLteSettings(Context context) {
-        List<SubscriptionInfo> sil =
+        final CarrierConfigManager carrierConfigManager = new CarrierConfigManager(context);
+        final List<SubscriptionInfo> sil =
                 SubscriptionManager.from(context).getActiveSubscriptionInfoList();
         // Check all active subscriptions. We only hide the button if it's disabled for all
         // active subscriptions.
         if (sil != null) {
             for (SubscriptionInfo subInfo : sil) {
                 ImsManager imsManager = ImsManager.getInstance(context, subInfo.getSimSlotIndex());
-                PersistableBundle carrierConfig = PhoneGlobals.getInstance()
-                        .getCarrierConfigForSubId(subInfo.getSubscriptionId());
+                PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(
+                        subInfo.getSubscriptionId());
                 if ((imsManager.isVolteEnabledByPlatform()
                         && imsManager.isVolteProvisionedOnDevice())
                         || carrierConfig.getBoolean(
@@ -347,6 +348,7 @@
 
         private SubscriptionManager mSubscriptionManager;
         private TelephonyManager mTelephonyManager;
+        private CarrierConfigManager mCarrierConfigManager;
         private int mSubId;
 
         //UI objects
@@ -788,6 +790,7 @@
             mSubscriptionManager = SubscriptionManager.from(activity);
             mTelephonyManager = (TelephonyManager) activity.getSystemService(
                             Context.TELEPHONY_SERVICE);
+            mCarrierConfigManager = new CarrierConfigManager(getContext());
 
             if (icicle != null) {
                 mExpandAdvancedFields = icicle.getBoolean(EXPAND_ADVANCED_FIELDS, false);
@@ -1052,8 +1055,7 @@
                     android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
                     preferredNetworkMode);
 
-            PersistableBundle carrierConfig =
-                    PhoneGlobals.getInstance().getCarrierConfigForSubId(mSubId);
+            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
             mIsGlobalCdma = isLteOnCdma
                     && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
             if (carrierConfig.getBoolean(
@@ -1200,8 +1202,7 @@
         // Requires that mSubId is up to date
         void updateEnabledNetworksEntries() {
             final int phoneType = mTelephonyManager.getPhoneType();
-            final PersistableBundle carrierConfig =
-                    PhoneGlobals.getInstance().getCarrierConfigForSubId(mSubId);
+            final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
             if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                 final int lteForced = android.provider.Settings.Global.getInt(
                         getContext().getContentResolver(),
@@ -1444,8 +1445,8 @@
 
                 //normally called on the toggle click
                 if (!mButtonDataRoam.isChecked()) {
-                    PersistableBundle carrierConfig =
-                            PhoneGlobals.getInstance().getCarrierConfigForSubId(mSubId);
+                    PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
+                            mSubId);
                     if (carrierConfig != null && carrierConfig.getBoolean(
                             CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL)) {
                         mTelephonyManager.setDataRoamingEnabled(true);
@@ -1885,8 +1886,7 @@
                 return;
             }
 
-            PersistableBundle carrierConfig = PhoneGlobals.getInstance()
-                    .getCarrierConfigForSubId(mSubId);
+            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
 
             if ((mImsMgr == null
                     || !mImsMgr.isVolteEnabledByPlatform()
@@ -1909,8 +1909,7 @@
                 return;
             }
 
-            PersistableBundle carrierConfig = PhoneGlobals.getInstance()
-                    .getCarrierConfigForSubId(mSubId);
+            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
 
             if (mImsMgr != null
                     && mImsMgr.isVtEnabledByPlatform()
diff --git a/src/com/android/phone/NetworkOperators.java b/src/com/android/phone/NetworkOperators.java
index 6d8b30f..6d798b0 100644
--- a/src/com/android/phone/NetworkOperators.java
+++ b/src/com/android/phone/NetworkOperators.java
@@ -29,6 +29,7 @@
 import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -193,25 +194,12 @@
 
     // Used by both mAutoSelect and mNetworkSelect buttons.
     protected void displayNetworkSelectionFailed() {
-        String status = getContext().getResources().getString(R.string.connect_later);
-
-        final PhoneGlobals app = PhoneGlobals.getInstance();
-        app.notificationMgr.postTransientNotification(
-                NotificationMgr.NETWORK_SELECTION_NOTIFICATION, status);
-
-        ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(mSubId);
-        if (ss != null) {
-            app.notificationMgr.updateNetworkSelection(ss.getState(), mSubId);
-        }
+        Toast.makeText(getContext(), R.string.connect_later, Toast.LENGTH_LONG).show();
     }
 
     // Used by both mAutoSelect and mNetworkSelect buttons.
     protected void displayNetworkSelectionSucceeded() {
-        String status = getContext().getResources().getString(R.string.registration_done);
-
-        final PhoneGlobals app = PhoneGlobals.getInstance();
-        app.notificationMgr.postTransientNotification(
-                NotificationMgr.NETWORK_SELECTION_NOTIFICATION, status);
+        Toast.makeText(getContext(), R.string.registration_done, Toast.LENGTH_LONG).show();
     }
 
     private void selectNetworkAutomatic(boolean autoSelect) {
diff --git a/src/com/android/phone/NetworkSelectListPreference.java b/src/com/android/phone/NetworkSelectListPreference.java
index cec914a..5b841c9 100644
--- a/src/com/android/phone/NetworkSelectListPreference.java
+++ b/src/com/android/phone/NetworkSelectListPreference.java
@@ -403,8 +403,7 @@
                 final OperatorInfo operatorInfo = getOperatorInfoFromCellInfo(mCellInfo);
                 if (DBG) logd("manually selected network: " + operatorInfo.toString());
                 boolean isSuccessed = mTelephonyManager.setNetworkSelectionModeManual(
-                        operatorInfo.getOperatorNumeric(), true /* persistSelection */);
-                int mode = mTelephonyManager.getNetworkSelectionMode();
+                        operatorInfo, true /* persistSelection */);
                 Message msg = mHandler.obtainMessage(EVENT_MANUALLY_NETWORK_SELECTION_DONE);
                 msg.obj = isSuccessed;
                 msg.sendToTarget();
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
index 6ef85cb..c8a29ce 100644
--- a/src/com/android/phone/NetworkSelectSetting.java
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -228,7 +228,7 @@
                 ThreadUtils.postOnBackgroundThread(() -> {
                     Message msg = mHandler.obtainMessage(EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE);
                     msg.obj = mTelephonyManager.setNetworkSelectionModeManual(
-                            operatorInfo.getOperatorNumeric(), true /* persistSelection */);
+                            operatorInfo, true /* persistSelection */);
                     msg.sendToTarget();
                 });
 
@@ -279,7 +279,6 @@
                         mSelectedNetworkOperatorPreference.setSummary(R.string.network_connected);
                     } else {
                         if (DBG) logd("manual network selection: failed! ");
-                        updateNetworkSelection();
                         // Set summary as "Couldn't connect" to the selected network.
                         mSelectedNetworkOperatorPreference.setSummary(
                                 R.string.network_could_not_connect);
@@ -628,21 +627,6 @@
         }
     }
 
-    /**
-     * Call {@link NotificationMgr#updateNetworkSelection(int, int)} to send notification about
-     * no service of user selected operator
-     */
-    private void updateNetworkSelection() {
-        if (DBG) logd("Update notification about no service of user selected operator");
-        final PhoneGlobals app = PhoneGlobals.getInstance();
-        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
-            ServiceState ss = mTelephonyManager.getServiceState();
-            if (ss != null) {
-                app.notificationMgr.updateNetworkSelection(ss.getState(), mSubId);
-            }
-        }
-    }
-
     private void stopNetworkQuery() {
         // Stop the network query process
         try {
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 1b2d49e..5aa87d0 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -569,6 +569,9 @@
     private void showNetworkSelection(String operator, int subId) {
         if (DBG) log("showNetworkSelection(" + operator + ")...");
 
+        if (!TextUtils.isEmpty(operator)) {
+            operator = String.format(" (%s)", operator);
+        }
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(android.R.drawable.stat_sys_warning)
                 .setContentTitle(mContext.getString(R.string.notification_network_selection_title))
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index b1e061f..67ec932 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -41,6 +41,7 @@
 import android.os.UserManager;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
+import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
@@ -665,7 +666,9 @@
         if (isAirplaneNewlyOn) {
             // If we are trying to turn off the radio, make sure there are no active
             // emergency calls.  If there are, switch airplane mode back to off.
-            if (PhoneUtils.isInEmergencyCall(mCM)) {
+            TelecomManager tm = (TelecomManager) context.getSystemService(TELECOM_SERVICE);
+
+            if (tm != null && tm.isInEmergencyCall()) {
                 // Switch airplane mode back to off.
                 ConnectivityManager.from(this).setAirplaneMode(false);
                 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG)
@@ -862,6 +865,20 @@
     }
 
     /**
+     * Called when the network selection on the subscription {@code subId} is changed by the user.
+     *
+     * @param subId the subscription id.
+     */
+    public void onNetworkSelectionChanged(int subId) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            notificationMgr.updateNetworkSelection(phone.getServiceState().getState(), subId);
+        } else {
+            Log.w(LOG_TAG, "onNetworkSelectionChanged on null phone, subId: " + subId);
+        }
+    }
+
+    /**
      * Dismisses the message waiting (voicemail) indicator.
      *
      * @param subId the subscription id we should dismiss the notification for.
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index f089d8f..353f4b5 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -764,7 +764,16 @@
                     break;
 
                 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
-                    handleNullReturnEvent(msg, "setNetworkSelectionModeManual");
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null) {
+                        request.result = true;
+                    } else {
+                        request.result = false;
+                        loge("setNetworkSelectionModeManual " + ar.exception);
+                    }
+                    notifyRequester(request);
+                    mApp.onNetworkSelectionChanged(request.subId);
                     break;
 
                 case CMD_GET_MODEM_ACTIVITY_INFO:
@@ -1169,9 +1178,6 @@
     private Phone getPhone(int subId) {
         return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
     }
-    //
-    // Implementation of the ITelephony interface.
-    //
 
     public void dial(String number) {
         dialForSubscriber(getPreferredVoiceSubscription(), number);
@@ -2584,6 +2590,10 @@
 
     @Override
     public int getNetworkSelectionMode(int subId) {
+        if (!isActiveSubscription(subId)) {
+            return TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
+        }
+
         return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
     }
 
@@ -2745,6 +2755,10 @@
         return mSubscriptionController.getDefaultVoiceSubId();
     }
 
+    private boolean isActiveSubscription(int subId) {
+        return mSubscriptionController.isActiveSubId(subId);
+    }
+
     /**
      * @see android.telephony.TelephonyManager.WifiCallingChoices
      */
@@ -3285,6 +3299,10 @@
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "setNetworkSelectionModeAutomatic");
 
+        if (!isActiveSubscription(subId)) {
+            return;
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
             if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
@@ -3294,24 +3312,35 @@
         }
     }
 
-    /**
-     * Set the network selection mode to manual with the selected carrier.
+   /**
+     * Ask the radio to connect to the input network and change selection mode to manual.
+     *
+     * @param subId the id of the subscription.
+     * @param operatorInfo the operator information, included the PLMN, long name and short name of
+     * the operator to attach to.
+     * @param persistSelection whether the selection will persist until reboot. If true, only allows
+     * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
+     * normal network selection next time.
+     * @return {@code true} on success; {@code true} on any failure.
      */
     @Override
-    public boolean setNetworkSelectionModeManual(int subId, String operatorNumeric,
-            boolean persistSelection) {
+    public boolean setNetworkSelectionModeManual(
+            int subId, OperatorInfo operatorInfo, boolean persistSelection) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "setNetworkSelectionModeManual");
 
+        if (!isActiveSubscription(subId)) {
+            return false;
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
-            OperatorInfo operator = new OperatorInfo(
-                /* operatorAlphaLong */ "",
-                /* operatorAlphaShort */ "",
-                    operatorNumeric);
-            if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
-            ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
+            ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
                     persistSelection);
+            if (DBG) {
+                log("setNetworkSelectionModeManual: subId: " + subId
+                        + " operator: " + operatorInfo);
+            }
             return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
         } finally {
             Binder.restoreCallingIdentity(identity);
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index c5625e9..9ede914 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -1330,20 +1330,6 @@
         return audioManager.isSpeakerphoneOn();
     }
 
-    static boolean isInEmergencyCall(CallManager cm) {
-        Call fgCall = cm.getActiveFgCall();
-        // isIdle includes checks for the DISCONNECTING/DISCONNECTED state.
-        if(!fgCall.isIdle()) {
-            for (Connection cn : fgCall.getConnections()) {
-                if (PhoneNumberUtils.isLocalEmergencyNumber(PhoneGlobals.getInstance(),
-                        cn.getAddress())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     /**
      * Get the mute state of foreground phone, which has the current
      * foreground call
diff --git a/src/com/android/phone/RoamingDialogFragment.java b/src/com/android/phone/RoamingDialogFragment.java
index d24967b..384a120 100644
--- a/src/com/android/phone/RoamingDialogFragment.java
+++ b/src/com/android/phone/RoamingDialogFragment.java
@@ -35,6 +35,7 @@
 
     public static final String SUB_ID_KEY = "sub_id_key";
 
+    private CarrierConfigManager mCarrierConfigManager;
     private int mSubId;
 
     /**
@@ -52,6 +53,7 @@
         super.onAttach(context);
         Bundle args = getArguments();
         mSubId = args.getInt(SUB_ID_KEY);
+        mCarrierConfigManager = new CarrierConfigManager(context);
 
         // Verify host activity implemented callback interface
         FragmentManager fragmentManager = getFragmentManager();
@@ -68,8 +70,7 @@
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         int title = R.string.roaming_alert_title;
-        PersistableBundle carrierConfig =
-                PhoneGlobals.getInstance().getCarrierConfigForSubId(mSubId);
+        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
         if (carrierConfig != null && carrierConfig.getBoolean(
                 CarrierConfigManager.KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL)) {
             title = R.string.roaming_check_price_warning;
diff --git a/src/com/android/services/telephony/CdmaConferenceController.java b/src/com/android/services/telephony/CdmaConferenceController.java
index 24c3870..5d987f7 100644
--- a/src/com/android/services/telephony/CdmaConferenceController.java
+++ b/src/com/android/services/telephony/CdmaConferenceController.java
@@ -211,6 +211,7 @@
             // 4) Add the conference to the connection service if it is new.
             if (isNewlyCreated) {
                 Log.d(this, "Adding the conference call");
+                mConference.updateCallRadioTechAfterCreation();
                 mConnectionService.addConference(mConference);
             }
         } else if (conferenceConnections.isEmpty()) {
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index b196d57..5722834 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -640,6 +640,7 @@
 
         setState(mConferenceHost.getState());
         updateStatusHints();
+        putExtras(mConferenceHost.getExtras());
     }
 
     /**
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index e96815c..e9eef46 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -264,6 +264,7 @@
                                 mTelephonyConference, connection);
                         mTelephonyConference.addConnection(connection);
                     }
+                    mTelephonyConference.updateCallRadioTechAfterCreation();
                     mConnectionService.addConference(mTelephonyConference);
                 } else {
                     Log.d(this, "Trigger recalculate later");
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 31fe68f..440a504 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -36,6 +36,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
 import android.text.TextUtils;
@@ -96,6 +97,7 @@
     private static final int MSG_CDMA_VOICE_PRIVACY_ON = 15;
     private static final int MSG_CDMA_VOICE_PRIVACY_OFF = 16;
     private static final int MSG_HANGUP = 17;
+    private static final int MSG_SET_CALL_RADIO_TECH = 18;
 
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
@@ -240,6 +242,31 @@
                     int cause = (int) msg.obj;
                     hangup(cause);
                     break;
+
+                case MSG_SET_CALL_RADIO_TECH:
+                    int vrat = (int) msg.obj;
+                    // Check whether Wi-Fi call tech is changed, it means call radio tech is:
+                    //  a) changed from IWLAN to other value, or
+                    //  b) changed from other value to IWLAN.
+                    //
+                    // In other word, below conditions are all met:
+                    // 1) {@link #getCallRadioTech} is different from new vrat
+                    // 2) Current call radio technology indicates Wi-Fi call, i.e. {@link #isWifi}
+                    //    is true, or new vrat indicates Wi-Fi call.
+                    boolean isWifiTechChange = getCallRadioTech() != vrat
+                            && (isWifi() || vrat == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN);
+
+                    // Step 1) Updates call radio tech firstly, so that afterwards Wi-Fi related
+                    // update actions are taken correctly.
+                    setCallRadioTech(vrat);
+
+                    // Step 2) Handles Wi-Fi call tech change.
+                    if (isWifiTechChange) {
+                        updateConnectionProperties();
+                        updateStatusHints();
+                        refreshDisableAddCall();
+                    }
+                    break;
             }
         }
     };
@@ -421,14 +448,14 @@
         }
 
         /**
-         * Used by {@link com.android.internal.telephony.Connection} to report a change in whether
-         * the call is being made over a wifi network.
+         * Used by {@link com.android.internal.telephony.Connection} to report a change for
+         * the call radio technology.
          *
-         * @param isWifi True if call is made over wifi.
+         * @param vrat the RIL Voice Radio Technology used for current connection.
          */
         @Override
-        public void onWifiChanged(boolean isWifi) {
-            setWifi(isWifi);
+        public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {
+            mHandler.obtainMessage(MSG_SET_CALL_RADIO_TECH, vrat).sendToTarget();
         }
 
         /**
@@ -575,6 +602,11 @@
                 com.android.internal.telephony.Connection newConnection) {
             setOriginalConnection(newConnection);
         }
+
+        @Override
+        public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall) {
+            setIsNetworkIdentifiedEmergencyCall(isEmergencyCall);
+        }
     };
 
     protected com.android.internal.telephony.Connection mOriginalConnection;
@@ -599,13 +631,6 @@
     private int mOriginalConnectionCapabilities;
 
     /**
-     * Determines if the {@link TelephonyConnection} is using wifi.
-     * This is used when {@link TelephonyConnection#updateConnectionProperties()} is called to
-     * indicate whether a call has the {@link Connection#PROPERTY_WIFI} property.
-     */
-    private boolean mIsWifi;
-
-    /**
      * Determines the audio quality is high for the {@link TelephonyConnection}.
      * This is used when {@link TelephonyConnection#updateConnectionProperties}} is called to
      * indicate whether a call has the {@link Connection#PROPERTY_HIGH_DEF_AUDIO} property.
@@ -620,6 +645,15 @@
     private boolean mTreatAsEmergencyCall;
 
     /**
+     * Indicates whether the network has identified this call as an emergency call.  Where
+     * {@link #mTreatAsEmergencyCall} is based on comparing dialed numbers to a list of known
+     * emergency numbers, this property is based on whether the network itself has identified the
+     * call as an emergency call (which can be the case for an incoming call from emergency
+     * services).
+     */
+    private boolean mIsNetworkIdentifiedEmergencyCall;
+
+    /**
      * For video calls, indicates whether the outgoing video for the call can be paused using
      * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
      */
@@ -1030,7 +1064,7 @@
 
         newProperties = changeBitmask(newProperties, PROPERTY_HIGH_DEF_AUDIO,
                 hasHighDefAudioProperty());
-        newProperties = changeBitmask(newProperties, PROPERTY_WIFI, mIsWifi);
+        newProperties = changeBitmask(newProperties, PROPERTY_WIFI, isWifi());
         newProperties = changeBitmask(newProperties, PROPERTY_IS_EXTERNAL_CALL,
                 isExternalConnection());
         newProperties = changeBitmask(newProperties, PROPERTY_HAS_CDMA_VOICE_PRIVACY,
@@ -1038,6 +1072,8 @@
         newProperties = changeBitmask(newProperties, PROPERTY_ASSISTED_DIALING_USED,
                 mIsUsingAssistedDialing);
         newProperties = changeBitmask(newProperties, PROPERTY_IS_RTT, isRtt());
+        newProperties = changeBitmask(newProperties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL,
+                isNetworkIdentifiedEmergencyCall());
 
         if (getConnectionProperties() != newProperties) {
             setConnectionProperties(newProperties);
@@ -1117,12 +1153,14 @@
         // Set video state and capabilities
         setVideoState(mOriginalConnection.getVideoState());
         setOriginalConnectionCapabilities(mOriginalConnection.getConnectionCapabilities());
-        setWifi(mOriginalConnection.isWifi());
+        setIsNetworkIdentifiedEmergencyCall(mOriginalConnection.isNetworkIdentifiedEmergencyCall());
         setAudioModeIsVoip(mOriginalConnection.getAudioModeIsVoip());
         setVideoProvider(mOriginalConnection.getVideoProvider());
         setAudioQuality(mOriginalConnection.getAudioQuality());
         setTechnologyTypeExtra();
 
+        setCallRadioTech(mOriginalConnection.getCallRadioTech());
+
         // Post update of extras to the handler; extras are updated via the handler to ensure thread
         // safety. The Extras Bundle is cloned in case the original extras are modified while they
         // are being added to mOriginalConnectionExtras in updateExtras.
@@ -1239,7 +1277,7 @@
 
         if (isCurrentVideoCall) {
             return true;
-        } else if (wasVideoCall && mIsWifi && !isVowifiEnabled) {
+        } else if (wasVideoCall && isWifi() && !isVowifiEnabled) {
             return true;
         }
         return false;
@@ -1274,7 +1312,7 @@
             return false;
         }
 
-        if (mIsWifi && !canWifiCallsBeHdAudio) {
+        if (isWifi() && !canWifiCallsBeHdAudio) {
             return false;
         }
 
@@ -1831,21 +1869,31 @@
     }
 
     /**
-     * Sets whether the call is using wifi. Used when rebuilding the capabilities to set or unset
-     * the {@link Connection#PROPERTY_WIFI} property.
-     */
-    public void setWifi(boolean isWifi) {
-        mIsWifi = isWifi;
-        updateConnectionProperties();
-        updateStatusHints();
-        refreshDisableAddCall();
-    }
-
-    /**
      * Whether the call is using wifi.
      */
     boolean isWifi() {
-        return mIsWifi;
+        return getCallRadioTech() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
+    }
+
+    /**
+     * Sets whether this call has been identified by the network as an emergency call.
+     * @param isNetworkIdentifiedEmergencyCall {@code true} if the network has identified this call
+     * as an emergency call, {@code false} otherwise.
+     */
+    public void setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall) {
+        Log.d(this, "setIsNetworkIdentifiedEmergencyCall; callId=%s, "
+                + "isNetworkIdentifiedEmergencyCall=%b", getTelecomCallId(),
+                isNetworkIdentifiedEmergencyCall);
+        mIsNetworkIdentifiedEmergencyCall = isNetworkIdentifiedEmergencyCall;
+        updateConnectionProperties();
+    }
+
+    /**
+     * @return {@code true} if the network has identified this call as an emergency call,
+     * {@code false} otherwise.
+     */
+    public boolean isNetworkIdentifiedEmergencyCall() {
+        return mIsNetworkIdentifiedEmergencyCall;
     }
 
     /**
@@ -2025,7 +2073,7 @@
     }
 
     private void updateStatusHints() {
-        if (mIsWifi && getPhone() != null) {
+        if (isWifi() && getPhone() != null) {
             int labelId = isValidRingingCall()
                     ? R.string.status_hint_label_incoming_wifi_call
                     : R.string.status_hint_label_wifi_call;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 195194c..1d2dfcb 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1005,7 +1005,9 @@
         }
 
         Queue<Phone> cachedPhones = mEmergencyRetryCache.second;
-        Phone phoneUsed = c.getPhone();
+        // Need to refer default phone considering ImsPhone because
+        // cachedPhones is a list that contains default phones.
+        Phone phoneUsed = c.getPhone().getDefaultPhone();
         if (phoneUsed == null) {
             return;
         }
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 3bd2716..a18adb8 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -21,7 +21,6 @@
 import static junit.framework.Assert.fail;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -817,6 +816,7 @@
         testServiceState.setEmergencyOnly(isEmergencyOnly);
         when(phone.getServiceState()).thenReturn(testServiceState);
         when(phone.getPhoneId()).thenReturn(phoneId);
+        when(phone.getDefaultPhone()).thenReturn(phone);
         return phone;
     }
 
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 9040257..39e4579 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -74,6 +74,7 @@
                 any(Connection.PostDialListener.class));
         when(mMockPhone.getRingingCall()).thenReturn(mMockCall);
         when(mMockPhone.getContext()).thenReturn(null);
+        when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
         when(mMockCall.getState()).thenReturn(Call.State.ACTIVE);
         when(mMockCall.getPhone()).thenReturn(mMockPhone);
     }
@@ -107,6 +108,11 @@
         mLastConnectionEventExtras.add(extras);
     }
 
+    @Override
+    void clearOriginalConnection() {
+        // Do nothing since the original connection is mock object
+    }
+
     public int getNotifyPhoneAccountChangedCount() {
         return mNotifyPhoneAccountChangedCount;
     }