Migrate the NetworkSelection settings

Bug: 111453847
Test: existing telephony test
Change-Id: Ib27cf66183f8ea506ffb329981b0b99a510d997c
diff --git a/src/com/android/phone/CdmaSubscriptionListPreference.java b/src/com/android/phone/CdmaSubscriptionListPreference.java
index 4a32dc4..cd0c681 100644
--- a/src/com/android/phone/CdmaSubscriptionListPreference.java
+++ b/src/com/android/phone/CdmaSubscriptionListPreference.java
@@ -17,17 +17,15 @@
 package com.android.phone;
 
 import android.content.Context;
-import android.os.AsyncResult;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
 import android.preference.ListPreference;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 public class CdmaSubscriptionListPreference extends ListPreference {
 
@@ -41,19 +39,17 @@
     //                           1 - NV
     static final int preferredSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
 
-    private Phone mPhone;
-    private CdmaSubscriptionButtonHandler mHandler;
+    private TelephonyManager mTelephonyManager;
 
     public CdmaSubscriptionListPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mPhone = PhoneFactory.getDefaultPhone();
-        mHandler = new CdmaSubscriptionButtonHandler();
+        mTelephonyManager = TelephonyManager.from(context);
         setCurrentCdmaSubscriptionModeValue();
     }
 
     private void setCurrentCdmaSubscriptionModeValue() {
-        int cdmaSubscriptionMode = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
+        int cdmaSubscriptionMode = Settings.Global.getInt(getContext().getContentResolver(),
                 Settings.Global.CDMA_SUBSCRIPTION_MODE, preferredSubscriptionMode);
         setValue(Integer.toString(cdmaSubscriptionMode));
     }
@@ -62,6 +58,15 @@
         this(context, null);
     }
 
+    /**
+     * Sets the subscription id associated with this preference.
+     *
+     * @param subId the subscription id.
+     */
+    public void setSubscriptionId(int subId) {
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+    }
+
     @Override
     protected void showDialog(Bundle state) {
         setCurrentCdmaSubscriptionModeValue();
@@ -92,40 +97,23 @@
                 statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
         }
 
-        // Set the CDMA subscription mode, when mode has been successfully changed
-        // handleSetCdmaSubscriptionMode will be invoked and the value saved.
-        mPhone.setCdmaSubscription(statusCdmaSubscriptionMode, mHandler
-                .obtainMessage(CdmaSubscriptionButtonHandler.MESSAGE_SET_CDMA_SUBSCRIPTION,
-                        getValue()));
+        // Set the CDMA subscription mode, when mode has been successfully changed, update the
+        // mode to the global setting.
+        ThreadUtils.postOnBackgroundThread(() -> {
+            // The subscription mode selected by user.
+            int cdmaSubscriptionMode = Integer.parseInt(getValue());
 
-    }
+            boolean isSuccessed = mTelephonyManager.setCdmaSubscriptionMode(
+                    statusCdmaSubscriptionMode);
 
-    private class CdmaSubscriptionButtonHandler extends Handler {
-
-        static final int MESSAGE_SET_CDMA_SUBSCRIPTION = 0;
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_SET_CDMA_SUBSCRIPTION:
-                    handleSetCdmaSubscriptionMode(msg);
-                    break;
-            }
-        }
-
-        private void handleSetCdmaSubscriptionMode(Message msg) {
-            mPhone = PhoneFactory.getDefaultPhone();
-            AsyncResult ar = (AsyncResult) msg.obj;
-
-            if (ar.exception == null) {
-                // Get the original string entered by the user
-                int cdmaSubscriptionMode = Integer.parseInt((String) ar.userObj);
-                Settings.Global.putInt(mPhone.getContext().getContentResolver(),
+            // Update the global settings if successed.
+            if (isSuccessed) {
+                Settings.Global.putInt(getContext().getContentResolver(),
                         Settings.Global.CDMA_SUBSCRIPTION_MODE,
-                        cdmaSubscriptionMode );
+                        cdmaSubscriptionMode);
             } else {
                 Log.e(LOG_TAG, "Setting Cdma subscription source failed");
             }
-        }
+        });
     }
 }
diff --git a/src/com/android/phone/CdmaSystemSelectListPreference.java b/src/com/android/phone/CdmaSystemSelectListPreference.java
index 9c24aa7..0044a8b 100644
--- a/src/com/android/phone/CdmaSystemSelectListPreference.java
+++ b/src/com/android/phone/CdmaSystemSelectListPreference.java
@@ -17,43 +17,49 @@
 package com.android.phone;
 
 import android.content.Context;
-import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.preference.ListPreference;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
 
-import com.android.internal.telephony.Phone;
+import com.android.settingslib.utils.ThreadUtils;
 
 public class CdmaSystemSelectListPreference extends ListPreference {
 
     private static final String LOG_TAG = "CdmaRoamingListPreference";
     private static final boolean DBG = false;
 
-    private Phone mPhone;
+    private TelephonyManager mTelephonyManager;
     private MyHandler mHandler = new MyHandler();
 
     public CdmaSystemSelectListPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mPhone = PhoneGlobals.getPhone();
         mHandler = new MyHandler();
-        mPhone.queryCdmaRoamingPreference(
-                mHandler.obtainMessage(MyHandler.MESSAGE_GET_ROAMING_PREFERENCE));
+        mTelephonyManager = TelephonyManager.from(context);
     }
 
     public CdmaSystemSelectListPreference(Context context) {
         this(context, null);
     }
 
+    /**
+     * Sets the subscription id associated with this preference.
+     *
+     * @param subId the subscription id.
+     */
+    public void setSubscriptionId(int subId) {
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+        queryCdmaRoamingMode();
+    }
+
     @Override
     protected void showDialog(Bundle state) {
-        if (mPhone.isInEcm()) {
-            // In ECM mode do not show selection options
-        } else {
+        if (!mTelephonyManager.getEmergencyCallbackMode()) {
             super.showDialog(state);
         }
     }
@@ -64,26 +70,22 @@
 
         if (positiveResult && (getValue() != null)) {
             int buttonCdmaRoamingMode = Integer.parseInt(getValue());
-            int settingsCdmaRoamingMode =
-                    Settings.Global.getInt(mPhone.getContext().getContentResolver(),
-                    Settings.Global.CDMA_ROAMING_MODE, Phone.CDMA_RM_HOME);
+            int settingsCdmaRoamingMode = Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    Settings.Global.CDMA_ROAMING_MODE,
+                    TelephonyManager.CDMA_ROAMING_MODE_HOME);
             if (buttonCdmaRoamingMode != settingsCdmaRoamingMode) {
-                int statusCdmaRoamingMode;
-                switch(buttonCdmaRoamingMode) {
-                    case Phone.CDMA_RM_ANY:
-                        statusCdmaRoamingMode = Phone.CDMA_RM_ANY;
-                        break;
-                    case Phone.CDMA_RM_HOME:
-                    default:
-                        statusCdmaRoamingMode = Phone.CDMA_RM_HOME;
+                int cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_ANY;
+                if (buttonCdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_ANY) {
+                    cdmaRoamingMode = TelephonyManager.CDMA_ROAMING_MODE_HOME;
                 }
                 //Set the Settings.Secure network mode
-                Settings.Global.putInt(mPhone.getContext().getContentResolver(),
+                Settings.Global.putInt(
+                        getContext().getContentResolver(),
                         Settings.Global.CDMA_ROAMING_MODE,
-                        buttonCdmaRoamingMode );
+                        buttonCdmaRoamingMode);
                 //Set the roaming preference mode
-                mPhone.setCdmaRoamingPreference(statusCdmaRoamingMode, mHandler
-                        .obtainMessage(MyHandler.MESSAGE_SET_ROAMING_PREFERENCE));
+                setCdmaRoamingMode(cdmaRoamingMode);
             }
         } else {
             Log.d(LOG_TAG, String.format("onDialogClosed: positiveResult=%b value=%s -- do nothing",
@@ -110,27 +112,28 @@
         }
 
         private void handleQueryCdmaRoamingPreference(Message msg) {
-            AsyncResult ar = (AsyncResult) msg.obj;
+            int cdmaRoamingMode = msg.arg1;
 
-            if (ar.exception == null) {
-                int statusCdmaRoamingMode = ((int[])ar.result)[0];
+            if (cdmaRoamingMode != TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT) {
                 int settingsRoamingMode = Settings.Global.getInt(
-                        mPhone.getContext().getContentResolver(),
-                        Settings.Global.CDMA_ROAMING_MODE, Phone.CDMA_RM_HOME);
+                        getContext().getContentResolver(),
+                        Settings.Global.CDMA_ROAMING_MODE,
+                        TelephonyManager.CDMA_ROAMING_MODE_HOME);
+
                 //check that statusCdmaRoamingMode is from an accepted value
-                if (statusCdmaRoamingMode == Phone.CDMA_RM_HOME ||
-                        statusCdmaRoamingMode == Phone.CDMA_RM_ANY ) {
+                if (cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_HOME
+                        || cdmaRoamingMode == TelephonyManager.CDMA_ROAMING_MODE_ANY) {
                     //check changes in statusCdmaRoamingMode and updates settingsRoamingMode
-                    if (statusCdmaRoamingMode != settingsRoamingMode) {
-                        settingsRoamingMode = statusCdmaRoamingMode;
+                    if (cdmaRoamingMode != settingsRoamingMode) {
+                        settingsRoamingMode = cdmaRoamingMode;
                         //changes the Settings.Secure accordingly to statusCdmaRoamingMode
                         Settings.Global.putInt(
-                                mPhone.getContext().getContentResolver(),
+                                getContext().getContentResolver(),
                                 Settings.Global.CDMA_ROAMING_MODE,
-                                settingsRoamingMode );
+                                settingsRoamingMode);
                     }
                     //changes the mButtonPreferredNetworkMode accordingly to modemNetworkMode
-                    setValue(Integer.toString(statusCdmaRoamingMode));
+                    setValue(Integer.toString(cdmaRoamingMode));
                 }
                 else {
                     if(DBG) Log.i(LOG_TAG, "reset cdma roaming mode to default" );
@@ -140,29 +143,45 @@
         }
 
         private void handleSetCdmaRoamingPreference(Message msg) {
-            AsyncResult ar = (AsyncResult) msg.obj;
+            boolean isSuccessed = (boolean) msg.obj;
 
-            if ((ar.exception == null) && (getValue() != null)) {
+            if (isSuccessed && (getValue() != null)) {
                 int cdmaRoamingMode = Integer.parseInt(getValue());
-                Settings.Global.putInt(mPhone.getContext().getContentResolver(),
+                Settings.Global.putInt(
+                        getContext().getContentResolver(),
                         Settings.Global.CDMA_ROAMING_MODE,
                         cdmaRoamingMode );
             } else {
-                mPhone.queryCdmaRoamingPreference(obtainMessage(MESSAGE_GET_ROAMING_PREFERENCE));
+                queryCdmaRoamingMode();
             }
         }
 
         private void resetCdmaRoamingModeToDefault() {
             //set the mButtonCdmaRoam
-            setValue(Integer.toString(Phone.CDMA_RM_ANY));
+            setValue(Integer.toString(TelephonyManager.CDMA_ROAMING_MODE_ANY));
             //set the Settings.System
-            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
-                        Settings.Global.CDMA_ROAMING_MODE,
-                        Phone.CDMA_RM_ANY );
+            Settings.Global.putInt(
+                    getContext().getContentResolver(),
+                    Settings.Global.CDMA_ROAMING_MODE,
+                    TelephonyManager.CDMA_ROAMING_MODE_ANY);
             //Set the Status
-            mPhone.setCdmaRoamingPreference(Phone.CDMA_RM_ANY,
-                    obtainMessage(MyHandler.MESSAGE_SET_ROAMING_PREFERENCE));
+            setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_ANY);
         }
     }
 
+    private void queryCdmaRoamingMode() {
+        ThreadUtils.postOnBackgroundThread(() -> {
+            Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_GET_ROAMING_PREFERENCE);
+            msg.arg1 = mTelephonyManager.getCdmaRoamingMode();
+            msg.sendToTarget();
+        });
+    }
+
+    private void setCdmaRoamingMode(int mode) {
+        ThreadUtils.postOnBackgroundThread(() -> {
+            Message msg = mHandler.obtainMessage(MyHandler.MESSAGE_SET_ROAMING_PREFERENCE);
+            msg.obj = mTelephonyManager.setCdmaRoamingMode(mode);
+            msg.sendToTarget();
+        });
+    }
 }
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 2f443b8..f43edf2 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -1200,7 +1200,7 @@
             }
         }
 
-        // Requires that mPhone is up to date
+        // Requires that mSubId is up to date
         void updateEnabledNetworksEntries() {
             final int phoneType = mTelephonyManager.getPhoneType();
             final PersistableBundle carrierConfig =
@@ -2040,6 +2040,7 @@
             CdmaSystemSelectListPreference systemSelect =
                     (CdmaSystemSelectListPreference)prefSet.findPreference
                             (BUTTON_CDMA_SYSTEM_SELECT_KEY);
+            systemSelect.setSubscriptionId(mSubId);
             if (systemSelect != null) {
                 systemSelect.setEnabled(enable);
             }
diff --git a/src/com/android/phone/NetworkOperators.java b/src/com/android/phone/NetworkOperators.java
index 46d95b9..78a2169 100644
--- a/src/com/android/phone/NetworkOperators.java
+++ b/src/com/android/phone/NetworkOperators.java
@@ -19,7 +19,6 @@
 import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.Intent;
-import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.preference.Preference;
@@ -33,9 +32,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 /**
  * "Networks" settings UI for the Phone app.
@@ -55,16 +52,14 @@
     public static final String BUTTON_CHOOSE_NETWORK_KEY = "button_choose_network_key";
     public static final String CATEGORY_NETWORK_OPERATORS_KEY = "network_operators_category_key";
 
-    int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
-    private static final int ALREADY_IN_AUTO_SELECTION = 1;
-
     //preference objects
     private NetworkSelectListPreference mNetworkSelect;
     private TwoStatePreference mAutoSelect;
     private Preference mChooseNetwork;
+    private ProgressDialog mProgressDialog;
 
     private int mSubId;
-    private ProgressDialog mProgressDialog;
+    private TelephonyManager mTelephonyManager;
 
     // There's two sets of Auto-Select UI in this class.
     // If {@code com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI} set as true
@@ -94,6 +89,7 @@
             removePreference(mChooseNetwork);
         }
         mProgressDialog = new ProgressDialog(getContext());
+        mTelephonyManager = TelephonyManager.from(getContext());
     }
 
     /**
@@ -104,7 +100,7 @@
      */
     protected void update(final int subId, INetworkQueryService queryService) {
         mSubId = subId;
-        mPhoneId = SubscriptionManager.getPhoneId(mSubId);
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
 
         if (mAutoSelect != null) {
             mAutoSelect.setOnPreferenceChangeListener(this);
@@ -112,11 +108,9 @@
 
         if (mEnableNewManualSelectNetworkUI) {
             if (mChooseNetwork != null) {
-                TelephonyManager telephonyManager = (TelephonyManager)
-                        getContext().getSystemService(Context.TELEPHONY_SERVICE);
-                if (DBG) logd("data connection status " + telephonyManager.getDataState());
-                if (telephonyManager.getDataState() == telephonyManager.DATA_CONNECTED) {
-                    mChooseNetwork.setSummary(telephonyManager.getNetworkOperatorName());
+                ServiceState ss = mTelephonyManager.getServiceState();
+                if (ss != null && ss.getState() == ServiceState.STATE_IN_SERVICE) {
+                    mChooseNetwork.setSummary(mTelephonyManager.getNetworkOperatorName());
                 } else {
                     mChooseNetwork.setSummary(R.string.network_disconnected);
                 }
@@ -152,48 +146,44 @@
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            AsyncResult ar;
             switch (msg.what) {
                 case EVENT_AUTO_SELECT_DONE:
                     mAutoSelect.setEnabled(true);
                     dismissProgressBar();
 
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception != null) {
-                        if (DBG) logd("automatic network selection: failed!");
-                        displayNetworkSelectionFailed(ar.exception);
-                    } else {
+                    boolean isSuccessed = (boolean) msg.obj;
+
+                    if (isSuccessed) {
                         if (DBG) logd("automatic network selection: succeeded!");
-                        displayNetworkSelectionSucceeded(msg.arg1);
+                        displayNetworkSelectionSucceeded();
+                    } else {
+                        if (DBG) logd("automatic network selection: failed!");
+                        displayNetworkSelectionFailed();
                     }
 
                     break;
                 case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception != null) {
+                    int networkSelectionMode = msg.arg1;
+                    if (networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN) {
                         if (DBG) logd("get network selection mode: failed!");
-                    } else if (ar.result != null) {
-                        try {
-                            int[] modes = (int[]) ar.result;
-                            boolean autoSelect = (modes[0] == 0);
-                            if (DBG) {
-                                logd("get network selection mode: "
-                                        + (autoSelect ? "auto" : "manual") + " selection");
+                    } else {
+                        boolean autoSelect = networkSelectionMode
+                                == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+                        if (DBG) {
+                            logd("get network selection mode: "
+                                    + (autoSelect ? "auto" : "manual") + " selection");
+                        }
+                        if (mAutoSelect != null) {
+                            mAutoSelect.setChecked(autoSelect);
+                        }
+                        if (mEnableNewManualSelectNetworkUI) {
+                            if (mChooseNetwork != null) {
+                                mChooseNetwork.setEnabled(!autoSelect);
                             }
-                            if (mAutoSelect != null) {
-                                mAutoSelect.setChecked(autoSelect);
+                        } else {
+                            if (mNetworkSelect != null) {
+                                mNetworkSelect.setEnabled(!autoSelect);
                             }
-                            if (mEnableNewManualSelectNetworkUI) {
-                                if (mChooseNetwork != null) {
-                                    mChooseNetwork.setEnabled(!autoSelect);
-                                }
-                            } else {
-                                if (mNetworkSelect != null) {
-                                    mNetworkSelect.setEnabled(!autoSelect);
-                                }
-                            }
-                        } catch (Exception e) {
-                            if (DBG) loge("get network selection mode: unable to parse result.");
                         }
                     }
             }
@@ -202,38 +192,22 @@
     };
 
     // Used by both mAutoSelect and mNetworkSelect buttons.
-    protected void displayNetworkSelectionFailed(Throwable ex) {
-        String status;
-        if ((ex != null && ex instanceof CommandException)
-                && ((CommandException) ex).getCommandError()
-                == CommandException.Error.ILLEGAL_SIM_OR_ME) {
-            status = getContext().getResources().getString(R.string.not_allowed);
-        } else {
-            status = getContext().getResources().getString(R.string.connect_later);
-        }
+    protected void displayNetworkSelectionFailed() {
+        String status = getContext().getResources().getString(R.string.connect_later);
 
         final PhoneGlobals app = PhoneGlobals.getInstance();
         app.notificationMgr.postTransientNotification(
                 NotificationMgr.NETWORK_SELECTION_NOTIFICATION, status);
 
-        TelephonyManager tm = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE);
-        Phone phone = PhoneFactory.getPhone(mPhoneId);
-        if (phone != null) {
-            ServiceState ss = tm.getServiceStateForSubscriber(phone.getSubId());
-            if (ss != null) {
-                app.notificationMgr.updateNetworkSelection(ss.getState(), phone.getSubId());
-            }
+        ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(mSubId);
+        if (ss != null) {
+            app.notificationMgr.updateNetworkSelection(ss.getState(), mSubId);
         }
     }
 
     // Used by both mAutoSelect and mNetworkSelect buttons.
-    protected void displayNetworkSelectionSucceeded(int msgArg1) {
-        String status = null;
-        if (msgArg1 == ALREADY_IN_AUTO_SELECTION) {
-            status = getContext().getResources().getString(R.string.already_auto);
-        } else {
-            status = getContext().getResources().getString(R.string.registration_done);
-        }
+    protected void displayNetworkSelectionSucceeded() {
+        String status = getContext().getResources().getString(R.string.registration_done);
 
         final PhoneGlobals app = PhoneGlobals.getInstance();
         app.notificationMgr.postTransientNotification(
@@ -256,10 +230,17 @@
             if (DBG) logd("select network automatically...");
             showAutoSelectProgressBar();
             mAutoSelect.setEnabled(false);
-            Message msg = mHandler.obtainMessage(EVENT_AUTO_SELECT_DONE);
-            Phone phone = PhoneFactory.getPhone(mPhoneId);
-            if (phone != null) {
-                phone.setNetworkSelectionModeAutomatic(msg);
+            if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+                ThreadUtils.postOnBackgroundThread(() -> {
+                    mTelephonyManager.setNetworkSelectionModeAutomatic();
+                    // Because TelephonyManager#setNetworkSelectionModeAutomatic doesn't have a
+                    // return value, we query the current network selection mode to tell if the
+                    // TelephonyManager#setNetworkSelectionModeAutomatic is successed.
+                    int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+                    Message msg = mHandler.obtainMessage(EVENT_AUTO_SELECT_DONE);
+                    msg.obj = networkSelectionMode == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+                    msg.sendToTarget();
+                });
             }
         } else {
             if (mEnableNewManualSelectNetworkUI) {
@@ -277,11 +258,12 @@
 
     protected void getNetworkSelectionMode() {
         if (DBG) logd("getting network selection mode...");
-        Message msg = mHandler.obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE);
-        Phone phone = PhoneFactory.getPhone(mPhoneId);
-        if (phone != null) {
-            phone.getNetworkSelectionMode(msg);
-        }
+        ThreadUtils.postOnBackgroundThread(() -> {
+            int networkSelectionMode = mTelephonyManager.getNetworkSelectionMode();
+            Message msg = mHandler.obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE);
+            msg.arg1 = networkSelectionMode;
+            msg.sendToTarget();
+        });
     }
 
     private void dismissProgressBar() {
@@ -300,10 +282,10 @@
     }
 
     /**
-     * Open the Choose netwotk page via {@alink NetworkSelectSettingActivity}
+     * Open the Choose network page via {@alink NetworkSelectSettingActivity}
      */
     public void openChooseNetworkPage() {
-        Intent intent = NetworkSelectSettingActivity.getIntent(getContext(), mPhoneId);
+        Intent intent = NetworkSelectSettingActivity.getIntent(getContext(), mSubId);
         getContext().startActivity(intent);
     }
 
diff --git a/src/com/android/phone/NetworkQueryService.java b/src/com/android/phone/NetworkQueryService.java
index 22b5509..e67582f 100644
--- a/src/com/android/phone/NetworkQueryService.java
+++ b/src/com/android/phone/NetworkQueryService.java
@@ -19,7 +19,6 @@
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
-import android.os.AsyncResult;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -33,13 +32,14 @@
 import android.telephony.NetworkScan;
 import android.telephony.NetworkScanRequest;
 import android.telephony.RadioAccessSpecifier;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyScanManager;
 import android.util.Log;
 
+import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.OperatorInfo;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -185,7 +185,7 @@
          * completion.
          */
         public void startNetworkQuery(
-                INetworkQueryServiceCallback cb, int phoneId, boolean isIncrementalResult) {
+                INetworkQueryServiceCallback cb, int subId, boolean isIncrementalResult) {
             if (cb != null) {
                 // register the callback to the list of callbacks.
                 synchronized (mCallbacks) {
@@ -233,16 +233,23 @@
                                         networkScanCallback);
                                 mState = QUERY_IS_RUNNING;
                             } else {
-                                Phone phone = PhoneFactory.getPhone(phoneId);
-                                if (phone != null) {
-                                    phone.getAvailableNetworks(
-                                            mHandler.obtainMessage(
-                                                    EVENT_NETWORK_SCAN_VIA_PHONE_COMPLETED));
+                                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                                     mState = QUERY_IS_RUNNING;
-                                    if (DBG) log("start network scan via Phone");
+                                    ThreadUtils.postOnBackgroundThread(() -> {
+                                        if (DBG) log("start network scan via Phone xxx");
+                                        TelephonyManager telephonyManager =
+                                                TelephonyManager.from(getApplicationContext())
+                                                        .createForSubscriptionId(subId);
+                                        CellNetworkScanResult result =
+                                                telephonyManager.getAvailableNetworks();
+                                        Message msg = mHandler.obtainMessage(
+                                                EVENT_NETWORK_SCAN_VIA_PHONE_COMPLETED);
+                                        msg.obj = result;
+                                        msg.sendToTarget();
+                                    });
                                 } else {
                                     if (DBG) {
-                                        log("phone is null");
+                                        log("SubscriptionId is invalid");
                                     }
                                 }
                             }
@@ -316,8 +323,7 @@
     }
 
     /**
-     * Broadcast the results from the query to all registered callback
-     * objects. 
+     * Broadcast the results from the query to all registered callback objects.
      */
     private void broadcastQueryResults(Message msg) {
         // reset the state.
@@ -331,11 +337,11 @@
                 try {
                     switch (msg.what) {
                         case EVENT_NETWORK_SCAN_VIA_PHONE_COMPLETED:
-                            AsyncResult ar = (AsyncResult) msg.obj;
-                            if (ar != null) {
-                                cb.onResults(getCellInfoList((List<OperatorInfo>) ar.result));
+                            CellNetworkScanResult result = (CellNetworkScanResult) msg.obj;
+                            if (result.getOperators() != null) {
+                                cb.onResults(getCellInfoList(result.getOperators()));
                             } else {
-                                if (DBG) log("AsyncResult is null.");
+                                if (DBG) log("Operators list is null.");
                             }
                             // Send the onComplete() callback to indicate the one-time network
                             // scan has completed.
diff --git a/src/com/android/phone/NetworkSelectListPreference.java b/src/com/android/phone/NetworkSelectListPreference.java
index b1d5544..8d947f7 100644
--- a/src/com/android/phone/NetworkSelectListPreference.java
+++ b/src/com/android/phone/NetworkSelectListPreference.java
@@ -19,7 +19,6 @@
 import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.os.AsyncResult;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Message;
@@ -44,8 +43,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.OperatorInfo;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,7 +62,7 @@
     private static final String LOG_TAG = "networkSelect";
     private static final boolean DBG = true;
 
-    private static final int EVENT_NETWORK_SELECTION_DONE = 1;
+    private static final int EVENT_MANUALLY_NETWORK_SELECTION_DONE = 1;
     private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
     private static final int EVENT_NETWORK_SCAN_COMPLETED = 3;
 
@@ -72,13 +70,12 @@
     private static final int DIALOG_NETWORK_SELECTION = 100;
     private static final int DIALOG_NETWORK_LIST_LOAD = 200;
 
-    private int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
     private List<CellInfo> mCellInfoList;
     private CellInfo mCellInfo;
 
     private int mSubId;
+    private TelephonyManager mTelephonyManager;
     private NetworkOperators mNetworkOperators;
-    private boolean mNeedScanAgain;
     private List<String> mForbiddenPlmns;
 
     private ProgressDialog mProgressDialog;
@@ -114,9 +111,8 @@
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            AsyncResult ar;
             switch (msg.what) {
-                case EVENT_NETWORK_SELECTION_DONE:
+                case EVENT_MANUALLY_NETWORK_SELECTION_DONE:
                     if (DBG) logd("hideProgressPanel");
                     try {
                         dismissProgressBar();
@@ -124,16 +120,16 @@
                     }
                     setEnabled(true);
 
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception != null) {
-                        if (DBG) logd("manual network selection: failed!");
-                        mNetworkOperators.displayNetworkSelectionFailed(ar.exception);
-                    } else {
+                    boolean isSuccessed = (boolean) msg.obj;
+                    if (isSuccessed) {
                         if (DBG) {
                             logd("manual network selection: succeeded! "
                                     + getNetworkTitle(mCellInfo));
                         }
-                        mNetworkOperators.displayNetworkSelectionSucceeded(msg.arg1);
+                        mNetworkOperators.displayNetworkSelectionSucceeded();
+                    } else {
+                        if (DBG) logd("manual network selection: failed!");
+                        mNetworkOperators.displayNetworkSelectionFailed();
                     }
                     mNetworkOperators.getNetworkSelectionMode();
                     break;
@@ -236,14 +232,9 @@
         // This preference should share the same progressDialog with networkOperators category.
         mProgressDialog = progressDialog;
 
-        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
-            mPhoneId = SubscriptionManager.getPhoneId(mSubId);
-        }
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
 
-        TelephonyManager telephonyManager = (TelephonyManager)
-                getContext().getSystemService(Context.TELEPHONY_SERVICE);
-
-        setSummary(telephonyManager.getNetworkOperatorName(mSubId));
+        setSummary(mTelephonyManager.getNetworkOperatorName());
 
         setOnPreferenceChangeListener(this);
     }
@@ -301,7 +292,8 @@
         if (DBG) logd("load networks list...");
         try {
             if (mNetworkQueryService != null) {
-                mNetworkQueryService.startNetworkQuery(mCallback, mPhoneId, false);
+                mNetworkQueryService.startNetworkQuery(
+                        mCallback, mSubId, false /* isIncrementalResult */);
             } else {
                 displayNetworkQueryFailed(NetworkQueryService.QUERY_EXCEPTION);
             }
@@ -407,16 +399,21 @@
         MetricsLogger.action(getContext(),
                 MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK);
 
-        Message msg = mHandler.obtainMessage(EVENT_NETWORK_SELECTION_DONE);
-        Phone phone = PhoneFactory.getPhone(mPhoneId);
-        if (phone != null) {
-            OperatorInfo operatorInfo = getOperatorInfoFromCellInfo(mCellInfo);
-            if (DBG) logd("manually selected network: " + operatorInfo.toString());
-            phone.selectNetworkManually(operatorInfo, true, msg);
-            displayNetworkSelectionInProgress();
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            ThreadUtils.postOnBackgroundThread(() -> {
+                final OperatorInfo operatorInfo = getOperatorInfoFromCellInfo(mCellInfo);
+                if (DBG) logd("manually selected network: " + operatorInfo.toString());
+                boolean isSuccessed = mTelephonyManager.setNetworkSelectionModeManual(
+                        operatorInfo.getOperatorNumeric(), true /* persistSelection */);
+                int mode = mTelephonyManager.getNetworkSelectionMode();
+                Message msg = mHandler.obtainMessage(EVENT_MANUALLY_NETWORK_SELECTION_DONE);
+                msg.obj = isSuccessed;
+                msg.sendToTarget();
+            });
         } else {
-            loge("Error selecting network. phone is null.");
+            loge("Error selecting network, subscription Id is invalid " + mSubId);
         }
+
         return true;
     }
 
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
index 3f211cb..6aaaf9d 100644
--- a/src/com/android/phone/NetworkSelectSetting.java
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.AsyncResult;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
@@ -47,8 +46,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.OperatorInfo;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,7 +62,7 @@
     private static final String TAG = "NetworkSelectSetting";
     private static final boolean DBG = true;
 
-    private static final int EVENT_NETWORK_SELECTION_DONE = 1;
+    private static final int EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE = 1;
     private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
     private static final int EVENT_NETWORK_SCAN_ERROR = 3;
     private static final int EVENT_NETWORK_SCAN_COMPLETED = 4;
@@ -81,11 +79,10 @@
     private View mProgressHeader;
     private Preference mStatusMessagePreference;
     private List<CellInfo> mCellInfoList;
-    private int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private ViewGroup mFrameLayout;
     private NetworkOperatorPreference mSelectedNetworkOperatorPreference;
     private TelephonyManager mTelephonyManager;
-    private NetworkOperators mNetworkOperators;
     private List<String> mForbiddenPlmns;
 
     private final Runnable mUpdateNetworkOperatorsRunnable = () -> {
@@ -95,9 +92,9 @@
     /**
      * Create a new instance of this fragment.
      */
-    public static NetworkSelectSetting newInstance(int phoneId) {
+    public static NetworkSelectSetting newInstance(int subId) {
         Bundle args = new Bundle();
-        args.putInt(NetworkSelectSettingActivity.KEY_PHONE_ID, phoneId);
+        args.putInt(NetworkSelectSettingActivity.KEY_SUBSCRIPTION_ID, subId);
         NetworkSelectSetting fragment = new NetworkSelectSetting();
         fragment.setArguments(args);
 
@@ -109,7 +106,7 @@
         if (DBG) logd("onCreate");
         super.onCreate(icicle);
 
-        mPhoneId = getArguments().getInt(NetworkSelectSettingActivity.KEY_PHONE_ID);
+        mSubId = getArguments().getInt(NetworkSelectSettingActivity.KEY_SUBSCRIPTION_ID);
 
         addPreferencesFromResource(R.xml.choose_network);
         mConnectedNetworkOperatorsPreference =
@@ -118,9 +115,7 @@
                 (PreferenceCategory) findPreference(PREF_KEY_NETWORK_OPERATORS);
         mStatusMessagePreference = new Preference(getContext());
         mSelectedNetworkOperatorPreference = null;
-        mTelephonyManager = (TelephonyManager)
-                getContext().getSystemService(Context.TELEPHONY_SERVICE);
-        mNetworkOperators = new NetworkOperators(getContext());
+        mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
         setRetainInstance(true);
     }
 
@@ -200,9 +195,7 @@
                     MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK);
 
             // Connect to the network
-            Message msg = mHandler.obtainMessage(EVENT_NETWORK_SELECTION_DONE);
-            Phone phone = PhoneFactory.getPhone(mPhoneId);
-            if (phone != null) {
+            if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
                 if (DBG) {
                     logd("Connect to the network: " + CellInfoUtil.getNetworkTitle(cellInfo));
                 }
@@ -219,14 +212,20 @@
                     }
                 }
 
-                // Select network manually via Phone
                 OperatorInfo operatorInfo = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo);
                 if (DBG) logd("manually selected network operator: " + operatorInfo.toString());
-                phone.selectNetworkManually(operatorInfo, true, msg);
+
+                ThreadUtils.postOnBackgroundThread(() -> {
+                    Message msg = mHandler.obtainMessage(EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE);
+                    msg.obj = mTelephonyManager.setNetworkSelectionModeManual(
+                            operatorInfo.getOperatorNumeric(), true /* persistSelection */);
+                    msg.sendToTarget();
+                });
+
                 setProgressBarVisible(true);
                 return true;
             } else {
-                loge("Error selecting network. phone is null.");
+                loge("Error selecting network. Subscription Id is invalid.");
                 mSelectedNetworkOperatorPreference = null;
                 return false;
             }
@@ -258,23 +257,22 @@
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            AsyncResult ar;
             switch (msg.what) {
-                case EVENT_NETWORK_SELECTION_DONE:
+                case EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE:
                     if (DBG) logd("network selection done: hide the progress header");
                     setProgressBarVisible(false);
 
-                    ar = (AsyncResult) msg.obj;
-                    if (ar.exception != null) {
+                    boolean isSuccessed = (boolean) msg.obj;
+                    if (isSuccessed) {
+                        if (DBG) logd("manual network selection: succeeded! ");
+                        // Set summary as "Connected" to the selected network.
+                        mSelectedNetworkOperatorPreference.setSummary(R.string.network_connected);
+                    } else {
                         if (DBG) logd("manual network selection: failed! ");
                         updateNetworkSelection();
                         // Set summary as "Couldn't connect" to the selected network.
                         mSelectedNetworkOperatorPreference.setSummary(
                                 R.string.network_could_not_connect);
-                    } else {
-                        if (DBG) logd("manual network selection: succeeded! ");
-                        // Set summary as "Connected" to the selected network.
-                        mSelectedNetworkOperatorPreference.setSummary(R.string.network_connected);
                     }
                     break;
 
@@ -317,7 +315,7 @@
             if (mNetworkQueryService != null) {
                 if (DBG) logd("start network query");
                 mNetworkQueryService
-                        .startNetworkQuery(mCallback, mPhoneId, true /* is incremental result */);
+                        .startNetworkQuery(mCallback, mSubId, true /* is incremental result */);
             } else {
                 if (DBG) logd("unable to start network query, mNetworkQueryService is null");
                 addMessagePreference(R.string.network_query_error);
@@ -421,7 +419,7 @@
         if (DBG) logd("Force config ConnectedNetworkOperatorsPreferenceCategory");
         if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
             // Try to get the network registration states
-            ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(mPhoneId);
+            ServiceState ss = mTelephonyManager.getServiceState();
             List<NetworkRegistrationState> networkList =
                     ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN);
             if (networkList == null || networkList.size() == 0) {
@@ -627,11 +625,10 @@
     private void updateNetworkSelection() {
         if (DBG) logd("Update notification about no service of user selected operator");
         final PhoneGlobals app = PhoneGlobals.getInstance();
-        Phone phone = PhoneFactory.getPhone(mPhoneId);
-        if (phone != null) {
-            ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(phone.getSubId());
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            ServiceState ss = mTelephonyManager.getServiceState();
             if (ss != null) {
-                app.notificationMgr.updateNetworkSelection(ss.getState(), phone.getSubId());
+                app.notificationMgr.updateNetworkSelection(ss.getState(), mSubId);
             }
         }
     }
diff --git a/src/com/android/phone/NetworkSelectSettingActivity.java b/src/com/android/phone/NetworkSelectSettingActivity.java
index a151c81..5b29b281 100644
--- a/src/com/android/phone/NetworkSelectSettingActivity.java
+++ b/src/com/android/phone/NetworkSelectSettingActivity.java
@@ -31,14 +31,14 @@
  */
 public class NetworkSelectSettingActivity extends Activity {
     private static final String TAG = "NetworkSelectSettingActivity";
-    public static final String KEY_PHONE_ID = "phone_id";
+    public static final String KEY_SUBSCRIPTION_ID = "subscription_id";
 
     /**
      * Returns the Android Intent that led to this Activity being created.
      */
-    public static Intent getIntent(Context context, int phoneId) {
+    public static Intent getIntent(Context context, int subId) {
         Intent intent = new Intent(context, NetworkSelectSettingActivity.class);
-        intent.putExtra(KEY_PHONE_ID, phoneId);
+        intent.putExtra(KEY_SUBSCRIPTION_ID, subId);
         return intent;
     }
 
@@ -46,7 +46,7 @@
     public void onCreate(Bundle savedState) {
         Log.d(TAG, "onCreate()");
         super.onCreate(savedState);
-        int phoneId = getIntent().getExtras().getInt(KEY_PHONE_ID);
+        int subId = getIntent().getExtras().getInt(KEY_SUBSCRIPTION_ID);
         setContentView(R.layout.choose_network);
 
         FragmentManager fragmentManager = getFragmentManager();
@@ -54,7 +54,7 @@
         if (fragment == null) {
             fragmentManager.beginTransaction()
                     .add(R.id.choose_network_content,
-                            NetworkSelectSetting.newInstance(phoneId), TAG)
+                            NetworkSelectSetting.newInstance(subId), TAG)
                     .commit();
         }
     }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 2479631..7bd0937 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -195,6 +195,14 @@
     private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
     private static final int CMD_SWITCH_SLOTS = 50;
     private static final int EVENT_SWITCH_SLOTS_DONE = 51;
+    private static final int CMD_GET_NETWORK_SELECTION_MODE = 52;
+    private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 53;
+    private static final int CMD_GET_CDMA_ROAMING_MODE = 54;
+    private static final int EVENT_GET_CDMA_ROAMING_MODE_DONE = 55;
+    private static final int CMD_SET_CDMA_ROAMING_MODE = 56;
+    private static final int EVENT_SET_CDMA_ROAMING_MODE_DONE = 57;
+    private static final int CMD_SET_CDMA_SUBSCRIPTION_MODE = 58;
+    private static final int EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE = 59;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -323,40 +331,35 @@
             IccAPDUArgument iccArgument;
 
             switch (msg.what) {
-                 case CMD_HANDLE_USSD_REQUEST: {
-                     request = (MainThreadRequest) msg.obj;
-                     final Phone phone = getPhoneFromRequest(request);
-                     Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
-                     String ussdRequest =  ussdObject.first;
-                     ResultReceiver wrappedCallback = ussdObject.second;
+                case CMD_HANDLE_USSD_REQUEST: {
+                    request = (MainThreadRequest) msg.obj;
+                    final Phone phone = getPhoneFromRequest(request);
+                    Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
+                    String ussdRequest =  ussdObject.first;
+                    ResultReceiver wrappedCallback = ussdObject.second;
 
-                     if (!isUssdApiAllowed(request.subId)) {
-                         // Carrier does not support use of this API, return failure.
-                         Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
-                         UssdResponse response = new UssdResponse(ussdRequest, null);
-                         Bundle returnData = new Bundle();
-                         returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
-                         wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
+                    if (!isUssdApiAllowed(request.subId)) {
+                        // Carrier does not support use of this API, return failure.
+                        Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
+                        UssdResponse response = new UssdResponse(ussdRequest, null);
+                        Bundle returnData = new Bundle();
+                        returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
+                        wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
 
-                         request.result = true;
-                         synchronized (request) {
-                             request.notifyAll();
-                         }
-                         return;
-                     }
+                        request.result = true;
+                        notifyRequester(request);
+                        return;
+                    }
 
-                     try {
-                         request.result = phone != null ?
-                                 phone.handleUssdRequest(ussdRequest, wrappedCallback)
-                                 : false;
-                     } catch (CallStateException cse) {
-                         request.result = false;
-                     }
-                     // Wake up the requesting thread
-                     synchronized (request) {
-                         request.notifyAll();
-                     }
-                     break;
+                    try {
+                        request.result = phone != null
+                                ? phone.handleUssdRequest(ussdRequest, wrappedCallback) : false;
+                    } catch (CallStateException cse) {
+                        request.result = false;
+                    }
+                    // Wake up the requesting thread
+                    notifyRequester(request);
+                    break;
                 }
 
                 case CMD_HANDLE_PIN_MMI: {
@@ -366,9 +369,7 @@
                             getPhoneFromRequest(request).handlePinMmi((String) request.argument)
                             : false;
                     // Wake up the requesting thread
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
                 }
 
@@ -378,9 +379,7 @@
                     answerRingingCallInternal(answer_subId);
                     request.result = ""; // dummy result for notifying the waiting thread
                     // Wake up the requesting thread
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_END_CALL:
@@ -406,9 +405,7 @@
                     if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
                     request.result = hungUp;
                     // Wake up the requesting thread
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
@@ -418,9 +415,7 @@
                     if (uiccCard == null) {
                         loge("iccTransmitApduLogicalChannel: No UICC");
                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
                             request);
@@ -447,9 +442,7 @@
                             loge("iccTransmitApduLogicalChannel: Unknown exception");
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
@@ -459,9 +452,7 @@
                     if (uiccCard == null) {
                         loge("iccTransmitApduBasicChannel: No UICC");
                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
                             request);
@@ -487,9 +478,7 @@
                             loge("iccTransmitApduBasicChannel: Unknown exception");
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_EXCHANGE_SIM_IO:
@@ -499,9 +488,7 @@
                     if (uiccCard == null) {
                         loge("iccExchangeSimIO: No UICC");
                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
                                 request);
@@ -519,9 +506,7 @@
                     } else {
                         request.result = new IccIoResult(0x6f, 0, (byte[])null);
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_SEND_ENVELOPE:
@@ -530,9 +515,7 @@
                     if (uiccCard == null) {
                         loge("sendEnvelopeWithStatus: No UICC");
                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
                         uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
@@ -555,9 +538,7 @@
                             loge("sendEnvelopeWithStatus: exception:" + ar.exception);
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_OPEN_CHANNEL:
@@ -568,9 +549,7 @@
                         loge("iccOpenLogicalChannel: No UICC");
                         request.result = new IccOpenLogicalChannelResponse(-1,
                             IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
                         uiccCard.iccOpenLogicalChannel(openChannelArgs.first,
@@ -616,9 +595,7 @@
                             IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
                     }
                     request.result = openChannelResp;
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_CLOSE_CHANNEL:
@@ -627,9 +604,7 @@
                     if (uiccCard == null) {
                         loge("iccCloseLogicalChannel: No UICC");
                         request.result = false;
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                     } else {
                         onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
                         uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
@@ -662,9 +637,7 @@
                             loge("nvReadItem: Unknown exception");
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_NV_WRITE_ITEM:
@@ -720,9 +693,7 @@
                             loge("getPreferredNetworkType: Unknown exception");
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_SET_PREFERRED_NETWORK_TYPE:
@@ -746,9 +717,7 @@
                     ar = (AsyncResult)msg.obj;
                     request = (MainThreadRequest)ar.userObj;
                     request.result = ar;
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_SET_VOICEMAIL_NUMBER:
@@ -808,9 +777,7 @@
                         cellScanResult = new CellNetworkScanResult(errorCode, null);
                     }
                     request.result = cellScanResult;
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
@@ -852,9 +819,7 @@
                     if (request.result == null) {
                         request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0);
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_SET_ALLOWED_CARRIERS:
@@ -884,9 +849,7 @@
                     if (request.result == null) {
                         request.result = new int[]{-1};
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_GET_ALLOWED_CARRIERS:
@@ -914,9 +877,7 @@
                     if (request.result == null) {
                         request.result = new ArrayList<CarrierIdentifier>(0);
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
@@ -933,9 +894,7 @@
                             loge("getForbiddenPlmns: Unknown exception");
                         }
                     }
-                    synchronized (request) {
-                        request.notifyAll();
-                    }
+                    notifyRequester(request);
                     break;
 
                 case CMD_GET_FORBIDDEN_PLMNS:
@@ -945,9 +904,7 @@
                         loge("getForbiddenPlmns() UiccCard is null");
                         request.result = new IllegalArgumentException(
                                 "getForbiddenPlmns() UiccCard is null");
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                         break;
                     }
                     Integer appType = (Integer) request.argument;
@@ -956,9 +913,7 @@
                         loge("getForbiddenPlmns() no app with specified type -- "
                                 + appType);
                         request.result = new IllegalArgumentException("Failed to get UICC App");
-                        synchronized (request) {
-                            request.notifyAll();
-                        }
+                        notifyRequester(request);
                         break;
                     } else {
                         if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
@@ -980,9 +935,67 @@
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     request.result = (ar.exception == null);
-                    synchronized (request) {
-                        request.notifyAll();
+                    notifyRequester(request);
+                    break;
+                case CMD_GET_NETWORK_SELECTION_MODE:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, request);
+                    getPhoneFromRequest(request).getNetworkSelectionMode(onCompleted);
+                    break;
+
+                case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception != null) {
+                        request.result = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
+                    } else {
+                        int mode = ((int[]) ar.result)[0];
+                        if (mode == 0) {
+                            request.result = TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+                        } else {
+                            request.result = TelephonyManager.NETWORK_SELECTION_MODE_MANUAL;
+                        }
                     }
+                    notifyRequester(request);
+                    break;
+                case CMD_GET_CDMA_ROAMING_MODE:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_CDMA_ROAMING_MODE_DONE, request);
+                    getPhoneFromRequest(request).queryCdmaRoamingPreference(onCompleted);
+                    break;
+                case EVENT_GET_CDMA_ROAMING_MODE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception != null) {
+                        request.result = TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
+                    } else {
+                        request.result = ((int[]) ar.result)[0];
+                    }
+                    notifyRequester(request);
+                    break;
+                case CMD_SET_CDMA_ROAMING_MODE:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_SET_CDMA_ROAMING_MODE_DONE, request);
+                    int mode = (int) request.argument;
+                    getPhoneFromRequest(request).setCdmaRoamingPreference(mode, onCompleted);
+                    break;
+                case EVENT_SET_CDMA_ROAMING_MODE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    request.result = ar.exception == null;
+                    notifyRequester(request);
+                    break;
+                case CMD_SET_CDMA_SUBSCRIPTION_MODE:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
+                    int subscriptionMode = (int) request.argument;
+                    getPhoneFromRequest(request).setCdmaSubscription(subscriptionMode, onCompleted);
+                    break;
+                case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    request.result = ar.exception == null;
+                    notifyRequester(request);
                     break;
 
                 default:
@@ -991,6 +1004,12 @@
             }
         }
 
+        private void notifyRequester(MainThreadRequest request) {
+            synchronized (request) {
+                request.notifyAll();
+            }
+        }
+
         private void handleNullReturnEvent(Message msg, String command) {
             AsyncResult ar = (AsyncResult) msg.obj;
             MainThreadRequest request = (MainThreadRequest) ar.userObj;
@@ -1004,9 +1023,7 @@
                     loge(command + ": Unknown exception");
                 }
             }
-            synchronized (request) {
-                request.notifyAll();
-            }
+            notifyRequester(request);
         }
     }
 
@@ -2598,6 +2615,11 @@
         }
     }
 
+    @Override
+    public int getNetworkSelectionMode(int subId) {
+        return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
+    }
+
     /**
      * Returns the network type for a subId
      */
@@ -3322,12 +3344,11 @@
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "getCellNetworkScanResults");
 
-        final long identity = Binder.clearCallingIdentity();
+        long identity = Binder.clearCallingIdentity();
         try {
             if (DBG) log("getCellNetworkScanResults: subId " + subId);
-            CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
+            return (CellNetworkScanResult) sendRequest(
                     CMD_PERFORM_NETWORK_SCAN, null, subId);
-            return result;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5018,16 +5039,20 @@
      */
     @Override
     public boolean isDataRoamingEnabled(int subId) {
+        boolean isEnabled = false;
+        final long identity = Binder.clearCallingIdentity();
         try {
             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
-                    null);
+                    null /* message */);
+            Phone phone = getPhone(subId);
+            isEnabled =  phone != null ? phone.getDataRoamingEnabled() : false;
         } catch (Exception e) {
             TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
                     mApp, subId, "isDataRoamingEnabled");
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
-
-        Phone phone = getPhone(subId);
-        return phone != null ? phone.getDataRoamingEnabled() : false;
+        return isEnabled;
     }
 
 
@@ -5043,12 +5068,17 @@
      */
     @Override
     public void setDataRoamingEnabled(int subId, boolean isEnabled) {
-        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
-                mApp, subId, "setDataRoamingEbaled");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, subId, "setDataRoamingEnabled");
 
-        Phone phone = getPhone(subId);
-        if (phone != null) {
-            phone.setDataRoamingEnabled(isEnabled);
+            Phone phone = getPhone(subId);
+            if (phone != null) {
+                phone.setDataRoamingEnabled(isEnabled);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -5256,4 +5286,43 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    @Override
+    public int getCdmaRoamingMode(int subId) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "getCdmaRoamingMode");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean setCdmaRoamingMode(int subId, int mode) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setCdmaRoamingMode");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean setCdmaSubscriptionMode(int subId, int mode) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setCdmaSubscriptionMode");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
 }