Merge "Handle multi-sim PUK reset in emergency dialer"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dbb9671..0028e63 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -87,11 +87,11 @@
     <protected-broadcast android:name= "android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
-    <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED" />
+    <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.NETWORK_COUNTRY_CHANGED" />
 
     <!-- For Vendor Debugging in Telephony -->
-    <protected-broadcast android:name="android.telephony.action.DEBUG_EVENT" />
+    <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
 
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
@@ -552,6 +552,7 @@
         <activity android:name="com.android.phone.settings.VoicemailSettingsActivity"
             android:label="@string/voicemail"
             android:configChanges="orientation|screenSize|keyboardHidden|screenLayout"
+            android:screenOrientation="portrait"
             android:theme="@style/DialerSettingsLight">
             <intent-filter >
                 <!-- DO NOT RENAME. There are existing apps which use this string. -->
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index bd97b69..3796e64 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -552,7 +552,8 @@
     }
 
     public void updatePhoneStateListeners(boolean isRefresh, int updateType, int subIdToUpdate) {
-        List<SubscriptionInfo> subInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
+        List<SubscriptionInfo> subInfos = SubscriptionController.getInstance()
+                .getActiveSubscriptionInfoList(mApplication.getOpPackageName());
 
         // Sort sub id list based on slot id, so that CFI/MWI notifications will be updated for
         // slot 0 first then slot 1. This is needed to ensure that when CFI or MWI is enabled for
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 1e9e286..137d3d1 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -532,8 +532,8 @@
         if (addSubIdExtra && (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN
                 && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY)) {
             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
-            intent.putExtra(TelephonyManager.EXTRA_PRECISE_CARRIER_ID,
-                    getPreciseCarrierIdForPhoneId(phoneId));
+            intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID,
+                    getSpecificCarrierIdForPhoneId(phoneId));
             intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, getCarrierIdForPhoneId(phoneId));
         }
         intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId);
@@ -564,7 +564,7 @@
         String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId);
         String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId);
         int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-        int preciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
         // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC.
         if (simOperator != null && simOperator.length() >= 3) {
             mcc = simOperator.substring(0, 3);
@@ -576,9 +576,9 @@
             gid1 = phone.getGroupIdLevel1();
             gid2 = phone.getGroupIdLevel2();
             carrierId = phone.getCarrierId();
-            preciseCarrierId = phone.getPreciseCarrierId();
+            specificCarrierId = phone.getSpecificCarrierId();
         }
-        return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, preciseCarrierId);
+        return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, specificCarrierId);
     }
 
     /** Returns the package name of a priveleged carrier app, or null if there is none. */
@@ -605,9 +605,9 @@
     }
 
     /**
-     * Get the sim precise carrier id {@link TelephonyManager#getSimPreciseCarrierId()}
+     * Get the sim specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}
      */
-    private int getPreciseCarrierIdForPhoneId(int phoneId) {
+    private int getSpecificCarrierIdForPhoneId(int phoneId) {
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
             return TelephonyManager.UNKNOWN_CARRIER_ID;
         }
@@ -615,7 +615,7 @@
         if (phone == null) {
             return TelephonyManager.UNKNOWN_CARRIER_ID;
         }
-        return phone.getPreciseCarrierId();
+        return phone.getSpecificCarrierId();
     }
 
     /**
@@ -636,7 +636,7 @@
      * Writes a bundle to an XML file.
      *
      * The bundle will be written to a file named after the package name, ICCID and
-     * precise carrier id {@link TelephonyManager#getSimPreciseCarrierId()}. the same carrier
+     * specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}. the same carrier
      * should have a single copy of XML file named after carrier id. However, it's still possible
      * that platform doesn't recognize the current sim carrier, we will use iccid + carrierid as
      * the canonical file name. carrierid can also handle the cases SIM OTA resolves to different
@@ -659,7 +659,7 @@
         }
 
         final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = getPreciseCarrierIdForPhoneId(phoneId);
+        final int cid = getSpecificCarrierIdForPhoneId(phoneId);
         if (packageName == null || iccid == null) {
             loge("Cannot save config with null packageName or iccid.");
             return;
@@ -734,7 +734,7 @@
         }
 
         final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = getPreciseCarrierIdForPhoneId(phoneId);
+        final int cid = getSpecificCarrierIdForPhoneId(phoneId);
         if (packageName == null || iccid == null) {
             loge("Cannot restore config with null packageName or iccid.");
             return null;
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 9e40ffe..38eb40d 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -129,7 +129,7 @@
         private MetricsLogger mMetricsLogger = new MetricsLogger();
 
         public void writeMetricsForEnter() {
-            if (!mIsShortcutViewEnabled) {
+            if (!mShortcutViewConfig.isEnabled()) {
                 return;
             }
 
@@ -142,7 +142,7 @@
         }
 
         public void writeMetricsForExit() {
-            if (!mIsShortcutViewEnabled) {
+            if (!mShortcutViewConfig.isEnabled()) {
                 return;
             }
 
@@ -157,7 +157,7 @@
 
         public void writeMetricsForMakingCall(int callSource, int phoneNumberType,
                 boolean hasShortcut) {
-            if (!mIsShortcutViewEnabled) {
+            if (!mShortcutViewConfig.isEnabled()) {
                 return;
             }
 
@@ -230,8 +230,6 @@
     private View mEmergencyShortcutView;
     private View mDialpadView;
 
-    private ShortcutViewUtils.PhoneInfo mPhoneInfo;
-
     private List<EmergencyShortcutButton> mEmergencyShortcutButtonList;
     private EccShortcutAdapter mShortcutAdapter;
     private DataSetObserver mShortcutDataSetObserver = null;
@@ -291,7 +289,7 @@
     private float mDefaultDigitsTextSize;
 
     private int mEntryType;
-    private boolean mIsShortcutViewEnabled;
+    private ShortcutViewUtils.Config mShortcutViewConfig;
 
     private MetricsWriter mMetricsWriter;
     private SensorManager mSensorManager;
@@ -361,20 +359,13 @@
         PersistableBundle carrierConfig =
                 configMgr.getConfigForSubId(SubscriptionManager.getDefaultVoiceSubscriptionId());
 
-        mIsShortcutViewEnabled = false;
-        mPhoneInfo = null;
-        if (canEnableShortcutView(carrierConfig)) {
-            mPhoneInfo = ShortcutViewUtils.pickPreferredPhone(this);
-            if (mPhoneInfo != null) {
-                mIsShortcutViewEnabled = true;
-            }
-        }
+        mShortcutViewConfig = new ShortcutViewUtils.Config(this, carrierConfig, mEntryType);
         Log.d(LOG_TAG, "Enable emergency dialer shortcut: "
-                + mIsShortcutViewEnabled);
+                + mShortcutViewConfig.isEnabled());
 
         mColorExtractor = new ColorExtractor(this);
 
-        if (mIsShortcutViewEnabled) {
+        if (mShortcutViewConfig.isEnabled()) {
             // Shortcut view doesn't support dark text theme.
             updateTheme(false);
         } else {
@@ -399,7 +390,7 @@
         ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay().getSize(displaySize);
         mBackgroundGradient.setScreenSize(displaySize.x, displaySize.y);
-        mBackgroundGradient.setAlpha(mIsShortcutViewEnabled
+        mBackgroundGradient.setAlpha(mShortcutViewConfig.isEnabled()
                 ? BLACK_BACKGROUND_GRADIENT_ALPHA : BACKGROUND_GRADIENT_ALPHA);
         getWindow().setBackgroundDrawable(mBackgroundGradient);
 
@@ -463,7 +454,7 @@
 
         mEmergencyInfoGroup = (EmergencyInfoGroup) findViewById(R.id.emergency_info_button);
 
-        if (mIsShortcutViewEnabled) {
+        if (mShortcutViewConfig.isEnabled()) {
             setupEmergencyShortcutsView();
         }
     }
@@ -529,7 +520,7 @@
     public void onBackPressed() {
         // If shortcut view is enabled and Dialpad view is visible, pressing the back key will
         // back to display EmergencyShortcutView view. Otherwise, it would finish the activity.
-        if (mIsShortcutViewEnabled && mDialpadView != null
+        if (mShortcutViewConfig.isEnabled() && mDialpadView != null
                 && mDialpadView.getVisibility() == View.VISIBLE) {
             switchView(mEmergencyShortcutView, mDialpadView, true);
             return;
@@ -606,7 +597,7 @@
         if (!TextUtils.isEmpty(phoneNumber)) {
             if (DBG) Log.d(LOG_TAG, "dial emergency number: " + Rlog.pii(LOG_TAG, phoneNumber));
             placeCall(phoneNumber, ParcelableCallAnalytics.CALL_SOURCE_EMERGENCY_SHORTCUT,
-                    mPhoneInfo);
+                    mShortcutViewConfig.getPhoneInfo());
         } else {
             Log.d(LOG_TAG, "emergency number is empty");
         }
@@ -747,7 +738,7 @@
         mUserActions = MetricsWriter.USER_ACTION_NONE;
         mMetricsWriter.writeMetricsForEnter();
 
-        if (mIsShortcutViewEnabled) {
+        if (mShortcutViewConfig.isEnabled()) {
             // Shortcut view doesn't support dark text theme.
             mBackgroundGradient.setColors(Color.BLACK, Color.BLACK, false);
             updateTheme(false);
@@ -760,8 +751,7 @@
             updateTheme(lockScreenColors.supportsDarkText());
         }
 
-        if (mIsShortcutViewEnabled) {
-            mPhoneInfo = ShortcutViewUtils.pickPreferredPhone(this);
+        if (mShortcutViewConfig.isEnabled()) {
             updateLocationAndEccInfo();
         }
     }
@@ -811,19 +801,6 @@
         mColorExtractor.removeOnColorsChangedListener(this);
     }
 
-    private boolean canEnableShortcutView(PersistableBundle carrierConfig) {
-        if (mEntryType != ENTRY_TYPE_POWER_MENU) {
-            Log.d(LOG_TAG, "Disables shortcut view since it's not launched from power menu");
-            return false;
-        }
-        if (!carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL)) {
-            Log.d(LOG_TAG, "Disables shortcut view by carrier requirement");
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Sets theme based on gradient colors
      *
@@ -867,17 +844,14 @@
         // nothing and just returns input number.
         mLastNumber = PhoneNumberUtils.convertToEmergencyNumber(this, mLastNumber);
 
-        boolean isEmergencyNumber = false;
+        boolean isEmergencyNumber;
         ShortcutViewUtils.PhoneInfo phoneToMakeCall = null;
-        if (mPhoneInfo != null) {
-            isEmergencyNumber = mPhoneInfo.hasPromotedEmergencyNumber(mLastNumber);
-            if (isEmergencyNumber) {
-                phoneToMakeCall = mPhoneInfo;
-            }
-        }
-        if (!isEmergencyNumber) {
+        if (mShortcutViewConfig.hasPromotedEmergencyNumber(mLastNumber)) {
+            isEmergencyNumber = true;
+            phoneToMakeCall = mShortcutViewConfig.getPhoneInfo();
+        } else {
             TelephonyManager tm = getSystemService(TelephonyManager.class);
-            isEmergencyNumber = tm.isCurrentEmergencyNumber(mLastNumber);
+            isEmergencyNumber = tm.isEmergencyNumber(mLastNumber);
         }
 
         if (isEmergencyNumber) {
@@ -1155,7 +1129,7 @@
     private void setLocationInfo() {
         final View locationInfo = findViewById(R.id.location_info);
 
-        String countryIso = mPhoneInfo != null ? mPhoneInfo.getCountryIso() : null;
+        String countryIso = mShortcutViewConfig.getCountryIso();
         String countryName = null;
         if (!TextUtils.isEmpty(countryIso)) {
             Locale locale = Locale.getDefault();
@@ -1236,7 +1210,7 @@
         if (!isFinishing() && !isDestroyed()) {
             setLocationInfo();
             if (mShortcutAdapter != null) {
-                mShortcutAdapter.updateCountryEccInfo(this, mPhoneInfo);
+                mShortcutAdapter.updateCountryEccInfo(this, mShortcutViewConfig.getPhoneInfo());
             }
         }
     }
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index ee23e6f..18fc534 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -113,7 +113,7 @@
     public static boolean shouldPromoteWfc(Context context, int phoneId) {
         CarrierConfigManager cfgManager = (CarrierConfigManager) context
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        if (cfgManager == null || cfgManager.getConfigForSubId(getSubId(phoneId))
+        if (cfgManager == null || !cfgManager.getConfigForSubId(getSubId(phoneId))
                 .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
             return false;
         }
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
index d9731be..45478d9 100644
--- a/src/com/android/phone/NetworkSelectSetting.java
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -31,7 +31,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -382,7 +382,7 @@
      * Config the connected network operator preference when the page was created. When user get
      * into this page, the device might or might not have data connection.
      *   - If the device has data:
-     *     1. use {@code ServiceState#getNetworkRegistrationStates()} to get the currently
+     *     1. use {@code ServiceState#getNetworkRegistrationInfoList()} to get the currently
      *        registered cellIdentity, wrap it into a CellInfo;
      *     2. set the signal strength level as strong;
      *     3. use {@link TelephonyManager#getNetworkOperatorName()} to get the title of the
@@ -396,10 +396,11 @@
         if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
             // Try to get the network registration states
             ServiceState ss = mTelephonyManager.getServiceState();
-            List<NetworkRegistrationState> networkList =
-                    ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN);
+            List<NetworkRegistrationInfo> networkList =
+                    ss.getNetworkRegistrationInfoListForTransportType(
+                            AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
             if (networkList == null || networkList.size() == 0) {
-                loge("getNetworkRegistrationStates return null");
+                loge("getNetworkRegistrationInfoList return null");
                 // Remove the connected network operators category
                 removeConnectedNetworkOperatorPreference();
                 return;
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 3d82e74..94cd0f6 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -43,8 +43,8 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.telecom.TelecomManager;
+import android.telephony.AnomalyReporter;
 import android.telephony.CarrierConfigManager;
-import android.telephony.DebugEventReporter;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -284,8 +284,8 @@
         //   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
 
         if (mCM == null) {
-            // Initialize DebugEventReporter early so that it can be used
-            DebugEventReporter.initialize(this);
+            // Initialize AnomalyReporter early so that it can be used
+            AnomalyReporter.initialize(this);
 
             // Inject telephony component factory if configured using other jars.
             XmlResourceParser parser = getResources().getXml(R.xml.telephony_injection);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index fd484f0..c04b639 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -24,6 +24,7 @@
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -53,6 +54,7 @@
 import android.os.WorkSource;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
+import android.provider.Telephony;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -138,6 +140,7 @@
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.euicc.EuiccConnector;
+import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.IccUtils;
@@ -1299,8 +1302,16 @@
     }
 
     private Phone getPhoneFromRequest(MainThreadRequest request) {
-        return (request.subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
-                ? getDefaultPhone() : getPhone(request.subId);
+        if (request.phone != null) {
+            return request.phone;
+        } else {
+            return getPhoneFromSubId(request.subId);
+        }
+    }
+
+    private Phone getPhoneFromSubId(int subId) {
+        return (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                ? getDefaultPhone() : getPhone(subId);
     }
 
     private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
@@ -2212,23 +2223,23 @@
     }
 
     @Override
-    public int getSubscriptionPreciseCarrierId(int subId) {
+    public int getSubscriptionSpecificCarrierId(int subId) {
         final long identity = Binder.clearCallingIdentity();
         try {
             final Phone phone = getPhone(subId);
             return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID
-                    : phone.getPreciseCarrierId();
+                    : phone.getSpecificCarrierId();
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     @Override
-    public String getSubscriptionPreciseCarrierName(int subId) {
+    public String getSubscriptionSpecificCarrierName(int subId) {
         final long identity = Binder.clearCallingIdentity();
         try {
             final Phone phone = getPhone(subId);
-            return phone == null ? null : phone.getPreciseCarrierName();
+            return phone == null ? null : phone.getSpecificCarrierName();
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -3656,13 +3667,43 @@
         return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
     }
 
+    private Phone getPhoneFromSlotIdOrThrowException(int slotIndex) {
+        int phoneId = UiccController.getInstance().getPhoneIdFromSlotId(slotIndex);
+        if (phoneId == -1) {
+            throw new IllegalArgumentException("Given slot index: " + slotIndex
+                    + " does not correspond to an active phone");
+        }
+        return PhoneFactory.getPhone(phoneId);
+    }
+
     @Override
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
             int subId, String callingPackage, String aid, int p2) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "iccOpenLogicalChannel");
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (DBG) {
+            log("iccOpenLogicalChannel: subId=" + subId + " aid=" + aid + " p2=" + p2);
+        }
+        return iccOpenLogicalChannelWithPermission(getPhoneFromSubId(subId), callingPackage, aid,
+                p2);
+    }
 
+
+    @Override
+    public IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(
+            int slotIndex, String callingPackage, String aid, int p2) {
+        enforceModifyPermission();
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (DBG) {
+            log("iccOpenLogicalChannelBySlot: slot=" + slotIndex + " aid=" + aid + " p2=" + p2);
+        }
+        return iccOpenLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
+                callingPackage, aid, p2);
+    }
+
+    private IccOpenLogicalChannelResponse iccOpenLogicalChannelWithPermission(Phone phone,
+            String callingPackage, String aid, int p2) {
         final long identity = Binder.clearCallingIdentity();
         try {
             if (TextUtils.equals(ISDR_AID, aid)) {
@@ -3677,12 +3718,10 @@
                 }
             }
 
-            if (DBG) {
-                log("iccOpenLogicalChannel: subId=" + subId + " aid=" + aid + " p2=" + p2);
-            }
             IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse) sendRequest(
-                    CMD_OPEN_CHANNEL, new Pair<String, Integer>(aid, p2), subId);
-            if (DBG) log("iccOpenLogicalChannel: " + response);
+                    CMD_OPEN_CHANNEL, new Pair<String, Integer>(aid, p2), phone,
+                    null /* workSource */);
+            if (DBG) log("iccOpenLogicalChannelWithPermission: " + response);
             return response;
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -3693,15 +3732,27 @@
     public boolean iccCloseLogicalChannel(int subId, int channel) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "iccCloseLogicalChannel");
+        if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
+        return iccCloseLogicalChannelWithPermission(getPhoneFromSubId(subId), channel);
+    }
 
+    @Override
+    public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
+        enforceModifyPermission();
+        if (DBG) log("iccCloseLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel);
+        return iccCloseLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
+                channel);
+    }
+
+    private boolean iccCloseLogicalChannelWithPermission(Phone phone, int channel) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
             if (channel < 0) {
                 return false;
             }
-            Boolean success = (Boolean) sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
-            if (DBG) log("iccCloseLogicalChannel: " + success);
+            Boolean success = (Boolean) sendRequest(CMD_CLOSE_CHANNEL, channel, phone,
+                    null /* workSource */);
+            if (DBG) log("iccCloseLogicalChannelWithPermission: " + success);
             return success;
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -3713,22 +3764,41 @@
             int command, int p1, int p2, int p3, String data) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "iccTransmitApduLogicalChannel");
+        if (DBG) {
+            log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
+                    + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
+                    + p3 + " data=" + data);
+        }
+        return iccTransmitApduLogicalChannelWithPermission(getPhoneFromSubId(subId), channel, cla,
+                command, p1, p2, p3, data);
+    }
 
+    @Override
+    public String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla,
+            int command, int p1, int p2, int p3, String data) {
+        enforceModifyPermission();
+        if (DBG) {
+            log("iccTransmitApduLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel
+                    + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
+                    + p3 + " data=" + data);
+        }
+        return iccTransmitApduLogicalChannelWithPermission(
+                getPhoneFromSlotIdOrThrowException(slotIndex), channel, cla, command, p1, p2, p3,
+                data);
+    }
+
+    private String iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla,
+            int command, int p1, int p2, int p3, String data) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (DBG) {
-                log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
-                        + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
-                        + p3 + " data=" + data);
-            }
-
             if (channel < 0) {
                 return "";
             }
 
             IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
-                    new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
-            if (DBG) log("iccTransmitApduLogicalChannel: " + response);
+                    new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), phone,
+                    null /* workSource */);
+            if (DBG) log("iccTransmitApduLogicalChannelWithPermission: " + response);
 
             // Append the returned status code to the end of the response payload.
             String s = Integer.toHexString(
@@ -3748,7 +3818,33 @@
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "iccTransmitApduBasicChannel");
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (DBG) {
+            log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
+                    + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
+        }
+        return iccTransmitApduBasicChannelWithPermission(getPhoneFromSubId(subId), callingPackage,
+                cla, command, p1, p2, p3, data);
+    }
 
+    @Override
+    public String iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla,
+            int command, int p1, int p2, int p3, String data) {
+        enforceModifyPermission();
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (DBG) {
+            log("iccTransmitApduBasicChannelBySlot: slotIndex=" + slotIndex + " cla=" + cla
+                    + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3
+                    + " data=" + data);
+        }
+
+        return iccTransmitApduBasicChannelWithPermission(
+                getPhoneFromSlotIdOrThrowException(slotIndex), callingPackage, cla, command, p1,
+                p2, p3, data);
+    }
+
+    // open APDU basic channel assuming the caller has sufficient permissions
+    private String iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage,
+            int cla, int command, int p1, int p2, int p3, String data) {
         final long identity = Binder.clearCallingIdentity();
         try {
             if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
@@ -3764,14 +3860,10 @@
                 }
             }
 
-            if (DBG) {
-                log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
-                        + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
-            }
-
             IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
-                    new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
-            if (DBG) log("iccTransmitApduBasicChannel: " + response);
+                    new IccAPDUArgument(0, cla, command, p1, p2, p3, data), phone,
+                    null /* workSource */);
+            if (DBG) log("iccTransmitApduBasicChannelWithPermission: " + response);
 
             // Append the returned status code to the end of the response payload.
             String s = Integer.toHexString(
@@ -4027,7 +4119,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            PhoneFactory.getImsResolver().enableIms(slotId);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return;
+            }
+            resolver.enableIms(slotId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4042,7 +4139,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            PhoneFactory.getImsResolver().disableIms(slotId);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return;
+            }
+            resolver.disableIms(slotId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4059,7 +4161,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().getMmTelFeatureAndListen(slotId, callback);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return null;
+            }
+            return resolver.getMmTelFeatureAndListen(slotId, callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4076,7 +4183,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().getRcsFeatureAndListen(slotId, callback);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return null;
+            }
+            return resolver.getRcsFeatureAndListen(slotId, callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4084,14 +4196,19 @@
 
     /**
      * Returns the {@link IImsRegistration} structure associated with the slotId and feature
-     * specified.
+     * specified or null if IMS is not supported on the slot specified.
      */
     public IImsRegistration getImsRegistration(int slotId, int feature) throws RemoteException {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().getImsRegistration(slotId, feature);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return null;
+            }
+            return resolver.getImsRegistration(slotId, feature);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4099,14 +4216,19 @@
 
     /**
      * Returns the {@link IImsConfig} structure associated with the slotId and feature
-     * specified.
+     * specified or null if IMS is not supported on the slot specified.
      */
     public IImsConfig getImsConfig(int slotId, int feature) throws RemoteException {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().getImsConfig(slotId, feature);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return null;
+            }
+            return resolver.getImsConfig(slotId, feature);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4131,8 +4253,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().overrideImsServiceConfiguration(slotId,
-                    isCarrierImsService, packageName);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return false;
+            }
+            return resolver.overrideImsServiceConfiguration(slotId, isCarrierImsService,
+                    packageName);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4154,8 +4281,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneFactory.getImsResolver().getImsServiceConfiguration(slotId,
-                    isCarrierImsService);
+            ImsResolver resolver = PhoneFactory.getImsResolver();
+            if (resolver == null) {
+                // may happen if the device does not support IMS.
+                return "";
+            }
+            return resolver.getImsServiceConfiguration(slotId, isCarrierImsService);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5182,11 +5313,22 @@
                 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
                 CarrierInfoManager.deleteAllCarrierKeysForImsiEncryption(mApp);
             }
+            // There has been issues when Sms raw table somehow stores orphan
+            // fragments. They lead to garbled message when new fragments come
+            // in and combined with those stale ones. In case this happens again,
+            // user can reset all network settings which will clean up this table.
+            cleanUpSmsRawTable(getDefaultPhone().getContext());
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
+    private void cleanUpSmsRawTable(Context context) {
+        ContentResolver resolver = context.getContentResolver();
+        Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
+        resolver.delete(uri, null, null);
+    }
+
     @Override
     public String getSimLocaleForSubscriber(int subId) {
         enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
@@ -6424,10 +6566,10 @@
     }
 
     @Override
-    public Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList(
+    public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
             String callingPackage) {
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                mApp, getDefaultSubscription(), callingPackage, "getCurrentEmergencyNumberList")) {
+                mApp, getDefaultSubscription(), callingPackage, "getEmergencyNumberList")) {
             throw new SecurityException("Requires READ_PHONE_STATE permission.");
         }
         final long identity = Binder.clearCallingIdentity();
@@ -6448,12 +6590,12 @@
     }
 
     @Override
-    public boolean isCurrentEmergencyNumber(String number, boolean exactMatch) {
+    public boolean isEmergencyNumber(String number, boolean exactMatch) {
         final Phone defaultPhone = getDefaultPhone();
         if (!exactMatch) {
             TelephonyPermissions
                     .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
-                            mApp, defaultPhone.getSubId(), "isCurrentEmergencyNumber(Potential)");
+                            mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
         }
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -6559,13 +6701,13 @@
     }
 
     @Override
-    public void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted) {
+    public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             mTelephonySharedPreferences.edit()
-                    .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultisimCarrierRestricted)
+                    .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultiSimCarrierRestricted)
                     .commit();
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -6573,45 +6715,47 @@
     }
 
     @Override
-    public boolean isMultisimSupported(String callingPackage) {
+    @TelephonyManager.IsMultiSimSupportedResult
+    public int isMultiSimSupported(String callingPackage) {
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp,
-                getDefaultPhone().getSubId(), callingPackage, "isMultisimSupported")) {
-            return false;
+                getDefaultPhone().getSubId(), callingPackage, "isMultiSimSupported")) {
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return isMultisimSupportedInternal();
+            return isMultiSimSupportedInternal();
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
-    private boolean isMultisimSupportedInternal() {
+    @TelephonyManager.IsMultiSimSupportedResult
+    private int isMultiSimSupportedInternal() {
         // If the device has less than 2 SIM cards, indicate that multisim is restricted.
         int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
         if (numPhysicalSlots < 2) {
-            loge("isMultisimSupportedInternal: requires at least 2 cards");
-            return false;
+            loge("isMultiSimSupportedInternal: requires at least 2 cards");
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
         // Check if the hardware supports multisim functionality. If usage of multisim is not
         // supported by the modem, indicate that it is restricted.
         PhoneCapability staticCapability =
                 mPhoneConfigurationManager.getStaticPhoneCapability();
         if (staticCapability == null) {
-            loge("isMultisimSupportedInternal: no static configuration available");
-            return false;
+            loge("isMultiSimSupportedInternal: no static configuration available");
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
         if (staticCapability.logicalModemList.size() < 2) {
-            loge("isMultisimSupportedInternal: maximum number of modem is < 2");
-            return false;
+            loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
         }
         // Check if support of multiple SIMs is restricted by carrier
         if (mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false)) {
-            return false;
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_CARRIER;
         }
 
-        return true;
+        return TelephonyManager.MULTISIM_ALLOWED;
     }
 
     /**
@@ -6633,7 +6777,7 @@
 
         try {
             //only proceed if multi-sim is not restricted
-            if (!isMultisimSupportedInternal()) {
+            if (isMultiSimSupportedInternal() != TelephonyManager.MULTISIM_ALLOWED) {
                 loge("switchMultiSimConfig not possible. It is restricted or not supported.");
                 return;
             }
diff --git a/src/com/android/phone/ShortcutViewUtils.java b/src/com/android/phone/ShortcutViewUtils.java
index 595ea86..8e5ab42 100644
--- a/src/com/android/phone/ShortcutViewUtils.java
+++ b/src/com/android/phone/ShortcutViewUtils.java
@@ -17,9 +17,12 @@
 package com.android.phone;
 
 import android.content.Context;
+import android.os.PersistableBundle;
+import android.provider.Settings;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.emergency.EmergencyNumber;
@@ -54,6 +57,64 @@
         PROMOTED_CATEGORIES_BITMASK = bitmask;
     }
 
+    static class Config {
+        private final boolean mCanEnableShortcutView;
+        private PhoneInfo mPhoneInfo = null;
+
+        Config(@NonNull Context context, PersistableBundle carrierConfig, int entryType) {
+            mCanEnableShortcutView = canEnableShortcutView(carrierConfig, entryType);
+            refresh(context);
+        }
+
+        void refresh(@NonNull Context context) {
+            if (mCanEnableShortcutView && !isAirplaneModeOn(context)) {
+                mPhoneInfo = ShortcutViewUtils.pickPreferredPhone(context);
+            } else {
+                mPhoneInfo = null;
+            }
+        }
+
+        boolean isEnabled() {
+            return mPhoneInfo != null;
+        }
+
+        PhoneInfo getPhoneInfo() {
+            return mPhoneInfo;
+        }
+
+        String getCountryIso() {
+            if (mPhoneInfo == null) {
+                return null;
+            }
+            return mPhoneInfo.getCountryIso();
+        }
+
+        boolean hasPromotedEmergencyNumber(String number) {
+            if (mPhoneInfo == null) {
+                return false;
+            }
+            return mPhoneInfo.hasPromotedEmergencyNumber(number);
+        }
+
+        private boolean canEnableShortcutView(PersistableBundle carrierConfig, int entryType) {
+            if (entryType != EmergencyDialer.ENTRY_TYPE_POWER_MENU) {
+                Log.d(LOG_TAG, "Disables shortcut view since it's not launched from power menu");
+                return false;
+            }
+            if (carrierConfig == null || !carrierConfig.getBoolean(
+                    CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL)) {
+                Log.d(LOG_TAG, "Disables shortcut view by carrier requirement");
+                return false;
+            }
+            return true;
+        }
+
+        private boolean isAirplaneModeOn(@NonNull Context context) {
+            return Settings.Global.getInt(context.getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+        }
+    }
+
     // Info and emergency call capability of every phone.
     static class PhoneInfo {
         private final PhoneAccountHandle mHandle;
@@ -242,7 +303,7 @@
     private static Map<Integer, List<EmergencyNumber>> getPromotedEmergencyNumberLists(
             @NonNull TelephonyManager telephonyManager) {
         Map<Integer, List<EmergencyNumber>> allLists =
-                telephonyManager.getCurrentEmergencyNumberList();
+                telephonyManager.getEmergencyNumberList();
         if (allLists == null || allLists.isEmpty()) {
             Log.w(LOG_TAG, "Unable to retrieve emergency number lists!");
             return new ArrayMap<>();
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 5c614d9..d540fba 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -93,7 +93,7 @@
         mButtonHac = (SwitchPreference) findPreference(BUTTON_HAC_KEY);
         mButtonRtt = (SwitchPreference) findPreference(BUTTON_RTT_KEY);
 
-        if (PhoneGlobals.getInstance().phoneMgr.isTtyModeSupported()) {
+        if (PhoneGlobals.getInstance().phoneMgr.isTtyModeSupported() && isTtySupportedByCarrier()) {
             mButtonTty.init();
         } else {
             getPreferenceScreen().removePreference(mButtonTty);
@@ -191,4 +191,15 @@
         }
         return false;
     }
+
+    /**
+     * Determines if the device supports TTY per carrier config.
+     * @return {@code true} if the carrier supports TTY, {@code false} otherwise.
+     */
+    private boolean isTtySupportedByCarrier() {
+        CarrierConfigManager configManager =
+                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        return configManager.getConfig().getBoolean(
+                CarrierConfigManager.KEY_TTY_SUPPORTED_BOOL);
+    }
 }
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6026443..d6c1da6 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -115,7 +116,10 @@
             }
 
             try {
-                mMmTelManager = ImsMmTelManager.createForSubscriptionId(getSubId());
+                if (mPhone.getContext().getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_TELEPHONY_IMS)) {
+                    mMmTelManager = ImsMmTelManager.createForSubscriptionId(getSubId());
+                }
             } catch (IllegalArgumentException e) {
                 Log.i(this, "Not registering MmTel capabilities listener because the subid '"
                         + getSubId() + "' is invalid: " + e.getMessage());
@@ -1031,10 +1035,16 @@
                     Log.d(this, "Phone with subscription id %d", subscriptionId);
                     // setupAccounts can be called multiple times during service changes. Don't add an
                     // account if the Icc has not been set yet.
-                    if (subscriptionId >= 0 && phone.getFullIccSerialNumber() != null) {
-                        mAccounts.add(new AccountEntry(phone, false /* emergency */,
-                                false /* isDummy */));
-                    }
+                    if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)
+                            || phone.getFullIccSerialNumber() == null) return;
+                    // Don't add account if it's opportunistic subscription, which is considered
+                    // data only for now.
+                    SubscriptionInfo info = SubscriptionManager.from(mContext)
+                            .getActiveSubscriptionInfo(subscriptionId);
+                    if (info == null || info.isOpportunistic()) return;
+
+                    mAccounts.add(new AccountEntry(phone, false /* emergency */,
+                            false /* isDummy */));
                 }
             }
 
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 7c09320..632e9ac 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -932,12 +932,6 @@
             try {
                 Phone phone = mOriginalConnection.getCall().getPhone();
 
-                // New behavior for IMS -- don't use the clunky switchHoldingAndActive logic.
-                if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
-                    ImsPhone imsPhone = (ImsPhone) phone;
-                    imsPhone.holdActiveCall();
-                    return;
-                }
                 Call ringingCall = phone.getRingingCall();
 
                 // Although the method says switchHoldingAndActive, it eventually calls a RIL method
@@ -951,6 +945,12 @@
                 // could "fake" hold by silencing the audio and microphone streams for this call
                 // instead of actually putting it on hold.
                 if (ringingCall.getState() != Call.State.WAITING) {
+                    // New behavior for IMS -- don't use the clunky switchHoldingAndActive logic.
+                    if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
+                        ImsPhone imsPhone = (ImsPhone) phone;
+                        imsPhone.holdActiveCall();
+                        return;
+                    }
                     phone.switchHoldingAndActive();
                 }
 
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 6d7c1f0..fd7eeb2 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -239,12 +239,12 @@
 
         @Override
         public boolean isCurrentEmergencyNumber(String number) {
-            return mTelephonyManager.isCurrentEmergencyNumber(number);
+            return mTelephonyManager.isEmergencyNumber(number);
         }
 
         @Override
         public Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList() {
-            return mTelephonyManager.getCurrentEmergencyNumberList();
+            return mTelephonyManager.getEmergencyNumberList();
         }
     }
 
@@ -518,6 +518,7 @@
     }
 
     private boolean isEmergencyNumberTestNumber(String number) {
+        number = PhoneNumberUtils.stripSeparators(number);
         Map<Integer, List<EmergencyNumber>> list =
                 mTelephonyManagerProxy.getCurrentEmergencyNumberList();
         // Do not worry about which subscription the test emergency call is on yet, only detect that
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
index 50be698..4ee9355 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
@@ -151,8 +151,8 @@
     private static final Map<Integer, String> REG_TECH_STRING = new ArrayMap<>(2);
     static {
         REG_TECH_STRING.put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, "NONE");
-        REG_TECH_STRING.put(AccessNetworkConstants.TransportType.WWAN, "WWAN");
-        REG_TECH_STRING.put(AccessNetworkConstants.TransportType.WLAN, "WLAN");
+        REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, "WWAN");
+        REG_TECH_STRING.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, "WLAN");
     }