Merge "Fix issue that the carrier configs are not updated after SIM unlocked"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 30760dc..c2f88c5 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -214,7 +214,8 @@
         <activity android:name="EmergencyDialer"
             android:label="@string/emergencyDialerIconLabel"
             android:theme="@style/EmergencyDialerTheme"
-            android:screenOrientation="portrait">
+            android:screenOrientation="portrait"
+            android:resizeableActivity="false">
             <intent-filter>
                 <action android:name="com.android.phone.EmergencyDialer.DIAL" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index 54be16b..403cad7 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -808,7 +808,7 @@
 countries {
   iso_code: "GB"
   eccs {
-    phone_number: "112"
+    phone_number: "999"
     types: POLICE
     types: AMBULANCE
     types: FIRE
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index 2d0165a..679bc36 100644
--- a/ecc/output/eccdata
+++ b/ecc/output/eccdata
Binary files differ
diff --git a/res/layout/emergency_shortcut_buttons_group.xml b/res/layout/emergency_shortcut_buttons_group.xml
index bafedd1..7911f30 100644
--- a/res/layout/emergency_shortcut_buttons_group.xml
+++ b/res/layout/emergency_shortcut_buttons_group.xml
@@ -38,7 +38,8 @@
                 android:ellipsize="end"
                 android:lineHeight="@dimen/emergency_number_title_line_height"
                 android:fontFamily="sans-serif-medium"
-                android:textAppearance="@style/SubtitleTextAppearance"
+                android:textColor="@android:color/white"
+                android:textSize="@dimen/emergency_number_title_text_size"
                 android:text="@string/single_emergency_number_title"/>
         </FrameLayout>
         <LinearLayout
@@ -63,7 +64,8 @@
                 android:maxLines="2"
                 android:ellipsize="end"
                 android:lineHeight="@dimen/location_text_line_height"
-                android:textAppearance="@style/SubtitleTextAppearance"/>
+                android:textColor="@android:color/white"
+                android:textSize="@dimen/emergency_location_text_size"/>
         </LinearLayout>
     </FrameLayout>
     <LinearLayout
diff --git a/res/values-sw345dp/dimens.xml b/res/values-sw345dp/dimens.xml
new file mode 100644
index 0000000..84db80b
--- /dev/null
+++ b/res/values-sw345dp/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <dimen name="emergency_info_button_height">88dp</dimen>
+    <dimen name="emergency_info_button_margin_vertical">48dp</dimen>
+    <dimen name="emergency_shortcut_button_height">88dp</dimen>
+    <dimen name="emergency_number_title_text_size">12sp</dimen>
+    <dimen name="emergency_location_text_size">12sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-sw360dp/dimens.xml b/res/values-sw360dp/dimens.xml
new file mode 100644
index 0000000..c578065
--- /dev/null
+++ b/res/values-sw360dp/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <dimen name="emergency_info_button_height">96dp</dimen>
+    <dimen name="emergency_info_button_margin_vertical">56dp</dimen>
+    <dimen name="emergency_shortcut_button_height">96dp</dimen>
+    <dimen name="emergency_number_title_text_size">14sp</dimen>
+    <dimen name="emergency_location_text_size">14sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b657e64..38241de 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -128,8 +128,8 @@
     <dimen name="emergency_number_title_group_padding_horizontal">16dp</dimen>
 
     <!-- Height and vertical margin for the emergency information button. -->
-    <dimen name="emergency_info_button_height">96dp</dimen>
-    <dimen name="emergency_info_button_margin_vertical">56dp</dimen>
+    <dimen name="emergency_info_button_height">80dp</dimen>
+    <dimen name="emergency_info_button_margin_vertical">40dp</dimen>
     <dimen name="emergency_info_button_fix_margin_vertical">40dp</dimen>
 
     <!-- Margin for the emergency information button text. -->
@@ -155,7 +155,7 @@
     <dimen name="location_image_width">16dp</dimen>
 
     <!-- The height for button of emergency shortcut. -->
-    <dimen name="emergency_shortcut_button_height">96dp</dimen>
+    <dimen name="emergency_shortcut_button_height">80dp</dimen>
 
     <!-- The height and width for the circle image of phone number type.-->
     <dimen name="phone_number_type_circle_image_height">40dp</dimen>
@@ -197,4 +197,9 @@
     <!-- The width for emergency number title container.-->
     <dimen name="emergency_number_title_container_width">210dp</dimen>
 
+    <!-- The text size for emergency number title.-->
+    <dimen name="emergency_number_title_text_size">13sp</dimen>
+
+    <!-- The text size for emergency location.-->
+    <dimen name="emergency_location_text_size">13sp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7fe534c..d6c5fd7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1804,7 +1804,11 @@
     <!-- Message displayed to the user to indicate that a held call has been released /
          disconnected. -->
     <string name="supp_service_held_call_released">Held call has been released.</string>
-
+    <!-- In-call screen: error message shown when the user attempts to place a call, but the device
+         is currently in the process of being provisioned for service.  Provisioning is the process
+         by which a device confirms which services are available to the user by contacting the
+         mobile service provider. -->
+    <string name="callFailed_otasp_provisioning_in_process">Cannot place a call as the device is currently being provisioned.</string>
     <!-- In-call screen: error message shown when the user has attempted to place a new outgoing
          call, but there is already a call in dialing state. -->
     <string name="callFailed_already_dialing">Cannot place a call as another outgoing call is already dialing.</string>
diff --git a/src/com/android/phone/CLIRListPreference.java b/src/com/android/phone/CLIRListPreference.java
old mode 100644
new mode 100755
index b3ff171..5c6132b
--- a/src/com/android/phone/CLIRListPreference.java
+++ b/src/com/android/phone/CLIRListPreference.java
@@ -7,6 +7,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.preference.ListPreference;
+import android.telephony.CarrierConfigManager;
 import android.util.AttributeSet;
 import android.util.Log;
 
@@ -26,6 +27,12 @@
     private Phone mPhone;
     private TimeConsumingPreferenceListener mTcpListener;
 
+    private final String[] mEntries = getContext().getResources()
+            .getStringArray(R.array.clir_display_values);
+    private final String[] mValues = getContext().getResources()
+            .getStringArray(R.array.clir_values);
+    private boolean mConfigSupportNetworkDefault;
+
     int clirArray[];
 
     public CLIRListPreference(Context context, AttributeSet attrs) {
@@ -40,7 +47,7 @@
     protected void onDialogClosed(boolean positiveResult) {
         super.onDialogClosed(positiveResult);
 
-        mPhone.setOutgoingCallerIdDisplay(findIndexOfValue(getValue()),
+        mPhone.setOutgoingCallerIdDisplay(convertValueToCLIRMode(getValue()),
                 mHandler.obtainMessage(MyHandler.MESSAGE_SET_CLIR));
         if (mTcpListener != null) {
             mTcpListener.onStarted(this, false);
@@ -51,6 +58,19 @@
             TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) {
         mPhone = phone;
         mTcpListener = listener;
+        mConfigSupportNetworkDefault = PhoneGlobals.getInstance()
+                .getCarrierConfigForSubId(mPhone.getSubId())
+                .getBoolean(CarrierConfigManager.KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL);
+        // When "Network default" is not supported, create entries with remaining two values.
+        if (!mConfigSupportNetworkDefault) {
+            String[] noNetworkDefaultEntries = {mEntries[CommandsInterface.CLIR_INVOCATION],
+                    mEntries[CommandsInterface.CLIR_SUPPRESSION]};
+            String[] noNetworkDefaultValues = {mValues[CommandsInterface.CLIR_INVOCATION],
+                    mValues[CommandsInterface.CLIR_SUPPRESSION]};
+            setEntries(noNetworkDefaultEntries);
+            setEntryValues(noNetworkDefaultValues);
+        }
+
         if (!skipReading) {
             Log.i(LOG_TAG, "init: requesting CLIR");
             mPhone.getOutgoingCallerIdDisplay(mHandler.obtainMessage(MyHandler.MESSAGE_GET_CLIR,
@@ -92,7 +112,10 @@
                 value = CommandsInterface.CLIR_DEFAULT;
                 break;
         }
-        setValueIndex(value);
+        value = (!mConfigSupportNetworkDefault && value == CommandsInterface.CLIR_DEFAULT)
+                ? CommandsInterface.CLIR_SUPPRESSION : value;
+
+        setValue(mValues[value]);
 
         // set the string summary to reflect the value
         int summary = R.string.sum_default_caller_id;
@@ -110,6 +133,25 @@
         setSummary(summary);
     }
 
+    /**
+     * When "Network default" is hidden, UI list index(0-1) doesn't match CLIR Mode(0-2 for Modem).
+     * In order to send request to Modem, it is necessary to convert value to CLIR Mode.
+     * ("Hide" = CommandsInterface.CLIR_INVOCATION, "Show" = CommandsInterface.CLIR_SUPPRESSION)
+     *
+     * @param String of entry value.
+     * @return "CommandInterface.CLIR_*" for Modem.
+     */
+    private int convertValueToCLIRMode(String value) {
+        if (mValues[CommandsInterface.CLIR_INVOCATION].equals(value)) {
+            return CommandsInterface.CLIR_INVOCATION;
+        } else if (mValues[CommandsInterface.CLIR_SUPPRESSION].equals(value)) {
+            return CommandsInterface.CLIR_SUPPRESSION;
+        } else {
+            return mConfigSupportNetworkDefault ? CommandsInterface.CLIR_DEFAULT :
+                    CommandsInterface.CLIR_SUPPRESSION;
+        }
+    }
+
     private class MyHandler extends Handler {
         static final int MESSAGE_GET_CLIR = 0;
         static final int MESSAGE_SET_CLIR = 1;
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 8c1436e..8194c60 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -93,6 +93,8 @@
     private PersistableBundle[] mConfigFromDefaultApp;
     // Carrier configs from privileged carrier config app, indexed by phoneID.
     private PersistableBundle[] mConfigFromCarrierApp;
+    // Carrier configs that are provided via the override test API, indexed by phone ID.
+    private PersistableBundle[] mOverrideConfigs;
     // Service connection for binding to config app.
     private CarrierServiceConnection[] mServiceConnection;
     // Whether we have sent config change bcast for each phone id.
@@ -493,6 +495,7 @@
         int numPhones = TelephonyManager.from(context).getPhoneCount();
         mConfigFromDefaultApp = new PersistableBundle[numPhones];
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
+        mOverrideConfigs = new PersistableBundle[numPhones];
         mServiceConnection = new CarrierServiceConnection[numPhones];
         mHasSentConfigChange = new boolean[numPhones];
         // Make this service available through ServiceManager.
@@ -820,9 +823,8 @@
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_DO_FETCH_DEFAULT, phoneId, -1));
     }
 
-    @Override public
-    @NonNull
-    PersistableBundle getConfigForSubId(int subId, String callingPackage) {
+    @Override
+    public @NonNull PersistableBundle getConfigForSubId(int subId, String callingPackage) {
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                 mContext, subId, callingPackage, "getCarrierConfig")) {
             return new PersistableBundle();
@@ -841,11 +843,39 @@
                 retConfig.putAll(config);
                 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
             }
+            config = mOverrideConfigs[phoneId];
+            if (config != null) {
+                retConfig.putAll(config);
+                retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+            }
         }
         return retConfig;
     }
 
     @Override
+    public void overrideConfig(int subscriptionId, PersistableBundle overrides) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_PHONE_STATE, null);
+        int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
+            log("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
+            return;
+        }
+
+        if (overrides == null) {
+            mOverrideConfigs[phoneId] = new PersistableBundle();
+            return;
+        }
+
+        if (mOverrideConfigs[phoneId] == null) {
+            mOverrideConfigs[phoneId] = overrides;
+        } else {
+            mOverrideConfigs[phoneId].putAll(overrides);
+        }
+        broadcastConfigChangedIntent(phoneId);
+    }
+
+    @Override
     public void notifyConfigChangedForSubId(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
@@ -919,6 +949,8 @@
             pw.println("");
             // display ConfigFromCarrierApp
             printConfig(mConfigFromCarrierApp[i], pw, "mConfigFromCarrierApp");
+            pw.println("");
+            printConfig(mOverrideConfigs[i], pw, "mOverrideConfigs");
         }
     }
 
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 1fbbd33..cb12cbb 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -62,7 +62,6 @@
 import android.text.TextWatcher;
 import android.text.method.DialerKeyListener;
 import android.text.style.TtsSpan;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
@@ -348,8 +347,25 @@
         // Allow turning screen on
         setTurnScreenOn(true);
 
-        mAreEmergencyDialerShortcutsEnabled = FeatureFlagUtils
-                .isEnabled(this, FeatureFlagUtils.EMERGENCY_DIAL_SHORTCUTS);
+        CarrierConfigManager configMgr = getSystemService(CarrierConfigManager.class);
+        PersistableBundle carrierConfig =
+                configMgr.getConfigForSubId(SubscriptionManager.getDefaultVoiceSubscriptionId());
+
+        // Disable emergency dialer shortcut when can't get the location information or inserting
+        // the SIM of the blacklisted carrier.
+        boolean isSupport = carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL);
+        Log.d(LOG_TAG, "Is the carrier supported: " + isSupport);
+        TelephonyManager tm = getSystemService(TelephonyManager.class);
+        String countryIso = tm.getNetworkCountryIso();
+        mAreEmergencyDialerShortcutsEnabled = false;
+        if (isSupport && !TextUtils.isEmpty(countryIso)) {
+            if (EccInfoHelper.isCountryEccInfoAvailable(this, countryIso)) {
+                mAreEmergencyDialerShortcutsEnabled = true;
+            } else {
+                Log.d(LOG_TAG, "ECC info is unavailable. Disable emergency dialer shortcut.");
+            }
+        }
         Log.d(LOG_TAG, "Enable emergency dialer shortcut: "
                 + mAreEmergencyDialerShortcutsEnabled);
 
@@ -400,11 +416,6 @@
         // Check whether we should show the onscreen "Dial" button and co.
         // Read carrier config through the public API because PhoneGlobals is not available when we
         // run as a secondary user.
-        CarrierConfigManager configMgr =
-                (CarrierConfigManager) getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        PersistableBundle carrierConfig =
-                configMgr.getConfigForSubId(SubscriptionManager.getDefaultVoiceSubscriptionId());
-
         if (carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL)) {
             mDialButton.setOnClickListener(this);
         } else {
@@ -451,7 +462,7 @@
         mEmergencyInfoGroup = (EmergencyInfoGroup) findViewById(R.id.emergency_info_button);
 
         if (mAreEmergencyDialerShortcutsEnabled) {
-            mEccInfoHelper = new EccInfoHelper(new IsoToEccProtobufRepository());
+            mEccInfoHelper = new EccInfoHelper(IsoToEccProtobufRepository.getInstance());
             setupEmergencyShortcutsView();
         }
     }
@@ -921,7 +932,7 @@
         AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
         int ringerMode = audioManager.getRingerMode();
         if ((ringerMode == AudioManager.RINGER_MODE_SILENT)
-            || (ringerMode == AudioManager.RINGER_MODE_VIBRATE)) {
+                || (ringerMode == AudioManager.RINGER_MODE_VIBRATE)) {
             return;
         }
 
@@ -1047,8 +1058,8 @@
                 boolean isCellAvailable =
                         ss.getRilVoiceRadioTechnology() != RIL_RADIO_TECHNOLOGY_UNKNOWN;
                 Log.i(LOG_TAG, "showWfcWarningTask: isWfcAvailable=" + isWfcAvailable
-                                + " isCellAvailable=" + isCellAvailable
-                                + "(rat=" + ss.getRilVoiceRadioTechnology() + ")");
+                        + " isCellAvailable=" + isCellAvailable
+                        + "(rat=" + ss.getRilVoiceRadioTechnology() + ")");
                 return isWfcAvailable && !isCellAvailable;
             }
 
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 28b6497..125c01a 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -424,7 +424,7 @@
         CdmaOptions mCdmaOptions;
 
         private Preference mClickedPreference;
-        private boolean mShow4GForLTE = true;
+        private boolean mShow4GForLTE = false;
         private boolean mIsGlobalCdma;
         private boolean mOnlyAutoSelectInHomeNW;
         private boolean mUnavailable;
@@ -1209,7 +1209,7 @@
             final int phoneType = mTelephonyManager.getPhoneType();
             final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
             mShow4GForLTE = carrierConfig != null ? carrierConfig.getBoolean(
-                    CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL) : true;
+                    CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL) : false;
             if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                 final int lteForced = android.provider.Settings.Global.getInt(
                         getContext().getContentResolver(),
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
index d0ab87a..9b905b4 100644
--- a/src/com/android/phone/NetworkSelectSetting.java
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -84,7 +84,7 @@
     private NetworkOperatorPreference mSelectedNetworkOperatorPreference;
     private TelephonyManager mTelephonyManager;
     private List<String> mForbiddenPlmns;
-    private boolean mShow4GForLTE = true;
+    private boolean mShow4GForLTE = false;
     private NetworkScanHelper mNetworkScanHelper;
     private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
 
@@ -417,7 +417,6 @@
 
                 mConnectedNetworkOperatorsPreference.addPreference(pref);
             } else {
-                loge("Invalid CellIfno: " + cellInfo.toString());
                 // Remove the connected network operators category
                 removeConnectedNetworkOperatorPreference();
             }
diff --git a/src/com/android/phone/PhoneApp.java b/src/com/android/phone/PhoneApp.java
index df151bf..333e0ec 100644
--- a/src/com/android/phone/PhoneApp.java
+++ b/src/com/android/phone/PhoneApp.java
@@ -19,6 +19,7 @@
 import android.app.Application;
 import android.os.UserHandle;
 
+import com.android.phone.ecc.IsoToEccProtobufRepository;
 import com.android.services.telephony.TelecomAccountRegistry;
 
 /**
@@ -40,5 +41,10 @@
 
             TelecomAccountRegistry.getInstance(this).setupOnBoot();
         }
+
+        new Thread(() -> {
+            // Preload ECC table in background.
+            IsoToEccProtobufRepository.getInstance().loadMappingTable(PhoneApp.this);
+        }).start();
     }
 }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 4e47bda..6ce8784 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -78,6 +78,7 @@
 import android.telephony.UssdResponse;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.cdma.CdmaCellLocation;
+import android.telephony.emergency.EmergencyNumber;
 import android.telephony.gsm.GsmCellLocation;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
@@ -116,6 +117,8 @@
 import com.android.internal.telephony.RIL;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.SmsApplication;
+import com.android.internal.telephony.SmsApplication.SmsApplicationData;
 import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.euicc.EuiccConnector;
@@ -139,6 +142,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -166,8 +170,8 @@
     private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
     private static final int CMD_NV_WRITE_CDMA_PRL = 17;
     private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
-    private static final int CMD_NV_RESET_CONFIG = 19;
-    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
+    private static final int CMD_RESET_MODEM_CONFIG = 19;
+    private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
     private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
     private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
     private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
@@ -211,6 +215,8 @@
     private static final int EVENT_GET_ALL_CELL_INFO_DONE = 61;
     private static final int CMD_GET_CELL_LOCATION = 62;
     private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
+    private static final int CMD_MODEM_REBOOT = 64;
+    private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -649,14 +655,14 @@
                     handleNullReturnEvent(msg, "nvWriteCdmaPrl");
                     break;
 
-                case CMD_NV_RESET_CONFIG:
+                case CMD_RESET_MODEM_CONFIG:
                     request = (MainThreadRequest) msg.obj;
-                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
-                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
+                    onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
+                    mPhone.resetModemConfig(onCompleted);
                     break;
 
-                case EVENT_NV_RESET_CONFIG_DONE:
-                    handleNullReturnEvent(msg, "nvResetConfig");
+                case EVENT_RESET_MODEM_CONFIG_DONE:
+                    handleNullReturnEvent(msg, "resetModemConfig");
                     break;
 
                 case CMD_GET_PREFERRED_NETWORK_TYPE:
@@ -1037,6 +1043,16 @@
                     break;
                 }
 
+                case CMD_MODEM_REBOOT:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
+                    mPhone.rebootModem(onCompleted);
+                    break;
+
+                case EVENT_CMD_MODEM_REBOOT_DONE:
+                    handleNullReturnEvent(msg, "rebootModem");
+                    break;
+
                 default:
                     Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
                     break;
@@ -2042,6 +2058,17 @@
         }
     }
 
+    @Override
+    public int getSubscriptionMNOCarrierId(int subId) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final Phone phone = getPhone(subId);
+            return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID : phone.getMNOCarrierId();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     //
     // Internal helper methods.
     //
@@ -3353,26 +3380,56 @@
     }
 
     /**
-     * Perform the specified type of NV config reset.
+     * Rollback modem configurations to factory default except some config which are in whitelist.
      * Used for device configuration by some CDMA operators.
      *
-     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
+     * @param slotIndex - device slot.
+     *
      * @return true on success; false on any failure
      */
     @Override
-    public boolean nvResetConfig(int resetType) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, getDefaultSubscription(), "nvResetConfig");
+    public boolean resetModemConfig(int slotIndex) {
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone != null) {
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, phone.getSubId(), "resetModemConfig");
 
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            if (DBG) log("nvResetConfig: type " + resetType);
-            Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
-            if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
-            return success;
-        } finally {
-            Binder.restoreCallingIdentity(identity);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
+                if (DBG) log("resetModemConfig:" + ' ' + (success ? "ok" : "fail"));
+                return success;
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
         }
+        return false;
+    }
+
+    /**
+     * Generate a radio modem reset. Used for device configuration by some CDMA operators.
+     *
+     * @param slotIndex - device slot.
+     *
+     * @return true on success; false on any failure
+     */
+    @Override
+    public boolean rebootModem(int slotIndex) {
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone != null) {
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, phone.getSubId(), "rebootModem");
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
+                if (DBG) log("rebootModem:" + ' ' + (success ? "ok" : "fail"));
+                return success;
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+        return false;
     }
 
     public String[] getPcscfAddress(String apnType, String callingPackage) {
@@ -3736,7 +3793,7 @@
 
     /**
      * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
-     * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
+     * SystemProperty to decide whether DUN APN is required for
      * tethering.
      *
      * @return 0: Not required. 1: required. 2: Not set.
@@ -3750,8 +3807,7 @@
         try {
             int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
                     Settings.Global.TETHER_DUN_REQUIRED, 2);
-            // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
-            // config_tether_apndata.
+            // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting
             if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
                 dunRequired = 1;
             }
@@ -4266,21 +4322,20 @@
     @Override
     public int getRadioAccessFamily(int phoneId, String callingPackage) {
         Phone phone = PhoneFactory.getPhone(phoneId);
+        int raf = RadioAccessFamily.RAF_UNKNOWN;
         if (phone == null) {
-            return RadioAccessFamily.RAF_UNKNOWN;
+            return raf;
         }
-        int subId = phone.getSubId();
-        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                mApp, subId, callingPackage, "getRadioAccessFamily")) {
-            return RadioAccessFamily.RAF_UNKNOWN;
-        }
-
         final long identity = Binder.clearCallingIdentity();
         try {
-            return ProxyController.getInstance().getRadioAccessFamily(phoneId);
+            TelephonyPermissions
+                    .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                            mApp, phone.getSubId(), "getRadioAccessFamily");
+            raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
+        return raf;
     }
 
     @Override
@@ -4370,7 +4425,14 @@
         }
     }
 
-    public boolean isRttSupported() {
+    /**
+     * Determines whether the device currently supports RTT (Real-time text). Based both on carrier
+     * support for the feature and device firmware support.
+     *
+     * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
+     */
+    @Override
+    public boolean isRttSupported(int subscriptionId) {
         final long identity = Binder.clearCallingIdentity();
         try {
             boolean isCarrierSupported = mApp.getCarrierConfigForSubId(
@@ -4384,10 +4446,14 @@
         }
     }
 
-    public boolean isRttEnabled() {
+    /**
+     * Determines whether the user has turned on RTT. Only returns true if the device and carrier
+     * both also support RTT.
+     */
+    public boolean isRttEnabled(int subscriptionId) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            return isRttSupported() && Settings.Secure.getInt(
+            return isRttSupported(subscriptionId) && Settings.Secure.getInt(
                     mPhone.getContext().getContentResolver(),
                     Settings.Secure.RTT_CALLING_MODE, 0) != 0;
         } finally {
@@ -5619,4 +5685,106 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void ensureUserRunning(int userId) {
+        if (!mUserManager.isUserRunning(userId)) {
+            throw new IllegalStateException("User " + userId + " does not exist or not running");
+        }
+    }
+
+    /**
+     * Returns a list of SMS apps on a given user.
+     *
+     * Only the shell user (UID 2000 or 0) can call it.
+     * Target user must be running.
+     */
+    @Override
+    public String[] getSmsApps(int userId) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getSmsApps");
+        ensureUserRunning(userId);
+
+        final Collection<SmsApplicationData> apps =
+                SmsApplication.getApplicationCollectionAsUser(mApp, userId);
+
+        String[] ret = new String[apps.size()];
+        int i = 0;
+        for (SmsApplicationData app : apps) {
+            ret[i++] = app.mPackageName;
+        }
+        return ret;
+    }
+
+    /**
+     * Returns the default SMS app package name on a given user.
+     *
+     * Only the shell user (UID 2000 or 0) can call it.
+     * Target user must be running.
+     */
+    @Override
+    public String getDefaultSmsApp(int userId) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDefaultSmsApp");
+        ensureUserRunning(userId);
+
+        final ComponentName cn = SmsApplication.getDefaultSmsApplicationAsUser(mApp,
+                /* updateIfNeeded= */ true, userId);
+        return cn == null ? null : cn.getPackageName();
+    }
+
+    /**
+     * Set a package as the default SMS app on a given user.
+     *
+     * Only the shell user (UID 2000 or 0) can call it.
+     * Target user must be running.
+     */
+    @Override
+    public void setDefaultSmsApp(int userId, String packageName) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDefaultSmsApp");
+        ensureUserRunning(userId);
+
+        boolean found = false;
+        for (String pkg : getSmsApps(userId)) {
+            if (TextUtils.equals(packageName, pkg)) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Package " + packageName + " is not an SMS app");
+        }
+
+        SmsApplication.setDefaultApplicationAsUser(packageName, mApp, userId);
+    }
+
+    @Override
+    public Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList(
+            String callingPackage) {
+        // TODO connect with internal content
+        return null;
+    }
+
+    @Override
+    public boolean isCurrentEmergencyNumber(String number) {
+        // TODO connect with internal content
+        return false;
+    }
+
+    @Override
+    public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
+        enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
+        Phone phone = getPhone(subId);
+        if (phone == null) {
+            return null;
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            UiccProfile profile = UiccController.getInstance()
+                    .getUiccProfileForPhone(phone.getPhoneId());
+            if (profile != null) {
+                return profile.getCertsFromCarrierPrivilegeAccessRules();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 4acb46b..1a25ae3 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -18,6 +18,7 @@
 
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.os.UserHandle;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
 
@@ -39,11 +40,16 @@
     private static final int DEFAULT_PHONE_ID = 0;
 
     private static final String IMS_SUBCOMMAND = "ims";
+    private static final String SMS_SUBCOMMAND = "sms";
     private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service";
     private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
     private static final String IMS_ENABLE = "enable";
     private static final String IMS_DISABLE = "disable";
 
+    private static final String SMS_GET_APPS = "get-apps";
+    private static final String SMS_GET_DEFAULT_APP = "get-default-app";
+    private static final String SMS_SET_DEFAULT_APP = "set-default-app";
+
     // Take advantage of existing methods that already contain permissions checks when possible.
     private final ITelephony mInterface;
 
@@ -61,6 +67,9 @@
             case IMS_SUBCOMMAND: {
                 return handleImsCommand();
             }
+            case SMS_SUBCOMMAND: {
+                return handleSmsCommand();
+            }
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -75,7 +84,10 @@
         pw.println("    Print this help text.");
         pw.println("  ims");
         pw.println("    IMS Commands.");
+        pw.println("  sms");
+        pw.println("    SMS Commands.");
         onHelpIms();
+        onHelpSms();
     }
 
     private void onHelpIms() {
@@ -103,6 +115,17 @@
         pw.println("    slot if none is specified.");
     }
 
+    private void onHelpSms() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("SMS Commands:");
+        pw.println("  sms get-apps [--user USER_ID]");
+        pw.println("    Print all SMS apps on a user.");
+        pw.println("  sms get-default-app [--user USER_ID]");
+        pw.println("    Get the default SMS app.");
+        pw.println("  sms set-default-app [--user USER_ID] PACKAGE_NAME");
+        pw.println("    Set PACKAGE_NAME as the default SMS app.");
+    }
+
     private int handleImsCommand() {
         String arg = getNextArg();
         if (arg == null) {
@@ -296,4 +319,85 @@
         }
         return slotId;
     }
+
+    private int handleSmsCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpSms();
+            return 0;
+        }
+
+        try {
+            switch (arg) {
+                case SMS_GET_APPS: {
+                    return handleSmsGetApps();
+                }
+                case SMS_GET_DEFAULT_APP: {
+                    return handleSmsGetDefaultApp();
+                }
+                case SMS_SET_DEFAULT_APP: {
+                    return handleSmsSetDefaultApp();
+                }
+                default:
+                    getErrPrintWriter().println("Unknown command " + arg);
+            }
+        } catch (RemoteException e) {
+            getErrPrintWriter().println("RemoteException: " + e.getMessage());
+        }
+
+        return -1;
+    }
+
+    private int maybeParseUserIdArg() {
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user": {
+                    try {
+                        userId = Integer.parseInt(getNextArgRequired());
+                    } catch (NumberFormatException e) {
+                        getErrPrintWriter().println("Invalid user ID for --user");
+                        return -1;
+                    }
+                    break;
+                }
+            }
+        }
+        return userId;
+    }
+
+    private int handleSmsGetApps() throws RemoteException {
+        final int userId = maybeParseUserIdArg();
+        if (userId < 0) {
+            return -1;
+        }
+
+        for (String packageName : mInterface.getSmsApps(userId)) {
+            getOutPrintWriter().println(packageName);
+        }
+        return 0;
+    }
+
+    private int handleSmsGetDefaultApp() throws RemoteException {
+        final int userId = maybeParseUserIdArg();
+        if (userId < 0) {
+            return -1;
+        }
+
+        getOutPrintWriter().println(mInterface.getDefaultSmsApp(userId));
+        return 0;
+    }
+
+    private int handleSmsSetDefaultApp() throws RemoteException {
+        final int userId = maybeParseUserIdArg();
+        if (userId < 0) {
+            return -1;
+        }
+
+        String packageName = getNextArgRequired();
+        mInterface.setDefaultSmsApp(userId, packageName);
+        getOutPrintWriter().println("SMS app set to " + mInterface.getDefaultSmsApp(userId));
+        return 0;
+    }
 }
diff --git a/src/com/android/phone/ecc/EccInfoHelper.java b/src/com/android/phone/ecc/EccInfoHelper.java
index cd47dde..c471c4b 100644
--- a/src/com/android/phone/ecc/EccInfoHelper.java
+++ b/src/com/android/phone/ecc/EccInfoHelper.java
@@ -50,6 +50,32 @@
     private static final boolean DBG = false;
     private static final String LOG_TAG = "EccInfoHelper";
 
+    /**
+     * Check if current CountryEccInfo is available for current environment.
+     */
+    public static boolean isCountryEccInfoAvailable(Context context, String countryIso) {
+        CountryEccInfo countryEccInfo;
+        try {
+            countryEccInfo = IsoToEccProtobufRepository.getInstance()
+                    .getCountryEccInfo(context, countryIso);
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Failed to retrieve ECC: ", e);
+            return false;
+        }
+
+        if (countryEccInfo == null) {
+            return false;
+        }
+        for (EccInfo entry : countryEccInfo.getEccInfoList()) {
+            if (!PhoneNumberUtils.isEmergencyNumber(entry.getNumber())) {
+                // The CountryEccInfo is unavailable if any ecc number in the local table was
+                // declined.
+                return false;
+            }
+        }
+        return true;
+    }
+
     // country ISO to ECC list data source
     private IsoToEccRepository mEccRepo;
 
@@ -136,7 +162,8 @@
         }.execute();
     }
 
-    private @NonNull CountryEccInfo getDialableCountryEccInfo(CountryEccInfo countryEccInfo) {
+    @NonNull
+    private CountryEccInfo getDialableCountryEccInfo(CountryEccInfo countryEccInfo) {
         ArrayList<EccInfo> dialableECCList = new ArrayList<>();
         String dialableFallback = null;
 
@@ -155,7 +182,8 @@
         return new CountryEccInfo(dialableFallback, dialableECCList);
     }
 
-    private @Nullable String getCurrentCountryIso(@NonNull Context context) {
+    @Nullable
+    private String getCurrentCountryIso(@NonNull Context context) {
         // Do not detect country ISO if airplane mode is on
         int airplaneMode = Settings.System.getInt(context.getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_ON, 0);
@@ -185,7 +213,8 @@
     // XXX: According to ServiceStateTracker implementation, to actually get current cell info,
     // this method must be called in a separate thread from ServiceStateTracker, which is the
     // main thread of Telephony service.
-    private @Nullable String getCurrentMccFromCellInfo(@NonNull Context context) {
+    @Nullable
+    private String getCurrentMccFromCellInfo(@NonNull Context context) {
         // retrieve mcc info from base station even no SIM present.
         TelephonyManager tm = (TelephonyManager) context.getSystemService(
                 Context.TELEPHONY_SERVICE);
diff --git a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java b/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
index 817ff1d..0cd3108 100644
--- a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
+++ b/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
@@ -40,7 +40,22 @@
 public class IsoToEccProtobufRepository implements IsoToEccRepository {
     private static final String LOG_TAG = "EccRepository";
 
-    private Map<String, CountryEccInfo> mEccTable = null;
+    private static IsoToEccProtobufRepository sInstance;
+
+    /**
+     * Returns the singleton instance of IsoToEccProtobufRepository
+     */
+    public static synchronized IsoToEccProtobufRepository getInstance() {
+        if (sInstance == null) {
+            sInstance = new IsoToEccProtobufRepository();
+        }
+        return sInstance;
+    }
+
+    private final Map<String, CountryEccInfo> mEccTable = new HashMap<>();
+
+    private IsoToEccProtobufRepository() {
+    }
 
     @Override
     @Nullable
@@ -50,24 +65,28 @@
             return null;
         }
 
-        if (mEccTable == null) {
-            mEccTable = initMappingTable(context);
+        synchronized (mEccTable) {
+            return mEccTable.get(iso.toUpperCase());
         }
-        return mEccTable.get(iso.toUpperCase());
     }
 
-    private Map<String, CountryEccInfo> initMappingTable(@NonNull Context context)
-            throws IOException {
+    /**
+     * Loads the mapping table.
+     */
+    public void loadMappingTable(@NonNull Context context) {
         ProtobufEccData.AllInfo allEccData = null;
 
         long startTime = SystemClock.uptimeMillis();
-        allEccData = parseEccData(new BufferedInputStream(
-                context.getAssets().open("eccdata")));
+        try {
+            allEccData = parseEccData(new BufferedInputStream(
+                    context.getAssets().open("eccdata")));
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Failed to retrieve ECC: ", e);
+        }
         long endTime = SystemClock.uptimeMillis();
 
         if (allEccData == null) {
-            // Returns an empty table.
-            return new HashMap<>();
+            return;
         }
 
         if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
@@ -77,16 +96,17 @@
         }
 
         // Converts to run-time data from Protobuf data.
-        Map<String, CountryEccInfo> table = new HashMap<>();
-        for (ProtobufEccData.CountryInfo countryData : allEccData.getCountriesList()) {
-            if (countryData.hasIsoCode()) {
-                CountryEccInfo countryInfo = loadCountryEccInfo(countryData);
-                if (countryInfo != null) {
-                    table.put(countryData.getIsoCode().toUpperCase(), countryInfo);
+        synchronized (mEccTable) {
+            mEccTable.clear();
+            for (ProtobufEccData.CountryInfo countryData : allEccData.getCountriesList()) {
+                if (countryData.hasIsoCode()) {
+                    CountryEccInfo countryInfo = loadCountryEccInfo(countryData);
+                    if (countryInfo != null) {
+                        mEccTable.put(countryData.getIsoCode().toUpperCase(), countryInfo);
+                    }
                 }
             }
         }
-        return table;
     }
 
     private ProtobufEccData.AllInfo parseEccData(InputStream input) throws IOException {
diff --git a/src/com/android/phone/otasp/OtaspActivationService.java b/src/com/android/phone/otasp/OtaspActivationService.java
index c41640c..7490880 100644
--- a/src/com/android/phone/otasp/OtaspActivationService.java
+++ b/src/com/android/phone/otasp/OtaspActivationService.java
@@ -28,6 +28,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import com.android.internal.telephony.GsmCdmaConnection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.phone.PhoneGlobals;
@@ -45,8 +46,10 @@
 public class OtaspActivationService extends Service {
     private static final String TAG = OtaspActivationService.class.getSimpleName();
     private static final boolean DBG = true;
-    /* non-interactive otasp number */
-    private static final String OTASP_NUMBER = "*22899";
+    /**
+     * non-interactive otasp number
+     */
+    private static final String OTASP_NUMBER = GsmCdmaConnection.OTASP_NUMBER;
 
     /**
      * Otasp call follows with SIM reloading which might triggers a retry loop on activation
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 0eb3845..5c614d9 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -109,7 +109,8 @@
             mButtonHac = null;
         }
 
-        if (PhoneGlobals.getInstance().phoneMgr.isRttSupported()) {
+        if (PhoneGlobals.getInstance().phoneMgr
+                .isRttSupported(SubscriptionManager.getDefaultVoiceSubscriptionId())) {
             // TODO: this is going to be a on/off switch for now. Ask UX about how to integrate
             // this settings with TTY
             boolean rttOn = Settings.Secure.getInt(
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index d891da9..670f98d 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -18,7 +18,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -77,15 +76,6 @@
     private SwitchPreference mSipReceiveCallsPreference;
     private SipPreferences mSipPreferences;
 
-    private final SubscriptionManager.OnSubscriptionsChangedListener
-            mOnSubscriptionsChangeListener =
-            new SubscriptionManager.OnSubscriptionsChangedListener() {
-        @Override
-        public void onSubscriptionsChanged() {
-            updateAccounts();
-        }
-    };
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -132,8 +122,34 @@
          */
         mAccountList = (PreferenceCategory) getPreferenceScreen().findPreference(
                 ACCOUNTS_LIST_CATEGORY_KEY);
+        List<PhoneAccountHandle> allNonSimAccounts =
+                getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
+        // Check to see if we should show the entire section at all.
+        if (shouldShowConnectionServiceList(allNonSimAccounts)) {
+            List<PhoneAccountHandle> enabledAccounts =
+                    getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
+            // Initialize the account list with the set of enabled & SIM accounts.
+            initAccountList(enabledAccounts);
 
-        updateAccounts();
+            mDefaultOutgoingAccount = (AccountSelectionPreference)
+                    getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
+            mDefaultOutgoingAccount.setListener(this);
+
+            // Only show the 'Make Calls With..." option if there are multiple accounts.
+            if (enabledAccounts.size() > 1) {
+                updateDefaultOutgoingAccountsModel();
+            } else {
+                mAccountList.removePreference(mDefaultOutgoingAccount);
+            }
+
+            Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
+            // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
+            if (allNonSimAccounts.isEmpty() && allAccounts != null) {
+                mAccountList.removePreference(allAccounts);
+            }
+        } else {
+            getPreferenceScreen().removePreference(mAccountList);
+        }
 
         if (isPrimaryUser() && SipUtil.isVoipSupported(getActivity())) {
             mSipPreferences = new SipPreferences(getActivity());
@@ -167,16 +183,6 @@
             getPreferenceScreen().removePreference(
                     getPreferenceScreen().findPreference(SIP_SETTINGS_CATEGORY_PREF_KEY));
         }
-
-        SubscriptionManager.from(getActivity()).addOnSubscriptionsChangedListener(
-                mOnSubscriptionsChangeListener);
-    }
-
-    @Override
-    public void onPause() {
-        SubscriptionManager.from(getActivity()).removeOnSubscriptionsChangedListener(
-                mOnSubscriptionsChangeListener);
-        super.onPause();
     }
 
     /**
@@ -385,40 +391,6 @@
         return mTelephonyManager.isMultiSimEnabled() || allNonSimAccounts.size() > 0;
     }
 
-    private void updateAccounts() {
-        if (mAccountList != null) {
-            mAccountList.removeAll();
-            List<PhoneAccountHandle> allNonSimAccounts =
-                    getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
-            // Check to see if we should show the entire section at all.
-            if (shouldShowConnectionServiceList(allNonSimAccounts)) {
-                List<PhoneAccountHandle> enabledAccounts =
-                        getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
-                // Initialize the account list with the set of enabled & SIM accounts.
-                initAccountList(enabledAccounts);
-
-                mDefaultOutgoingAccount = (AccountSelectionPreference)
-                        getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
-                mDefaultOutgoingAccount.setListener(this);
-
-                // Only show the 'Make Calls With..." option if there are multiple accounts.
-                if (enabledAccounts.size() > 1) {
-                    updateDefaultOutgoingAccountsModel();
-                } else {
-                    mAccountList.removePreference(mDefaultOutgoingAccount);
-                }
-
-                Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
-                // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
-                if (allNonSimAccounts.isEmpty() && allAccounts != null) {
-                    mAccountList.removePreference(allAccounts);
-                }
-            } else {
-                getPreferenceScreen().removePreference(mAccountList);
-            }
-        }
-    }
-
     private List<PhoneAccountHandle> getCallingAccounts(
             boolean includeSims, boolean includeDisabledAccounts) {
         PhoneAccountHandle emergencyAccountHandle = getEmergencyPhoneAccount();
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 611d147..9ed34e7 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -173,6 +173,7 @@
             case android.telephony.DisconnectCause.CANT_CALL_WHILE_RINGING:
             case android.telephony.DisconnectCause.CALLING_DISABLED:
             case android.telephony.DisconnectCause.TOO_MANY_ONGOING_CALLS:
+            case android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS:
             case android.telephony.DisconnectCause.UNOBTAINABLE_NUMBER:
             case android.telephony.DisconnectCause.VOICEMAIL_NUMBER_MISSING:
             case android.telephony.DisconnectCause.DIAL_MODIFIED_TO_USSD:
@@ -337,11 +338,12 @@
             case android.telephony.DisconnectCause.TOO_MANY_ONGOING_CALLS:
                 resourceId = R.string.callFailed_too_many_calls;
                 break;
-
             case android.telephony.DisconnectCause.IMS_SIP_ALTERNATE_EMERGENCY_CALL:
                 resourceId = R.string.incall_error_power_off;
                 break;
-
+            case android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS:
+                resourceId = R.string.callFailed_otasp_provisioning_in_process;
+                break;
             default:
                 break;
         }
@@ -717,11 +719,12 @@
             case android.telephony.DisconnectCause.TOO_MANY_ONGOING_CALLS:
                 resourceId = R.string.callFailed_too_many_calls;
                 break;
-
             case android.telephony.DisconnectCause.IMS_SIP_ALTERNATE_EMERGENCY_CALL:
                 resourceId = R.string.incall_error_power_off;
                 break;
-
+            case android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS:
+                resourceId = R.string.callFailed_otasp_provisioning_in_process;
+                break;
             default:
                 break;
         }
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6b7a002..a0e5530 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -260,7 +260,7 @@
                 extras.putBoolean(PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, true);
             }
 
-            if (PhoneGlobals.getInstance().phoneMgr.isRttEnabled()) {
+            if (PhoneGlobals.getInstance().phoneMgr.isRttEnabled(subId)) {
                 capabilities |= PhoneAccount.CAPABILITY_RTT;
             }
 
@@ -525,7 +525,8 @@
         }
 
         public void updateRttCapability() {
-            boolean isRttEnabled = PhoneGlobals.getInstance().phoneMgr.isRttEnabled();
+            boolean isRttEnabled = PhoneGlobals.getInstance().phoneMgr
+                    .isRttEnabled(mPhone.getSubId());
             boolean oldRttEnabled = mAccount.hasCapabilities(PhoneAccount.CAPABILITY_RTT);
             if (isRttEnabled != oldRttEnabled) {
                 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 07754c6..f986994 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1140,6 +1140,9 @@
                 case CallStateException.ERROR_TOO_MANY_CALLS:
                     cause = android.telephony.DisconnectCause.TOO_MANY_ONGOING_CALLS;
                     break;
+                case CallStateException.ERROR_OTASP_PROVISIONING_IN_PROCESS:
+                    cause = android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS;
+                    break;
             }
             connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
                     cause, e.getMessage(), phone.getPhoneId()));
diff --git a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
index 5f19509..708ea66 100644
--- a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
+++ b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
@@ -18,6 +18,7 @@
           package="com.android.phone.testapps.telephonyregistry">
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
     <application android:label="TelephonyRegistryTestApp">
         <activity
             android:name=".TelephonyRegistryTestApp"
diff --git a/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java b/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
index 8593245..74cafcd 100644
--- a/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
+++ b/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
@@ -54,7 +54,7 @@
         put(PhoneStateListener.LISTEN_PRECISE_CALL_STATE, "PRECISE_CALL_STATE");
         put(PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE,
                 "PRECISE_DATA_CONNECTION_STATE");
-        put(PhoneStateListener.LISTEN_VOLTE_STATE, "VOLTE_STATE");
+        put(PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED, "SRVCC_STATE");
         put(PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE, "CARRIER_NETWORK_CHANGE");
         put(PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE, "VOICE_ACTIVATION_STATE");
         put(PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE, "DATA_ACTIVATION_STATE");
@@ -71,6 +71,11 @@
             notify("onCellInfoChanged", cellInfo);
         }
 
+        @Override
+        public void onSrvccStateChanged(int srvccState) {
+            notify("onSrvccStateChanged", srvccState);
+        }
+
         private void notify(String method, Object data) {
             Notification.Builder builder = new Notification.Builder(TelephonyRegistryTestApp.this,
                     NOTIFICATION_CHANNEL);