Merge "VVM: Cancel retries when network is lost." into mnc-dev
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 1faf0ee..315929b 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -344,12 +344,8 @@
             startService(intent);
 
             mCM = CallManager.getInstance();
-            boolean hasCdmaPhoneType = false;
             for (Phone phone : PhoneFactory.getPhones()) {
                 mCM.registerPhone(phone);
-                if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
-                    hasCdmaPhoneType = true;
-                }
             }
 
             // Create the NotificationMgr singleton, which is used to display
@@ -358,11 +354,9 @@
 
             mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);
 
-            if (hasCdmaPhoneType) {
-                // Create an instance of CdmaPhoneCallState and initialize it to IDLE
-                cdmaPhoneCallState = new CdmaPhoneCallState();
-                cdmaPhoneCallState.CdmaPhoneCallStateInit();
-            }
+            // Create an instance of CdmaPhoneCallState and initialize it to IDLE
+            cdmaPhoneCallState = new CdmaPhoneCallState();
+            cdmaPhoneCallState.CdmaPhoneCallStateInit();
 
             // before registering for phone state changes
             mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
@@ -962,6 +956,15 @@
     }
 
     /**
+     * Dismisses the message waiting (voicemail) indicator.
+     *
+     * @param subId the subscription id we should dismiss the notification for.
+     */
+    public void clearMwiIndicator(int subId) {
+        notificationMgr.updateMwi(subId, false);
+    }
+
+    /**
      * "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/VvmPhoneStateListener.java b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
similarity index 93%
rename from src/com/android/phone/VvmPhoneStateListener.java
rename to src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
index fb267cd..1b2e34e 100644
--- a/src/com/android/phone/VvmPhoneStateListener.java
+++ b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-package com.android.phone;
+package com.android.phone.vvm.omtp;
 
 import android.content.Context;
 import android.content.Intent;
@@ -23,8 +23,8 @@
 import android.telephony.ServiceState;
 import android.util.Log;
 
-import com.android.phone.vvm.omtp.LocalLogHelper;
-import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.PhoneGlobals;
+import com.android.phone.PhoneUtils;
 import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
 import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
 import com.android.phone.vvm.omtp.sync.VoicemailStatusQueryHelper;
@@ -66,8 +66,8 @@
                             VoicemailContract.Status.CONFIGURATION_STATE_OK,
                             VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
                             VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
-                    PhoneGlobals.getInstance().notificationMgr.updateMwi(
-                            PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount), false);
+                    PhoneGlobals.getInstance().clearMwiIndicator(
+                            PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
                 }
             }
 
@@ -98,6 +98,10 @@
                     mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
                     true /* firstAttempt */));
 
+            if (!OmtpVvmSourceManager.getInstance(mContext).isVvmSourceRegistered(mPhoneAccount)) {
+                return;
+            }
+
             VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
                     VoicemailContract.Status.CONFIGURATION_STATE_OK,
                     VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 1caefe6..3eefbee 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -23,9 +23,11 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
 import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
 
 import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.PhoneGlobals;
 import com.android.phone.PhoneUtils;
 import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.omtp.LocalLogHelper;
@@ -49,6 +51,11 @@
         mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
                 intent.getExtras().getInt(PhoneConstants.PHONE_KEY));
 
+        if (mPhoneAccount == null) {
+            Log.w(TAG, "Received message for null phone account");
+            return;
+        }
+
         if (!VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(mContext, mPhoneAccount)) {
             Log.v(TAG, "Received vvm message for disabled vvm source.");
             return;
@@ -144,6 +151,9 @@
                     mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
                     true /* firstAttempt */);
             mContext.startService(serviceIntent);
+
+            PhoneGlobals.getInstance().clearMwiIndicator(
+                    PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
         } else {
             Log.w(TAG, "Visual voicemail not available for subscriber.");
             // Override default isEnabled setting to false since visual voicemail is unable to
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
index 286dde3..0520098 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
@@ -24,12 +24,12 @@
 
 import com.android.internal.telephony.Phone;
 import com.android.phone.PhoneUtils;
-import com.android.phone.VvmPhoneStateListener;
+import com.android.phone.vvm.omtp.VvmPhoneStateListener;
 
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A singleton class designed to remember the active OMTP visual voicemail sources. Because a
@@ -69,8 +69,10 @@
             mSubscriptionManager = SubscriptionManager.from(context);
             mTelephonyManager = (TelephonyManager)
                     mContext.getSystemService(Context.TELEPHONY_SERVICE);
-            mActiveVvmSources = new HashSet<PhoneAccountHandle>();
-            mPhoneStateListenerMap = new HashMap<PhoneAccountHandle, PhoneStateListener>();
+            mActiveVvmSources = Collections.newSetFromMap(
+                    new ConcurrentHashMap<PhoneAccountHandle, Boolean>(8, 0.9f, 1));
+            mPhoneStateListenerMap =
+                    new ConcurrentHashMap<PhoneAccountHandle, PhoneStateListener>(8, 0.9f, 1);
         }
     }
 
@@ -89,6 +91,13 @@
                 removeSource(phoneAccount);
             }
         }
+
+        // Remove any orphaned phone state listeners as well.
+        for (PhoneAccountHandle phoneAccount : mPhoneStateListenerMap.keySet()) {
+            if (!PhoneUtils.isPhoneAccountActive(mSubscriptionManager, phoneAccount)) {
+                removePhoneStateListener(phoneAccount);
+            }
+        }
     }
 
     public void removeSource(Phone phone) {