When voicemail number is unknown, show voicemail setup on notification click.

1. In NotificationMgr changed intent when no voicemail number is found so
that it will trigger opening of the voicemail screen.
2. In CallFeaturesSetting added new intent extra to indicate we just want
to open the voicemail settings.  This intent is used by Google Voice, and
I wanted to ensure that the code path for that case is not changed, hence
the new extra.

Bug: 17795834
Change-Id: I62b3d6c99558dc698565459aa0d43cd4efdd6fdd
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 9956397..1d054a6 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -131,6 +131,12 @@
      */
     public static final String IGNORE_PROVIDER_EXTRA = "com.android.phone.ProviderToIgnore";
 
+    /**
+     * String Extra put into ACTION_ADD_VOICEMAIL to indicate that the voicemail setup screen should
+     * be opened.
+     */
+    public static final String SETUP_VOICEMAIL_EXTRA = "com.android.phone.SetupVoicemail";
+
     // string constants
     private static final String NUM_PROJECTION[] = {CommonDataKinds.Phone.NUMBER};
 
@@ -287,6 +293,11 @@
      */
     private boolean mShowVoicemailPreference = false;
 
+    /**
+     * Used to indicate that the voicemail setup screen should be shown.
+     */
+    private boolean mSetupVoicemail = false;
+
     /*
      * Click Listeners, handle click based on objects attached to UI.
      */
@@ -713,6 +724,9 @@
         } else {
             saveVoiceMailAndForwardingNumberStage2();
         }
+
+        // Refresh the MWI indicator if it is already showing.
+        PhoneGlobals.getInstance().refreshMwiIndicator(mSubscriptionInfoHelper.getSubId());
     }
 
     private final Handler mGetOptionComplete = new Handler() {
@@ -1107,6 +1121,8 @@
         // ACTION_ADD_VOICEMAIL action.
         mShowVoicemailPreference = (icicle == null) &&
                 TextUtils.equals(getIntent().getAction(), ACTION_ADD_VOICEMAIL);
+        mSetupVoicemail = mShowVoicemailPreference &&
+                getIntent().getBooleanExtra(SETUP_VOICEMAIL_EXTRA, false);
 
         mSubscriptionInfoHelper = new SubscriptionInfoHelper(getIntent());
         mSubscriptionInfoHelper.setActionBarTitle(
@@ -1268,7 +1284,10 @@
         // We only bring up the dialog the first time we are called (not after orientation change)
         if (mShowVoicemailPreference) {
             if (DBG) log("ACTION_ADD_VOICEMAIL Intent is thrown");
-            if (mVoicemailProviders.hasMoreThanOneVoicemailProvider()) {
+            if (mSetupVoicemail) {
+                simulatePreferenceClick(mVoicemailSettingsScreen);
+                mSetupVoicemail = false;
+            } else if (mVoicemailProviders.hasMoreThanOneVoicemailProvider()) {
                 if (DBG) log("Voicemail data has more than one provider.");
                 simulatePreferenceClick(mVoicemailProviders);
             } else {
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 65f7594..f026442 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -41,6 +41,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.widget.Toast;
 
@@ -48,8 +49,12 @@
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.TelephonyCapabilities;
 import com.android.phone.settings.VoicemailNotificationSettingsUtil;
+import com.android.phone.settings.VoicemailProviderSettingsUtil;
 
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * NotificationManager-related utility code for the Phone app.
@@ -95,6 +100,9 @@
     // used to track the notification of selected network unavailable
     private boolean mSelectedUnavailableNotify = false;
 
+    // used to track whether the message waiting indicator is visible, per subscription id.
+    private ArrayMap<Integer, Boolean> mMwiVisible = new ArrayMap<Integer, Boolean>();
+
     /**
      * Private constructor (this is a singleton).
      * @see #init(PhoneGlobals)
@@ -236,12 +244,52 @@
     };
 
     /**
+     * Re-creates the message waiting indicator (voicemail) notification if it is showing.  Used to
+     * refresh the voicemail intent on the indicator when the user changes it via the voicemail
+     * settings screen.  The voicemail notification sound is suppressed.
+     *
+     * @param subId The subscription Id.
+     */
+    /* package */ void refreshMwi(int subId) {
+        // In a single-sim device, subId can be -1 which means "no sub id".  In this case we will
+        // reference the single subid stored in the mMwiVisible map.
+        if (subId == SubscriptionInfoHelper.NO_SUB_ID) {
+            if (mMwiVisible.keySet().size() == 1) {
+                Set<Integer> keySet = mMwiVisible.keySet();
+                Iterator<Integer> keyIt = keySet.iterator();
+                if (!keyIt.hasNext()) {
+                    return;
+                }
+                subId = keyIt.next();
+            }
+        }
+        if (mMwiVisible.containsKey(subId)) {
+            boolean mwiVisible = mMwiVisible.get(subId);
+            if (mwiVisible) {
+                updateMwi(subId, mwiVisible, false /* enableNotificationSound */);
+            }
+        }
+    }
+
+    /**
      * Updates the message waiting indicator (voicemail) notification.
      *
      * @param visible true if there are messages waiting
      */
     /* package */ void updateMwi(int subId, boolean visible) {
+        updateMwi(subId, visible, true /* enableNotificationSound */);
+    }
+
+    /**
+     * Updates the message waiting indicator (voicemail) notification.
+     *
+     * @param subId the subId to update.
+     * @param visible true if there are messages waiting
+     * @param enableNotificationSound {@code true} if the notification sound should be played.
+     */
+    void updateMwi(int subId, boolean visible, boolean enableNotificationSound) {
         if (DBG) log("updateMwi(): subId " + subId + " update to " + visible);
+        mMwiVisible.put(subId, visible);
 
         if (!PhoneGlobals.sVoiceCapable) {
             // Do not show the message waiting indicator on devices which are not voice capable.
@@ -296,28 +344,44 @@
                 notificationTitle = String.format(titleFormat, vmCount);
             }
 
+            // This pathway only applies to PSTN accounts; only SIMS have subscription ids.
+            PhoneAccountHandle phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(phone);
+
+            Intent intent;
             String notificationText;
-            if (mTelephonyManager.getPhoneCount() > 1) {
-                notificationText = subInfo.getDisplayName().toString();
+            if (TextUtils.isEmpty(vmNumber)) {
+                notificationText = mContext.getString(
+                        R.string.notification_voicemail_no_vm_number);
+
+                // If the voicemail number if unknown, instead of calling voicemail, take the user
+                // to the voicemail settings.
+                notificationText = mContext.getString(
+                        R.string.notification_voicemail_no_vm_number);
+                intent = new Intent(CallFeaturesSetting.ACTION_ADD_VOICEMAIL);
+                intent.putExtra(CallFeaturesSetting.SETUP_VOICEMAIL_EXTRA, true);
+                intent.putExtra(SubscriptionInfoHelper.SUB_ID_EXTRA, subId);
+                intent.setClass(mContext, CallFeaturesSetting.class);
             } else {
-                if (TextUtils.isEmpty(vmNumber)) {
-                    notificationText = mContext.getString(
-                            R.string.notification_voicemail_no_vm_number);
+                if (mTelephonyManager.getPhoneCount() > 1) {
+                    notificationText = subInfo.getDisplayName().toString();
                 } else {
                     notificationText = String.format(
                             mContext.getString(R.string.notification_voicemail_text_format),
                             PhoneNumberUtils.formatNumber(vmNumber));
                 }
+                intent = new Intent(
+                        Intent.ACTION_CALL, Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "",
+                        null));
+                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
             }
 
-            // This pathway only applies to PSTN accounts; only SIMS have subscription ids.
-            PhoneAccountHandle phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(phone);
-            Intent intent = new Intent(
-                    Intent.ACTION_CALL, Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null));
-            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
             PendingIntent pendingIntent =
                     PendingIntent.getActivity(mContext, subId /* requestCode */, intent, 0);
-            Uri ringtoneUri = VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
+            Uri ringtoneUri = null;
+
+            if (enableNotificationSound) {
+                ringtoneUri = VoicemailNotificationSettingsUtil.getRingtoneUri(mPhone);
+            }
 
             Notification.Builder builder = new Notification.Builder(mContext);
             builder.setSmallIcon(resId)
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 03827ce..2fcce90 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -924,6 +924,15 @@
     }
 
     /**
+     * Triggers a refresh of the message waiting (voicemail) indicator.
+     *
+     * @param subId the subscription id we should refresh the notification for.
+     */
+    public void refreshMwiIndicator(int subId) {
+        notificationMgr.refreshMwi(subId);
+    }
+
+    /**
      * "Call origin" may be used by Contacts app to specify where the phone call comes from.
      * Currently, the only permitted value for this extra is {@link #ALLOWED_EXTRA_CALL_ORIGIN}.
      * Any other value will be ignored, to make sure that malicious apps can't trick the in-call
diff --git a/src/com/android/phone/SubscriptionInfoHelper.java b/src/com/android/phone/SubscriptionInfoHelper.java
index 347d00e..f325b1a 100644
--- a/src/com/android/phone/SubscriptionInfoHelper.java
+++ b/src/com/android/phone/SubscriptionInfoHelper.java
@@ -36,10 +36,10 @@
  * helping extract this info and perform common operations using this info.
  */
 public class SubscriptionInfoHelper {
-    private static final int NO_SUB_ID = -1;
+    public static final int NO_SUB_ID = -1;
 
     // Extra on intent containing the id of a subscription.
-    private static final String SUB_ID_EXTRA =
+    public static final String SUB_ID_EXTRA =
             "com.android.phone.settings.SubscriptionInfoHelper.SubscriptionId";
     // Extra on intent containing the label of a subscription.
     private static final String SUB_LABEL_EXTRA =