Implemented reverting of vm and forwarding settings when we revert
to the previous vm provider in case of failure.
This is *likely* a fix for:
http://b/issue?id=2248473
and
http://b/issue?id=2248656
Added "Please contact your carrier if this problem persists" to errors as requested by
mafoster.
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8081d8f..d9bd43f 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -308,6 +308,8 @@
     <string name="reading_settings">Reading settings\u2026</string>
     <!-- Toast in Call settings dialog while settings are being saved -->
     <string name="updating_settings">Updating settings\u2026</string>
+    <!-- Toast in Call settings dialog while settings are being reverted -->
+    <string name="reverting_settings">Reverting settings\u2026</string>
     <!-- Status message displayed in the "Call settings error" dialog -->
     <string name="response_error">Unexpected response from network.</string>
     <!-- Status message displayed in the "Call settings error" dialog -->
@@ -348,9 +350,9 @@
     <!-- Call settings screen, Set voicemail number dialog text -->
     <string name="vm_changed">Voicemail number changed.</string>
     <!-- Call settings screen, Set voicemail number dialog text -->
-    <string name="vm_change_failed">Voicemail number change unsuccessful.</string>
+    <string name="vm_change_failed">Voicemail number change unsuccessful.\nPlease contact your carrier if this problem persists.</string>
     <!-- Call settings screen, displayed when vm provider supplied forwarding number change fails-->
-    <string name="fw_change_failed">Forwarding number change unsuccessful.</string>
+    <string name="fw_change_failed">Forwarding number change unsuccessful.\nPlease contact your carrier if this problem persists.</string>
     <!-- Call settings screen, displayed when forwarding number read fails-->
     <string name="fw_get_in_vm_failed">Failed to retrieve and save current forwarding number settings.\nDo you want to switch to the new provider anyway?</string>
     <!-- Call settings screen, Set voicemail number dialog text -->
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 4284f01..f6e6a9f 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -168,6 +168,7 @@
     private static final int VOICEMAIL_DIALOG_CONFIRM = 600;
     private static final int VOICEMAIL_FWD_SAVING_DIALOG = 601;
     private static final int VOICEMAIL_FWD_READING_DIALOG = 602;
+    private static final int VOICEMAIL_REVERTING_DIALOG = 603;
 
     // status message sent back from handlers
     private static final int MSG_OK = 100;
@@ -321,6 +322,24 @@
     boolean mChangingVMorFwdDueToProviderChange = false;
 
     /**
+     * True if we are in the process of vm & fwd number change and vm has already been changed.
+     * This is used to decide what to do in case of rollback.
+     */
+    boolean mVMChangeCompletedSuccesfully = false;
+
+    /**
+     * True if we are in the process of vm & fwd number change and fwd# has already been changed.
+     * This is used to decide what to do in case of rollback.
+     */
+    boolean mFwdChangeCompletedSuccesfully = false;
+
+    /**
+     * Id of error msg to display to user once we are done reverting the VM provider to the previous
+     * one.
+     */
+    int mVMOrFwdSetError = 0;
+
+    /**
      * Data about discovered voice mail settings providers.
      * Is populated by querying which activities can handle ACTION_CONFIGURE_VOICEMAIL.
      * They key in this map is package name + activity name.
@@ -403,7 +422,10 @@
             final String newProviderKey = (String)objValue;
             if (DBG) log("VM provider changes to " + newProviderKey + " from " +
                     mPreviousVMProviderKey);
-
+            if (mPreviousVMProviderKey.equals(newProviderKey)) {
+                if (DBG) log("No change ");
+                return true;
+            }
             updateVMPreferenceWidgets(newProviderKey);
 
             final VoiceMailProviderSettings newProviderSettings =
@@ -487,8 +509,53 @@
     private void switchToPreviousVoicemailProvider() {
         if (DBG) log("switchToPreviousVoicemailProvider " + mPreviousVMProviderKey);
         if (mPreviousVMProviderKey != null) {
-            mVoicemailProviders.setValue(mPreviousVMProviderKey);
-            updateVMPreferenceWidgets(mPreviousVMProviderKey);
+            if (mVMChangeCompletedSuccesfully || mFwdChangeCompletedSuccesfully) { // we have to revert with carrier
+                showDialog(VOICEMAIL_REVERTING_DIALOG);
+                VoiceMailProviderSettings prevSettings =
+                    loadSettingsForVoiceMailProvider(mPreviousVMProviderKey);
+                if (mVMChangeCompletedSuccesfully) {
+                    mNewVMNumber = prevSettings.voicemailNumber;
+                    if (DBG) log("have to revert VM to " + mNewVMNumber);
+                    mPhone.setVoiceMailNumber(
+                            mPhone.getVoiceMailAlphaTag().toString(),
+                            mNewVMNumber,
+                            Message.obtain(mRevertOptionComplete, EVENT_VOICEMAIL_CHANGED));
+                }
+                if (mFwdChangeCompletedSuccesfully) {
+                    if (DBG) log("have to revert fwd");
+                    final CallForwardInfo[] prevFwdSettings = prevSettings.forwardingSettings;
+                    if (prevFwdSettings != null) {
+                        mForwardingChangeResults = new AsyncResult[mNewFwdSettings.length];
+                        for (int i = 0; i < prevFwdSettings.length; i++) {
+                            CallForwardInfo fi = prevFwdSettings[i];
+                            if (DBG) log("Reverting fwd #: " + i + ": " + fi.toString());
+                            mPhone.setCallForwardingOption(
+                                    (fi.status == 1 ?
+                                            CommandsInterface.CF_ACTION_REGISTRATION :
+                                            CommandsInterface.CF_ACTION_DISABLE),
+                                    fi.reason,
+                                    fi.number,
+                                    fi.timeSeconds,
+                                    mRevertOptionComplete.obtainMessage(
+                                            EVENT_FORWARDING_CHANGED, i, 0));
+                         }
+                    }
+                }
+            } else {
+                if (DBG) log("No need to revert");
+                onRevertDone();
+            }
+        }
+    }
+
+    void onRevertDone() {
+        if (DBG) log("Flipping provider key back to " + mPreviousVMProviderKey);
+        mVoicemailProviders.setValue(mPreviousVMProviderKey);
+        updateVMPreferenceWidgets(mPreviousVMProviderKey);
+        updateVoiceNumberField();
+        if (mVMOrFwdSetError != 0) {
+            showVMDialog(mVMOrFwdSetError);
+            mVMOrFwdSetError = 0;
         }
     }
 
@@ -621,7 +688,9 @@
         }
 
         maybeSaveSettingsForVoicemailProvider(key, newSettings);
-
+        mVMChangeCompletedSuccesfully = false;
+        mFwdChangeCompletedSuccesfully = false;
+        mVMOrFwdSetError = 0;
         // If we are switching to a non default provider - save previous forwarding
         // settings
         if (!key.equals(mPreviousVMProviderKey) &&
@@ -745,7 +814,11 @@
              showDialog(VOICEMAIL_FWD_SAVING_DIALOG);
         } else {
             if (DBG) log("Not touching fwd #");
+            setVMNumberWithCarrier();
         }
+    }
+
+    void setVMNumberWithCarrier() {
         if (DBG) log("save voicemail #: " + mNewVMNumber);
         mPhone.setVoiceMailNumber(
                 mPhone.getVoiceMailAlphaTag().toString(),
@@ -760,29 +833,44 @@
         @Override
         public void handleMessage(Message msg) {
             AsyncResult result = (AsyncResult) msg.obj;
-            // query to make sure we're looking at the same data as that in the network.
             switch (msg.what) {
                 case EVENT_VOICEMAIL_CHANGED:
-                    if (DBG) log("VM change complete msg");
                     mVoicemailChangeResult = result;
+                    mVMChangeCompletedSuccesfully = checkVMChangeSuccess() == null;
+                    if (DBG) log("VM change complete msg, VM change done = " +
+                            String.valueOf(mVMChangeCompletedSuccesfully));
                     break;
                 case EVENT_FORWARDING_CHANGED:
-                    if (DBG) log("FWD change complete msg " + msg.arg1);
                     mForwardingChangeResults[msg.arg1] = result;
+                    final boolean completed = checkForwardingCompleted();
+                    if (completed) {
+                        mFwdChangeCompletedSuccesfully = checkFwdChangeSuccess() == null;
+                    }
+                    if (DBG) log("FWD change complete msg " + msg.arg1 + ", completed=" +
+                            String.valueOf(completed) + ", succesfully=" +
+                            String.valueOf(mFwdChangeCompletedSuccesfully));
+                    if (mFwdChangeCompletedSuccesfully) {
+                        setVMNumberWithCarrier();
+                    }
                     break;
                 default:
                     // TODO: should never reach this, may want to throw exception
             }
             // Check if we are done - either we are only setting vm and that is done
             // or we are setting both vm and fwd and both are done.
-            boolean done = mVoicemailChangeResult != null;
-            if (done && mForwardingChangeResults != null) {
-                for (int i = 0; i < mForwardingChangeResults.length; i++) {
-                    if (mForwardingChangeResults[i] == null) {
-                        done = false;
-                        break;
+            final boolean vmCompleted = mVoicemailChangeResult != null;
+
+            boolean done = false;
+            if (mForwardingChangeResults != null) {
+                if (checkForwardingCompleted()) {
+                    if (!mFwdChangeCompletedSuccesfully) {
+                        done = true;
+                    } else {
+                        done = vmCompleted;
                     }
                 }
+            } else {
+                done = vmCompleted;
             }
             if (done) {
                 if (DBG) log("All VM related changes done");
@@ -794,6 +882,80 @@
         }
     };
 
+    /**
+     * Callback to handle option revert completions
+     */
+    private Handler mRevertOptionComplete = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult result = (AsyncResult) msg.obj;
+            switch (msg.what) {
+                case EVENT_VOICEMAIL_CHANGED:
+                    mVoicemailChangeResult = result;
+                    if (DBG) log("VM revert complete msg");
+                    break;
+                case EVENT_FORWARDING_CHANGED:
+                    mForwardingChangeResults[msg.arg1] = result;
+                    if (DBG) log("FWD revert complete msg ");
+                    break;
+                default:
+                    // TODO: should never reach this, may want to throw exception
+            }
+            final boolean done =
+                (!mVMChangeCompletedSuccesfully || mVoicemailChangeResult != null) &&
+                (!mFwdChangeCompletedSuccesfully || checkForwardingCompleted());
+            if (done) {
+                if (DBG) log("All VM reverts done");
+                dismissDialog(VOICEMAIL_REVERTING_DIALOG);
+                onRevertDone();
+            }
+        }
+    };
+
+    /**
+     * @return true if forwarding change has completed
+     */
+    private boolean checkForwardingCompleted() {
+        if (mForwardingChangeResults == null) {
+            return true;
+        }
+        for (int i = 0; i < mForwardingChangeResults.length; i++) {
+            if (mForwardingChangeResults[i] == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+    /**
+     * @return error string or null if successful
+     */
+    private String checkFwdChangeSuccess() {
+        for (int i = 0; i < mForwardingChangeResults.length; i++) {
+            if (mForwardingChangeResults[i].exception != null) {
+                final String msg = mForwardingChangeResults[i].exception.getMessage();
+                if (msg == null) {
+                    return "";
+                }
+                return msg;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return error string or null if succesfull
+     */
+    private String checkVMChangeSuccess() {
+        if (mVoicemailChangeResult.exception != null) {
+            final String msg = mVoicemailChangeResult.exception.getMessage();
+            if (msg == null) {
+                return "";
+            }
+            return msg;
+        }
+        return null;
+    }
+
     private void handleSetVMOrFwdMessage() {
         if (DBG) {
             log("handleSetVMMessage: set VM request complete");
@@ -802,22 +964,22 @@
         boolean fwdFailure = false;
         String exceptionMessage = "";
         if (mForwardingChangeResults != null) {
-            for (int i = 0; i < mForwardingChangeResults.length; i++) {
-                if (mForwardingChangeResults[i].exception != null) {
-                    exceptionMessage = mForwardingChangeResults[i].exception.getMessage();
-                    success = false;
-                    fwdFailure = true;
-                    break;
-                }
+            exceptionMessage = checkFwdChangeSuccess();
+            if (exceptionMessage != null) {
+                success = false;
+                fwdFailure = true;
             }
         }
-        if (success && mVoicemailChangeResult.exception != null) {
-            exceptionMessage = mVoicemailChangeResult.exception.getMessage();
-            success = false;
+        if (success) {
+            exceptionMessage = checkVMChangeSuccess();
+            if (exceptionMessage != null) {
+                success = false;
+            }
         }
         if (success) {
             if (DBG) log("change VM success!");
             handleVMAndFwdSetSuccess(MSG_VM_OK);
+            updateVoiceNumberField();
         } else {
             if (fwdFailure) {
                 log("change FW failed: " + exceptionMessage);
@@ -827,15 +989,18 @@
                 handleVMOrFwdSetError(MSG_VM_EXCEPTION);
             }
         }
-        updateVoiceNumberField();
     }
 
     private void handleVMOrFwdSetError(int msgId) {
         if (mChangingVMorFwdDueToProviderChange) {
+            mVMOrFwdSetError = msgId;
+            mChangingVMorFwdDueToProviderChange = false;
             switchToPreviousVoicemailProvider();
+            return;
         }
         mChangingVMorFwdDueToProviderChange = false;
         showVMDialog(msgId);
+        updateVoiceNumberField();
     }
 
     private void handleVMAndFwdSetSuccess(int msgId) {
@@ -931,14 +1096,16 @@
             dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
 
             return dialog;
-        } else if (id == VOICEMAIL_FWD_SAVING_DIALOG || id == VOICEMAIL_FWD_READING_DIALOG) {
+        } else if (id == VOICEMAIL_FWD_SAVING_DIALOG || id == VOICEMAIL_FWD_READING_DIALOG ||
+                id == VOICEMAIL_REVERTING_DIALOG) {
             ProgressDialog dialog = new ProgressDialog(this);
             dialog.setTitle(getText(R.string.updating_title));
             dialog.setIndeterminate(true);
             dialog.setCancelable(false);
             dialog.setMessage(getText(
-                    id == VOICEMAIL_FWD_SAVING_DIALOG ?
-                            R.string.updating_settings : R.string.reading_settings));
+                    id == VOICEMAIL_FWD_SAVING_DIALOG ? R.string.updating_settings :
+                    (id == VOICEMAIL_REVERTING_DIALOG ? R.string.reverting_settings :
+                    R.string.reading_settings)));
             return dialog;
         }