Merge "Hide account settings in call settings if multiple SIMs." into lmp-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 73113d2..c086376 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -94,8 +94,8 @@
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
     <uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES" />
-    <uses-permission
-            android:name="com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" />
+    <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" />
 
     <!-- This tells the activity manager to not delay any of our activity
          start requests, even if they happen immediately after the user
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index c1e1a7f..b7f2d55 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -63,6 +63,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.phone.common.util.SettingsUtil;
 import com.android.phone.settings.AccountSelectionPreference;
+import com.android.phone.settings.VoicemailProviderSettings;
 import com.android.services.telephony.sip.SipUtil;
 
 import java.lang.String;
@@ -127,8 +128,6 @@
     private static final String UP_ACTIVITY_CLASS =
             "com.android.dialer.DialtactsActivity";
 
-    // Used to tell the saving logic to leave forwarding number as is
-    public static final CallForwardInfo[] FWD_SETTINGS_DONT_TOUCH = null;
     // Suffix appended to provider key for storing vm number
     public static final String VM_NUMBER_TAG = "#VMNumber";
     // Suffix appended to provider key for storing forwarding settings
@@ -273,90 +272,6 @@
         public Intent intent;
     }
 
-    /**
-     * Forwarding settings we are going to save.
-     */
-    private static final int [] FORWARDING_SETTINGS_REASONS = new int[] {
-        CommandsInterface.CF_REASON_UNCONDITIONAL,
-        CommandsInterface.CF_REASON_BUSY,
-        CommandsInterface.CF_REASON_NO_REPLY,
-        CommandsInterface.CF_REASON_NOT_REACHABLE
-    };
-
-    private class VoiceMailProviderSettings {
-        /**
-         * Constructs settings object, setting all conditional forwarding to the specified number
-         */
-        public VoiceMailProviderSettings(String voicemailNumber, String forwardingNumber,
-                int timeSeconds) {
-            this.voicemailNumber = voicemailNumber;
-            if (forwardingNumber == null || forwardingNumber.length() == 0) {
-                this.forwardingSettings = FWD_SETTINGS_DONT_TOUCH;
-            } else {
-                this.forwardingSettings = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
-                for (int i = 0; i < this.forwardingSettings.length; i++) {
-                    CallForwardInfo fi = new CallForwardInfo();
-                    this.forwardingSettings[i] = fi;
-                    fi.reason = FORWARDING_SETTINGS_REASONS[i];
-                    fi.status = (fi.reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ? 0 : 1;
-                    fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
-                    fi.toa = PhoneNumberUtils.TOA_International;
-                    fi.number = forwardingNumber;
-                    fi.timeSeconds = timeSeconds;
-                }
-            }
-        }
-
-        public VoiceMailProviderSettings(String voicemailNumber, CallForwardInfo[] infos) {
-            this.voicemailNumber = voicemailNumber;
-            this.forwardingSettings = infos;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o == null) return false;
-            if (!(o instanceof VoiceMailProviderSettings)) return false;
-            final VoiceMailProviderSettings v = (VoiceMailProviderSettings)o;
-
-            return ((this.voicemailNumber == null &&
-                        v.voicemailNumber == null) ||
-                    this.voicemailNumber != null &&
-                        this.voicemailNumber.equals(v.voicemailNumber))
-                    &&
-                    forwardingSettingsEqual(this.forwardingSettings,
-                            v.forwardingSettings);
-        }
-
-        private boolean forwardingSettingsEqual(CallForwardInfo[] infos1,
-                CallForwardInfo[] infos2) {
-            if (infos1 == infos2) return true;
-            if (infos1 == null || infos2 == null) return false;
-            if (infos1.length != infos2.length) return false;
-            for (int i = 0; i < infos1.length; i++) {
-                CallForwardInfo i1 = infos1[i];
-                CallForwardInfo i2 = infos2[i];
-                if (i1.status != i2.status ||
-                    i1.reason != i2.reason ||
-                    i1.serviceClass != i2.serviceClass ||
-                    i1.toa != i2.toa ||
-                    i1.number != i2.number ||
-                    i1.timeSeconds != i2.timeSeconds) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return voicemailNumber + ((forwardingSettings != null ) ? (", " +
-                    forwardingSettings.toString()) : "");
-        }
-
-        public String voicemailNumber;
-        public CallForwardInfo[] forwardingSettings;
-    }
-
     private SharedPreferences mPerProviderSavedVMNumbers;
 
     /**
@@ -563,7 +478,7 @@
             }
             updateVMPreferenceWidgets(newProviderKey);
 
-            final VoiceMailProviderSettings newProviderSettings =
+            final VoicemailProviderSettings newProviderSettings =
                     loadSettingsForVoiceMailProvider(newProviderKey);
 
             // If the user switches to a voice mail provider and we have a
@@ -656,11 +571,11 @@
                 }
 
                 showDialogIfForeground(VOICEMAIL_REVERTING_DIALOG);
-                final VoiceMailProviderSettings prevSettings =
+                final VoicemailProviderSettings prevSettings =
                         loadSettingsForVoiceMailProvider(mPreviousVMProviderKey);
                 if (prevSettings == null) {
                     // prevSettings never becomes null since it should be already loaded!
-                    Log.e(LOG_TAG, "VoiceMailProviderSettings for the key \""
+                    Log.e(LOG_TAG, "VoicemailProviderSettings for the key \""
                             + mPreviousVMProviderKey + "\" becomes null, which is unexpected.");
                     if (DBG) {
                         Log.e(LOG_TAG,
@@ -669,7 +584,7 @@
                     }
                 }
                 if (mVMChangeCompletedSuccessfully) {
-                    mNewVMNumber = prevSettings.voicemailNumber;
+                    mNewVMNumber = prevSettings.getVoicemailNumber();
                     Log.i(LOG_TAG, "VM change is already completed successfully."
                             + "Have to revert VM back to " + mNewVMNumber + " again.");
                     mPhone.setVoiceMailNumber(
@@ -679,8 +594,7 @@
                 }
                 if (mFwdChangesRequireRollback) {
                     Log.i(LOG_TAG, "Requested to rollback Fwd changes.");
-                    final CallForwardInfo[] prevFwdSettings =
-                        prevSettings.forwardingSettings;
+                    final CallForwardInfo[] prevFwdSettings = prevSettings.getForwardingSettings();
                     if (prevFwdSettings != null) {
                         Map<Integer, AsyncResult> results =
                             mForwardingChangeResults;
@@ -791,7 +705,7 @@
             if (DBG) log("onActivityResult: vm provider cfg result " +
                     (fwdNum != null ? "has" : " does not have") + " forwarding number");
             saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(),
-                    new VoiceMailProviderSettings(vmNum, fwdNum, fwdNumTime));
+                    new VoicemailProviderSettings(vmNum, fwdNum, fwdNumTime));
             return;
         }
 
@@ -830,8 +744,8 @@
 
         saveVoiceMailAndForwardingNumber(
                 getCurrentVoicemailProviderKey(),
-                new VoiceMailProviderSettings(mSubMenuVoicemailSettings.getPhoneNumber(),
-                        FWD_SETTINGS_DONT_TOUCH)
+                new VoicemailProviderSettings(mSubMenuVoicemailSettings.getPhoneNumber(),
+                        VoicemailProviderSettings.NO_FORWARDING)
         );
     }
 
@@ -876,28 +790,29 @@
         }
     }
 
-    private void saveVoiceMailAndForwardingNumber(String key,
-            VoiceMailProviderSettings newSettings) {
+    private void saveVoiceMailAndForwardingNumber(
+            String key, VoicemailProviderSettings newSettings) {
         if (DBG) log("saveVoiceMailAndForwardingNumber: " + newSettings.toString());
-        mNewVMNumber = newSettings.voicemailNumber;
+        mNewVMNumber = newSettings.getVoicemailNumber();
         // empty vm number == clearing the vm number ?
         if (mNewVMNumber == null) {
             mNewVMNumber = "";
         }
 
-        mNewFwdSettings = newSettings.forwardingSettings;
-        if (DBG) log("newFwdNumber " +
-                String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
+        mNewFwdSettings = newSettings.getForwardingSettings();
+        if (DBG) log("newFwdNumber "
+                + String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
                 + " settings");
 
         // No fwd settings on CDMA
         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             if (DBG) log("ignoring forwarding setting since this is CDMA phone");
-            mNewFwdSettings = FWD_SETTINGS_DONT_TOUCH;
+            mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
         }
 
-        //throw a warning if the vm is the same and we do not touch forwarding.
-        if (mNewVMNumber.equals(mOldVmNumber) && mNewFwdSettings == FWD_SETTINGS_DONT_TOUCH) {
+        //Throw a warning if the voicemail is the same and we did not change forwarding.
+        if (mNewVMNumber.equals(mOldVmNumber)
+                && mNewFwdSettings == VoicemailProviderSettings.NO_FORWARDING) {
             showVMDialog(MSG_VM_NOCHANGE);
             return;
         }
@@ -910,10 +825,11 @@
             mReadingSettingsForDefaultProvider =
                     mPreviousVMProviderKey.equals(DEFAULT_VM_PROVIDER_KEY);
             if (DBG) log("Reading current forwarding settings");
-            mForwardingReadResults = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
-            for (int i = 0; i < FORWARDING_SETTINGS_REASONS.length; i++) {
-                mForwardingReadResults[i] = null;
-                mPhone.getCallForwardingOption(FORWARDING_SETTINGS_REASONS[i],
+            int numSettingsReasons = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS.length;
+            mForwardingReadResults = new CallForwardInfo[numSettingsReasons];
+            for (int i = 0; i < mForwardingReadResults.length; i++) {
+                mPhone.getCallForwardingOption(
+                        VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[i],
                         mGetOptionComplete.obtainMessage(EVENT_FORWARDING_GET_COMPLETED, i, 0));
             }
             showDialogIfForeground(VOICEMAIL_FWD_READING_DIALOG);
@@ -979,7 +895,7 @@
             if (DBG) Log.d(LOG_TAG, "Creating default info for " + idx);
             fi = new CallForwardInfo();
             fi.status = 0;
-            fi.reason = FORWARDING_SETTINGS_REASONS[idx];
+            fi.reason = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[idx];
             fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
         } else {
             // if there is not a forwarding number, ensure the entry is set to "not active."
@@ -1004,7 +920,7 @@
             dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
             if (mReadingSettingsForDefaultProvider) {
                 maybeSaveSettingsForVoicemailProvider(DEFAULT_VM_PROVIDER_KEY,
-                        new VoiceMailProviderSettings(this.mOldVmNumber,
+                        new VoicemailProviderSettings(this.mOldVmNumber,
                                 mForwardingReadResults));
                 mReadingSettingsForDefaultProvider = false;
             }
@@ -1050,7 +966,7 @@
     private void saveVoiceMailAndForwardingNumberStage2() {
         mForwardingChangeResults = null;
         mVoicemailChangeResult = null;
-        if (mNewFwdSettings != FWD_SETTINGS_DONT_TOUCH) {
+        if (mNewFwdSettings != VoicemailProviderSettings.NO_FORWARDING) {
             resetForwardingChangeState();
             for (int i = 0; i < mNewFwdSettings.length; i++) {
                 CallForwardInfo fi = mNewFwdSettings[i];
@@ -1931,11 +1847,11 @@
      * Later on these will be used when the user switches a provider.
      */
     private void maybeSaveSettingsForVoicemailProvider(String key,
-            VoiceMailProviderSettings newSettings) {
+            VoicemailProviderSettings newSettings) {
         if (mVoicemailProviders == null) {
             return;
         }
-        final VoiceMailProviderSettings curSettings = loadSettingsForVoiceMailProvider(key);
+        final VoicemailProviderSettings curSettings = loadSettingsForVoiceMailProvider(key);
         if (newSettings.equals(curSettings)) {
             if (DBG) {
                 log("maybeSaveSettingsForVoicemailProvider:"
@@ -1945,10 +1861,10 @@
         }
         if (DBG) log("Saving settings for " + key + ": " + newSettings.toString());
         Editor editor = mPerProviderSavedVMNumbers.edit();
-        editor.putString(key + VM_NUMBER_TAG, newSettings.voicemailNumber);
+        editor.putString(key + VM_NUMBER_TAG, newSettings.getVoicemailNumber());
         String fwdKey = key + FWD_SETTINGS_TAG;
-        CallForwardInfo[] s = newSettings.forwardingSettings;
-        if (s != FWD_SETTINGS_DONT_TOUCH) {
+        CallForwardInfo[] s = newSettings.getForwardingSettings();
+        if (s != VoicemailProviderSettings.NO_FORWARDING) {
             editor.putInt(fwdKey + FWD_SETTINGS_LENGTH_TAG, s.length);
             for (int i = 0; i < s.length; i++) {
                 final String settingKey = fwdKey + FWD_SETTING_TAG + String.valueOf(i);
@@ -1972,7 +1888,7 @@
      * and forwarding number to the stored one. Otherwise we will bring up provider's configuration
      * UI.
      */
-    private VoiceMailProviderSettings loadSettingsForVoiceMailProvider(String key) {
+    private VoicemailProviderSettings loadSettingsForVoiceMailProvider(String key) {
         final String vmNumberSetting = mPerProviderSavedVMNumbers.getString(key + VM_NUMBER_TAG,
                 null);
         if (vmNumberSetting == null) {
@@ -1981,7 +1897,7 @@
             return null;
         }
 
-        CallForwardInfo[] cfi = FWD_SETTINGS_DONT_TOUCH;
+        CallForwardInfo[] cfi = VoicemailProviderSettings.NO_FORWARDING;
         String fwdKey = key + FWD_SETTINGS_TAG;
         final int fwdLen = mPerProviderSavedVMNumbers.getInt(fwdKey + FWD_SETTINGS_LENGTH_TAG, 0);
         if (fwdLen > 0) {
@@ -2003,7 +1919,7 @@
             }
         }
 
-        VoiceMailProviderSettings settings =  new VoiceMailProviderSettings(vmNumberSetting, cfi);
+        VoicemailProviderSettings settings =  new VoicemailProviderSettings(vmNumberSetting, cfi);
         if (DBG) log("Loaded settings for " + key + ": " + settings.toString());
         return settings;
     }
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index eb74956..106484b 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -442,13 +442,10 @@
         switch (id) {
             case R.id.deleteButton: {
                 mDigits.getText().clear();
-                // TODO: The framework forgets to clear the pressed
-                // status of disabled button. Until this is fixed,
-                // clear manually the pressed status. b/2133127
-                mDelete.setPressed(false);
                 return true;
             }
             case R.id.zero: {
+                removePreviousDigitIfPossible();
                 keyPressed(KeyEvent.KEYCODE_PLUS);
                 return true;
             }
@@ -623,4 +620,16 @@
 
         mDelete.setEnabled(notEmpty);
     }
+
+    /**
+     * Remove the digit just before the current position. Used by various long pressed callbacks
+     * to remove the digit that was populated as a result of the short click.
+     */
+    private void removePreviousDigitIfPossible() {
+        final int currentPosition = mDigits.getSelectionStart();
+        if (currentPosition > 0) {
+            mDigits.setSelection(currentPosition);
+            mDigits.getText().delete(currentPosition - 1, currentPosition);
+        }
+    }
 }
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index ca8acc8..2c57b47 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -331,7 +331,7 @@
         }
 
         // Enable enhanced 4G LTE mode settings depending on whether exists on platform
-        if (!ImsManager.isEnhanced4gLteModeSettingEnabledByPlatform(this)) {
+        if (!ImsManager.isVolteEnabledByPlatform(this)) {
             Preference pref = prefSet.findPreference(BUTTON_4G_LTE_KEY);
             if (pref != null) {
                 prefSet.removePreference(pref);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c9eeeaf..58b8599 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -245,13 +245,13 @@
 
                 case CMD_ANSWER_RINGING_CALL:
                     request = (MainThreadRequest) msg.obj;
-                    long answer_subId = ((Long)request.argument).longValue();
+                    int answer_subId = ((Integer)request.argument).intValue();
                     answerRingingCallInternal(answer_subId);
                     break;
 
                 case CMD_END_CALL:
                     request = (MainThreadRequest) msg.obj;
-                    long end_subId = ((Long)request.argument).longValue();
+                    int end_subId = ((Integer)request.argument).intValue();
                     final boolean hungUp;
                     int phoneType = getPhone(end_subId).getPhoneType();
                     if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
@@ -716,7 +716,7 @@
     }
 
     // returns phone associated with the subId.
-    private Phone getPhone(long subId) {
+    private Phone getPhone(int subId) {
         return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
     }
     //
@@ -727,7 +727,7 @@
         dialForSubscriber(getPreferredVoiceSubscription(), number);
     }
 
-    public void dialForSubscriber(long subId, String number) {
+    public void dialForSubscriber(int subId, String number) {
         if (DBG) log("dial: " + number);
         // No permission check needed here: This is just a wrapper around the
         // ACTION_DIAL intent, which is available to any app since it puts up
@@ -751,7 +751,7 @@
         callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
     }
 
-    public void callForSubscriber(long subId, String callingPackage, String number) {
+    public void callForSubscriber(int subId, String callingPackage, String number) {
         if (DBG) log("call: " + number);
 
         // This is just a wrapper around the ACTION_CALL intent, but we still
@@ -799,7 +799,7 @@
      * End a call based on the call state of the subId
      * @return true is a call was ended
      */
-    public boolean endCallForSubscriber(long subId) {
+    public boolean endCallForSubscriber(int subId) {
         enforceCallPermission();
         return (Boolean) sendRequest(CMD_END_CALL, new Long(subId), null);
     }
@@ -808,7 +808,7 @@
         answerRingingCallForSubscriber(getDefaultSubscription());
     }
 
-    public void answerRingingCallForSubscriber(long subId) {
+    public void answerRingingCallForSubscriber(int subId) {
         if (DBG) log("answerRingingCall...");
         // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
         // but that can probably wait till the big TelephonyManager API overhaul.
@@ -830,7 +830,7 @@
      * than sendRequestAsync(), and right now we don't actually *need* that
      * return value, so let's just return void for now.
      */
-    private void answerRingingCallInternal(long subId) {
+    private void answerRingingCallInternal(int subId) {
         final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
         if (hasRingingCall) {
             final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
@@ -866,7 +866,7 @@
         return isOffhookForSubscriber(getDefaultSubscription());
     }
 
-    public boolean isOffhookForSubscriber(long subId) {
+    public boolean isOffhookForSubscriber(int subId) {
         return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
     }
 
@@ -874,7 +874,7 @@
         return (isRingingForSubscriber(getDefaultSubscription()));
     }
 
-    public boolean isRingingForSubscriber(long subId) {
+    public boolean isRingingForSubscriber(int subId) {
         return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
     }
 
@@ -882,7 +882,7 @@
         return isIdleForSubscriber(getDefaultSubscription());
     }
 
-    public boolean isIdleForSubscriber(long subId) {
+    public boolean isIdleForSubscriber(int subId) {
         return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
     }
 
@@ -895,7 +895,7 @@
         return supplyPinForSubscriber(getDefaultSubscription(), pin);
     }
 
-    public boolean supplyPinForSubscriber(long subId, String pin) {
+    public boolean supplyPinForSubscriber(int subId, String pin) {
         int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
     }
@@ -904,7 +904,7 @@
         return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
     }
 
-    public boolean supplyPukForSubscriber(long subId, String puk, String pin) {
+    public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
         int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
     }
@@ -914,7 +914,7 @@
         return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
     }
 
-    public int[] supplyPinReportResultForSubscriber(long subId, String pin) {
+    public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
         enforceModifyPermission();
         final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
         checkSimPin.start();
@@ -926,7 +926,7 @@
         return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
     }
 
-    public int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin) {
+    public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
         enforceModifyPermission();
         final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
         checkSimPuk.start();
@@ -1037,7 +1037,7 @@
 
     }
 
-    public void updateServiceLocationForSubscriber(long subId) {
+    public void updateServiceLocationForSubscriber(int subId) {
         // No permission check needed here: this call is harmless, and it's
         // needed for the ServiceState.requestStateUpdate() call (which is
         // already intentionally exposed to 3rd parties.)
@@ -1048,7 +1048,7 @@
         return isRadioOnForSubscriber(getDefaultSubscription());
     }
 
-    public boolean isRadioOnForSubscriber(long subId) {
+    public boolean isRadioOnForSubscriber(int subId) {
         return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
     }
 
@@ -1057,7 +1057,7 @@
 
     }
 
-    public void toggleRadioOnOffForSubscriber(long subId) {
+    public void toggleRadioOnOffForSubscriber(int subId) {
         enforceModifyPermission();
         getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
     }
@@ -1066,7 +1066,7 @@
         return setRadioForSubscriber(getDefaultSubscription(), turnOn);
     }
 
-    public boolean setRadioForSubscriber(long subId, boolean turnOn) {
+    public boolean setRadioForSubscriber(int subId, boolean turnOn) {
         enforceModifyPermission();
         if ((getPhone(subId).getServiceState().getState() !=
                 ServiceState.STATE_POWER_OFF) != turnOn) {
@@ -1107,7 +1107,7 @@
         return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
     }
 
-    public boolean setRadioPowerForSubscriber(long subId, boolean turnOn) {
+    public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
         enforceModifyPermission();
         getPhone(subId).setRadioPower(turnOn);
         return true;
@@ -1116,7 +1116,7 @@
     // FIXME: subId version needed
     public boolean enableDataConnectivity() {
         enforceModifyPermission();
-        long subId = SubscriptionManager.getDefaultDataSubId();
+        int subId = SubscriptionManager.getDefaultDataSubId();
         getPhone(subId).setDataEnabled(true);
         return true;
     }
@@ -1124,14 +1124,14 @@
     // FIXME: subId version needed
     public boolean disableDataConnectivity() {
         enforceModifyPermission();
-        long subId = SubscriptionManager.getDefaultDataSubId();
+        int subId = SubscriptionManager.getDefaultDataSubId();
         getPhone(subId).setDataEnabled(false);
         return true;
     }
 
     // FIXME: subId version needed
     public boolean isDataConnectivityPossible() {
-        long subId = SubscriptionManager.getDefaultDataSubId();
+        int subId = SubscriptionManager.getDefaultDataSubId();
         return getPhone(subId).isDataConnectivityPossible();
     }
 
@@ -1139,7 +1139,7 @@
         return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
     }
 
-    public boolean handlePinMmiForSubscriber(long subId, String dialString) {
+    public boolean handlePinMmiForSubscriber(int subId, String dialString) {
         enforceModifyPermission();
         return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
     }
@@ -1148,7 +1148,7 @@
         return getCallStateForSubscriber(getDefaultSubscription());
     }
 
-    public int getCallStateForSubscriber(long subId) {
+    public int getCallStateForSubscriber(int subId) {
         return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
     }
 
@@ -1191,7 +1191,7 @@
         enableLocationUpdatesForSubscriber(getDefaultSubscription());
     }
 
-    public void enableLocationUpdatesForSubscriber(long subId) {
+    public void enableLocationUpdatesForSubscriber(int subId) {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
         getPhone(subId).enableLocationUpdates();
@@ -1202,7 +1202,7 @@
         disableLocationUpdatesForSubscriber(getDefaultSubscription());
     }
 
-    public void disableLocationUpdatesForSubscriber(long subId) {
+    public void disableLocationUpdatesForSubscriber(int subId) {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
         getPhone(subId).disableLocationUpdates();
@@ -1401,7 +1401,7 @@
         return getActivePhoneTypeForSubscriber(getDefaultSubscription());
     }
 
-    public int getActivePhoneTypeForSubscriber(long subId) {
+    public int getActivePhoneTypeForSubscriber(int subId) {
         return getPhone(subId).getPhoneType();
     }
 
@@ -1413,7 +1413,7 @@
 
     }
 
-    public int getCdmaEriIconIndexForSubscriber(long subId) {
+    public int getCdmaEriIconIndexForSubscriber(int subId) {
         return getPhone(subId).getCdmaEriIconIndex();
     }
 
@@ -1426,7 +1426,7 @@
         return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
     }
 
-    public int getCdmaEriIconModeForSubscriber(long subId) {
+    public int getCdmaEriIconModeForSubscriber(int subId) {
         return getPhone(subId).getCdmaEriIconMode();
     }
 
@@ -1437,14 +1437,14 @@
         return getCdmaEriTextForSubscriber(getDefaultSubscription());
     }
 
-    public String getCdmaEriTextForSubscriber(long subId) {
+    public String getCdmaEriTextForSubscriber(int subId) {
         return getPhone(subId).getCdmaEriText();
     }
 
     /**
      * Returns the CDMA MDN.
      */
-    public String getCdmaMdn(long subId) {
+    public String getCdmaMdn(int subId) {
         enforceModifyPermissionOrCarrierPrivilege();
         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             return getPhone(subId).getLine1Number();
@@ -1456,7 +1456,7 @@
     /**
      * Returns the CDMA MIN.
      */
-    public String getCdmaMin(long subId) {
+    public String getCdmaMin(int subId) {
         enforceModifyPermissionOrCarrierPrivilege();
         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             return getPhone(subId).getCdmaMin();
@@ -1482,7 +1482,7 @@
     /**
      * Returns the unread count of voicemails for a subId
      */
-    public int getVoiceMessageCountForSubscriber( long subId) {
+    public int getVoiceMessageCountForSubscriber( int subId) {
         return getPhone(subId).getVoiceMessageCount();
     }
 
@@ -1500,7 +1500,7 @@
      * Returns the network type for a subId
      */
     @Override
-    public int getNetworkTypeForSubscriber(long subId) {
+    public int getNetworkTypeForSubscriber(int subId) {
         return getPhone(subId).getServiceState().getDataNetworkType();
     }
 
@@ -1516,7 +1516,7 @@
      * Returns the data network type for a subId
      */
     @Override
-    public int getDataNetworkTypeForSubscriber(long subId) {
+    public int getDataNetworkTypeForSubscriber(int subId) {
         return getPhone(subId).getServiceState().getDataNetworkType();
     }
 
@@ -1532,7 +1532,7 @@
      * Returns the Voice network type for a subId
      */
     @Override
-    public int getVoiceNetworkTypeForSubscriber(long subId) {
+    public int getVoiceNetworkTypeForSubscriber(int subId) {
         return getPhone(subId).getServiceState().getVoiceNetworkType();
     }
 
@@ -1547,7 +1547,7 @@
     /**
      * @return true if a ICC card is present for a slotId
      */
-    public boolean hasIccCardUsingSlotId(long slotId) {
+    public boolean hasIccCardUsingSlotId(int slotId) {
         return getPhone(slotId).getIccCard().hasIccCard();
     }
 
@@ -1563,7 +1563,7 @@
         return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
     }
 
-    public int getLteOnCdmaModeForSubscriber(long subId) {
+    public int getLteOnCdmaModeForSubscriber(int subId) {
         return getPhone(subId).getLteOnCdmaMode();
     }
 
@@ -1575,11 +1575,11 @@
      * {@hide}
      * Returns Default subId, 0 in the case of single standby.
      */
-    private long getDefaultSubscription() {
+    private int getDefaultSubscription() {
         return SubscriptionManager.getDefaultSubId();
     }
 
-    private long getPreferredVoiceSubscription() {
+    private int getPreferredVoiceSubscription() {
         return SubscriptionManager.getDefaultVoiceSubId();
     }
 
@@ -1927,7 +1927,7 @@
             mPhone.getContext().getPackageManager(), intent);
     }
 
-    private String getIccId(long subId) {
+    private String getIccId(int subId) {
         UiccCard card = getPhone(subId).getUiccCard();
         if (card == null) {
             loge("getIccId: No UICC");
@@ -1942,7 +1942,7 @@
     }
 
     @Override
-    public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) {
+    public void enableSimplifiedNetworkSettingsForSubscriber(int subId, boolean enable) {
         enforceModifyPermissionOrCarrierPrivilege();
 
         String iccId = getIccId(subId);
@@ -1959,7 +1959,7 @@
     }
 
     @Override
-    public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) {
+    public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(int subId) {
         enforceReadPermission();
         String iccId = getIccId(subId);
         if (iccId != null) {
@@ -1970,7 +1970,7 @@
     }
 
     @Override
-    public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) {
+    public void setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number) {
         enforceModifyPermissionOrCarrierPrivilege();
 
         String iccId = getIccId(subId);
@@ -1994,7 +1994,7 @@
     }
 
     @Override
-    public String getLine1NumberForDisplay(long subId) {
+    public String getLine1NumberForDisplay(int subId) {
         enforceReadPermission();
 
         String iccId = getIccId(subId);
@@ -2006,7 +2006,7 @@
     }
 
     @Override
-    public String getLine1AlphaTagForDisplay(long subId) {
+    public String getLine1AlphaTagForDisplay(int subId) {
         enforceReadPermission();
 
         String iccId = getIccId(subId);
diff --git a/src/com/android/phone/SimContacts.java b/src/com/android/phone/SimContacts.java
index 8192795..ac76d4f 100644
--- a/src/com/android/phone/SimContacts.java
+++ b/src/com/android/phone/SimContacts.java
@@ -245,7 +245,7 @@
     protected Uri resolveIntent() {
         final Intent intent = getIntent();
         if (intent.hasExtra("subscription_id")) {
-            final long subId = intent.getLongExtra("subscription_id", -1);
+            final int subId = intent.getIntExtra("subscription_id", -1);
             intent.setData(Uri.parse("content://icc/adn/subId/" + subId));
         } else {
             intent.setData(Uri.parse("content://icc/adn"));
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index c48812c..ba6871c 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -1,6 +1,7 @@
 package com.android.phone.settings;
 
 import android.content.ActivityNotFoundException;
+import android.content.Context;
 import android.content.Intent;
 import android.net.sip.SipManager;
 import android.os.Bundle;
@@ -45,6 +46,7 @@
     private String LOG_TAG = PhoneAccountSettingsFragment.class.getSimpleName();
 
     private TelecomManager mTelecomManager;
+    private Context mApplicationContext;
 
     private AccountSelectionPreference mDefaultOutgoingAccount;
     private AccountSelectionPreference mSelectCallAssistant;
@@ -59,6 +61,7 @@
         super.onCreate(icicle);
 
         mTelecomManager = TelecomManager.from(getActivity());
+        mApplicationContext = getActivity().getApplicationContext();
     }
 
     @Override
@@ -216,11 +219,11 @@
     private synchronized void handleSipReceiveCallsOption(boolean isEnabled) {
         mSipSharedPreferences.setReceivingCallsEnabled(isEnabled);
 
-        SipUtil.useSipToReceiveIncomingCalls(getActivity(), isEnabled);
+        SipUtil.useSipToReceiveIncomingCalls(mApplicationContext, isEnabled);
 
         // Restart all Sip services to ensure we reflect whether we are receiving calls.
         SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
-        sipAccountRegistry.restartSipService(getActivity());
+        sipAccountRegistry.restartSipService(mApplicationContext);
     }
 
     /**
diff --git a/src/com/android/phone/settings/VoicemailProviderSettings.java b/src/com/android/phone/settings/VoicemailProviderSettings.java
new file mode 100644
index 0000000..fc2e7f8
--- /dev/null
+++ b/src/com/android/phone/settings/VoicemailProviderSettings.java
@@ -0,0 +1,127 @@
+/**
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.phone.settings;
+
+import android.telephony.PhoneNumberUtils;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandsInterface;
+
+/**
+ * Settings for a voicemail provider, including any conditional forwarding information.
+ */
+public class VoicemailProviderSettings {
+
+    // If no forwarding is set, leave the forwarding number unchanged from its current value.
+    public static final CallForwardInfo[] NO_FORWARDING = null;
+
+    /**
+     * Reasons for the forwarding settings we are going to save.
+     */
+    public static final int [] FORWARDING_SETTINGS_REASONS = new int[] {
+        CommandsInterface.CF_REASON_UNCONDITIONAL,
+        CommandsInterface.CF_REASON_BUSY,
+        CommandsInterface.CF_REASON_NO_REPLY,
+        CommandsInterface.CF_REASON_NOT_REACHABLE
+    };
+
+    private String mVoicemailNumber;
+    private CallForwardInfo[] mForwardingSettings;
+
+    /**
+     * Constructs settings object, setting all conditional forwarding to the specified number
+     */
+    public VoicemailProviderSettings(
+            String voicemailNumber, String forwardingNumber, int timeSeconds) {
+        mVoicemailNumber = voicemailNumber;
+        if (forwardingNumber == null || forwardingNumber.length() == 0) {
+            mForwardingSettings = NO_FORWARDING;
+        } else {
+            mForwardingSettings = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
+            for (int i = 0; i < mForwardingSettings.length; i++) {
+                CallForwardInfo fi = new CallForwardInfo();
+                mForwardingSettings[i] = fi;
+                fi.reason = FORWARDING_SETTINGS_REASONS[i];
+                fi.status = (fi.reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ? 0 : 1;
+                fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
+                fi.toa = PhoneNumberUtils.TOA_International;
+                fi.number = forwardingNumber;
+                fi.timeSeconds = timeSeconds;
+            }
+        }
+    }
+
+    public VoicemailProviderSettings(String voicemailNumber, CallForwardInfo[] infos) {
+        mVoicemailNumber = voicemailNumber;
+        mForwardingSettings = infos;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+        if (!(o instanceof VoicemailProviderSettings)) {
+            return false;
+        }
+
+        final VoicemailProviderSettings v = (VoicemailProviderSettings) o;
+        return ((mVoicemailNumber == null && v.getVoicemailNumber() == null)
+                || (mVoicemailNumber != null && mVoicemailNumber.equals(v.getVoicemailNumber()))
+                        && forwardingSettingsEqual(mForwardingSettings, v.getForwardingSettings()));
+    }
+
+    @Override
+    public String toString() {
+        return mVoicemailNumber + ((mForwardingSettings == null) ? ""
+                : ", " + mForwardingSettings.toString());
+    }
+
+    public String getVoicemailNumber() {
+        return mVoicemailNumber;
+    }
+
+    public CallForwardInfo[] getForwardingSettings() {
+        return mForwardingSettings;
+    }
+
+    private boolean forwardingSettingsEqual(CallForwardInfo[] infos1, CallForwardInfo[] infos2) {
+        if (infos1 == infos2) {
+            return true;
+        }
+        if (infos1 == null || infos2 == null) {
+            return false;
+        }
+        if (infos1.length != infos2.length) {
+            return false;
+        }
+
+        for (int i = 0; i < infos1.length; i++) {
+            CallForwardInfo i1 = infos1[i];
+            CallForwardInfo i2 = infos2[i];
+            if (i1.status != i2.status
+                    || i1.reason != i2.reason
+                    || i1.serviceClass != i2.serviceClass
+                    || i1.toa != i2.toa
+                    || i1.number != i2.number
+                    || i1.timeSeconds != i2.timeSeconds) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6980df8..5a480a5 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -92,7 +92,7 @@
                     makePstnPhoneAccountHandleWithPrefix(mPhone, dummyPrefix, isEmergency);
 
             // Populate the phone account data.
-            long subId = mPhone.getSubId();
+            int subId = mPhone.getSubId();
             int color = 0;
             int slotId = SubscriptionManager.INVALID_SLOT_ID;
             String line1Number = mTelephonyManager.getLine1NumberForSubscriber(subId);
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 9d309dc..91f164b 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -387,7 +387,7 @@
             if (accountHandle.getId() != null) {
                 try {
                     int phoneId = SubscriptionController.getInstance().getPhoneId(
-                            Long.parseLong(accountHandle.getId()));
+                            Integer.parseInt(accountHandle.getId()));
                     return PhoneFactory.getPhone(phoneId);
                 } catch (NumberFormatException e) {
                     Log.w(this, "Could not get subId from account: " + accountHandle.getId());