Merge "Migrate packages/services/Telephony to androidx.test"
diff --git a/res/drawable-hdpi/ic_add_gnu_grey.png b/res/drawable-hdpi/ic_add_gnu_grey.png
new file mode 100644
index 0000000..9196537
--- /dev/null
+++ b/res/drawable-hdpi/ic_add_gnu_grey.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_add_gnu_grey.png b/res/drawable-mdpi/ic_add_gnu_grey.png
new file mode 100644
index 0000000..3afab9c
--- /dev/null
+++ b/res/drawable-mdpi/ic_add_gnu_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_add_gnu_grey.png b/res/drawable-xhdpi/ic_add_gnu_grey.png
new file mode 100644
index 0000000..e85f779
--- /dev/null
+++ b/res/drawable-xhdpi/ic_add_gnu_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_add_gnu_grey.png b/res/drawable-xxhdpi/ic_add_gnu_grey.png
new file mode 100644
index 0000000..b16ea9f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_add_gnu_grey.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_add_gnu_grey.png b/res/drawable-xxxhdpi/ic_add_gnu_grey.png
new file mode 100644
index 0000000..6fc56a4
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_add_gnu_grey.png
Binary files differ
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 065515a..be3e2b8 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -36,13 +36,13 @@
 
     <!-- Settings screen should use the same colors as the Dialer -->
     <color name="phone_settings_background_color">#f5f5f5</color>
-    <!-- Action bar text color.  Ensure this stays in sync with Dialer actionbar_text_color. -->
-    <color name="phone_settings_actionbar_text_color">#FFFFFF</color>
+    <!-- Action bar text color.  Ensure this stays in sync with dialer_icon_color in action bar. -->
+    <color name="phone_settings_actionbar_text_color">#5f6368</color>
     <!-- Background color of action bars.  Ensure this stays in sync with Dialer
          actionbar_background_color. -->
-    <color name="actionbar_background_color">#fafafa</color>
+    <color name="actionbar_background_color">#ffffff</color>
     <!-- Dark variant of the action bar color.  Ensure this stays in sync with Dialer version. -->
-    <color name="actionbar_background_color_dark">#fafafa</color>
+    <color name="actionbar_background_color_dark">#ffffff</color>
     <!-- Color for icons in the actionbar. Ensure this stays in sync with Dialer version. -->
     <color name="actionbar_icon_color">#ffffff</color>
 
@@ -58,7 +58,7 @@
     <color name="emergency_shortcut_confirm_button_background_color">#E25142</color>
 
     <!-- Color matches dialer settings light M2 theme.-->
-    <color name="dialer_background_color">#fafafa</color>
+    <color name="dialer_background_color">#ffffff</color>
     <color name="dialer_divider_color">#d8d8d8</color>
     <color name="dialer_primary_text_color">#202124</color>
     <color name="dialer_secondary_text_color">#5f6368</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d2845ae..e4588c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1764,6 +1764,10 @@
     <!-- In-call screen: error message shown when the user attempts to place a call, but the network
          does not have enough resources (e.g. it is busy) and the call cannot be placed. -->
     <string name="callFailed_NetworkBusy">Network is busy.  Please try your call again later.</string>
+    <!-- In-call screen: error message shown when the user attempts to place a call, but the network
+         does not have enough resources (e.g. it is congested) and the call cannot be placed. -->
+    <string name="callFailed_NetworkCongested">Network is congested.  Contact your mobile operator
+    for assistance.</string>
     <!-- Message displayed to the user when an outgoing call is deflected.  This means that the
          party the user is calling has chosen to send the call to another phone number. -->
     <string name="supp_service_notification_call_deflected">Call deflected.</string>
diff --git a/sip/src/com/android/services/telephony/sip/SipSettings.java b/sip/src/com/android/services/telephony/sip/SipSettings.java
index 0d87798..ded16df 100644
--- a/sip/src/com/android/services/telephony/sip/SipSettings.java
+++ b/sip/src/com/android/services/telephony/sip/SipSettings.java
@@ -39,6 +39,8 @@
 import android.view.Menu;
 import android.view.MenuItem;
 
+import com.android.phone.R;
+
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Comparator;
@@ -46,8 +48,6 @@
 import java.util.List;
 import java.util.Map;
 
-import com.android.phone.R;
-
 /**
  * The PreferenceActivity class for managing sip profile preferences.
  */
@@ -410,7 +410,7 @@
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
         MenuItem addAccountMenuItem = menu.add(0, MENU_ADD_ACCOUNT, 0, R.string.add_sip_account);
-        addAccountMenuItem.setIcon(R.drawable.ic_add_24dp);
+        addAccountMenuItem.setIcon(R.drawable.ic_add_gnu_grey);
         addAccountMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         return true;
     }
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 137d3d1..6a3e928 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -324,7 +324,7 @@
                     final String carrierPackageName = getCarrierPackageForPhoneId(phoneId);
                     if (carrierPackageName != null) {
                         log("Found carrier config app: " + carrierPackageName);
-                        sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId));
+                        sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId, -1));
                     } else {
                         broadcastConfigChangedIntent(phoneId);
                     }
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index cff27b1..38eb40d 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -851,7 +851,7 @@
             phoneToMakeCall = mShortcutViewConfig.getPhoneInfo();
         } else {
             TelephonyManager tm = getSystemService(TelephonyManager.class);
-            isEmergencyNumber = tm.isCurrentEmergencyNumber(mLastNumber);
+            isEmergencyNumber = tm.isEmergencyNumber(mLastNumber);
         }
 
         if (isEmergencyNumber) {
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/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 46f99e2..9444c1d 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) {
@@ -2786,6 +2797,22 @@
     }
 
     @Override
+    public boolean isInEmergencySmsMode() {
+        enforceReadPrivilegedPermission("isInEmergencySmsMode");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            for (Phone phone : PhoneFactory.getPhones()) {
+                if (phone.isInEmergencySmsMode()) {
+                    return true;
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return false;
+    }
+
+    @Override
     public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
             throws RemoteException {
         enforceReadPrivilegedPermission("registerImsRegistrationCallback");
@@ -3656,13 +3683,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 +3734,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 +3748,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 +3780,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 +3834,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 +3876,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 +4135,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 +4155,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 +4177,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 +4199,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 +4212,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 +4232,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 +4269,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 +4297,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);
         }
@@ -4393,18 +4540,23 @@
     }
 
     /**
-     * Check whether DUN APN is required for tethering.
+     * Check whether DUN APN is required for tethering with subId.
      *
+     * @param subId the id of the subscription to require tethering.
      * @return {@code true} if DUN APN is required for tethering.
      * @hide
      */
     @Override
-    public boolean getTetherApnRequired() {
+    public boolean getTetherApnRequiredForSubscriber(int subId) {
         enforceModifyPermission();
         final long identity = Binder.clearCallingIdentity();
-        final Phone defaultPhone = getDefaultPhone();
+        final Phone phone = getPhone(subId);
         try {
-            return defaultPhone.hasMatchedTetherApnSetting();
+            if (phone != null) {
+                return phone.hasMatchedTetherApnSetting();
+            } else {
+                return false;
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5182,11 +5334,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 +6587,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 +6611,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 +6722,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 +6736,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 +6798,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 7e24c7a..8e5ab42 100644
--- a/src/com/android/phone/ShortcutViewUtils.java
+++ b/src/com/android/phone/ShortcutViewUtils.java
@@ -303,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/SpecialCharSequenceMgr.java b/src/com/android/phone/SpecialCharSequenceMgr.java
index 5a5d488..514b2c9 100644
--- a/src/com/android/phone/SpecialCharSequenceMgr.java
+++ b/src/com/android/phone/SpecialCharSequenceMgr.java
@@ -23,12 +23,19 @@
 import android.content.Intent;
 import android.provider.Settings;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.view.WindowManager;
 
+import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyCapabilities;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Helper class to listen for some magic dialpad character sequences
  * that are handled specially by the Phone app.
@@ -185,6 +192,40 @@
         return false;
     }
 
+    private static IccCardConstants.State getSimState(int slotId, Context context) {
+        final TelephonyManager tele = TelephonyManager.from(context);
+        int simState =  tele.getSimState(slotId);
+        IccCardConstants.State state;
+        try {
+            state = IccCardConstants.State.intToState(simState);
+        } catch (IllegalArgumentException ex) {
+            Log.w(TAG, "Unknown sim state: " + simState);
+            state = IccCardConstants.State.UNKNOWN;
+        }
+        return state;
+    }
+
+    private static int getNextSubIdForState(IccCardConstants.State state, Context context) {
+        SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
+        List<SubscriptionInfo> list = subscriptionManager.getActiveSubscriptionInfoList();
+        if (list == null) {
+            // getActiveSubscriptionInfoList was null callers expect an empty list.
+            list = new ArrayList<>();
+        }
+        int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
+        for (int i = 0; i < list.size(); i++) {
+            final SubscriptionInfo info = list.get(i);
+            final int id = info.getSubscriptionId();
+            if (state == getSimState(info.getSimSlotIndex(), context)
+                    && bestSlotId > info.getSimSlotIndex()) {
+                resultId = id;
+                bestSlotId = info.getSimSlotIndex();
+            }
+        }
+        return resultId;
+    }
+
     static private boolean handlePinEntry(Context context, String input,
                                           Activity pukInputActivity) {
         // TODO: The string constants here should be removed in favor
@@ -193,7 +234,20 @@
         if ((input.startsWith("**04") || input.startsWith("**05"))
                 && input.endsWith("#")) {
             PhoneGlobals app = PhoneGlobals.getInstance();
-            Phone phone = PhoneGlobals.getPhone();
+            Phone phone;
+            int subId;
+            if (input.startsWith("**04")) {
+                subId = getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED, context);
+            } else {
+                subId = getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED, context);
+            }
+            if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                log("get phone with subId: " + subId);
+                phone = PhoneGlobals.getPhone(subId);
+            } else {
+                log("get default phone");
+                phone = PhoneGlobals.getPhone();
+            }
             boolean isMMIHandled = phone.handlePinMmi(input);
 
             // if the PUK code is recognized then indicate to the
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 8ef9565..e3155f3 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -253,6 +253,10 @@
                 resourceId = R.string.callFailed_NetworkBusy;
                 break;
 
+            case android.telephony.DisconnectCause.IMS_ACCESS_BLOCKED:
+                resourceId = R.string.callFailed_NetworkCongested;
+                break;
+
             case android.telephony.DisconnectCause.CONGESTION:
                 resourceId = R.string.callFailed_congestion;
                 break;
@@ -565,6 +569,10 @@
                 resourceId = R.string.callFailed_NetworkBusy;
                 break;
 
+            case android.telephony.DisconnectCause.IMS_ACCESS_BLOCKED:
+                resourceId = R.string.callFailed_NetworkCongested;
+                break;
+
             case android.telephony.DisconnectCause.FDN_BLOCKED:
                 resourceId = R.string.callFailed_fdn_only;
                 break;
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index fce4dfe..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());
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");
     }