Merge "Ensure duplicate voicemails are ignored, add msim to voicemail." into mnc-dev
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 1d6c559..1368286 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -18,10 +18,12 @@
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.Context;
+import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
 
 import android.util.Base64;
 
+import com.android.phone.PhoneUtils;
 import com.android.phone.common.mail.Address;
 import com.android.phone.common.mail.Body;
 import com.android.phone.common.mail.BodyPart;
@@ -57,10 +59,12 @@
     private ImapFolder mFolder;
     private ImapStore mImapStore;
     private Context mContext;
+    private PhoneAccountHandle mPhoneAccount;
 
     public ImapHelper(Context context, Account account) {
         try {
             mContext = context;
+            mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(account.name);
             TempDirectory.setTempDirectory(context);
 
             AccountManager accountManager = AccountManager.get(context);
@@ -260,6 +264,7 @@
                     boolean isRead = Arrays.asList(message.getFlags()).contains(Flag.SEEN);
 
                     return Voicemail.createForInsertion(time, number)
+                            .setPhoneAccount(mPhoneAccount)
                             .setSourcePackage(mContext.getPackageName())
                             .setSourceData(message.getUid())
                             .setIsRead(isRead)
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 7e6d645..2d18ee7 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -33,6 +33,7 @@
 import com.android.phone.vvm.omtp.OmtpConstants;
 import com.android.phone.vvm.omtp.sync.OmtpVvmSyncAccountManager;
 import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService.OmtpVvmSyncAdapter;
+import com.android.phone.vvm.omtp.sync.VoicemailsQueryHelper;
 
 /**
  * Receive SMS messages and send for processing by the OMTP visual voicemail source.
@@ -86,12 +87,13 @@
             case OmtpConstants.NEW_MESSAGE:
                 Voicemail voicemail = Voicemail.createForInsertion(
                         message.getTimestampMillis(), message.getSender())
+                        .setPhoneAccount(mPhoneAccount)
                         .setSourceData(message.getId())
                         .setDuration(message.getLength())
                         .setSourcePackage(mContext.getPackageName())
                         .build();
-
-                VoicemailContract.Voicemails.insert(mContext, voicemail);
+                VoicemailsQueryHelper queryHelper = new VoicemailsQueryHelper(mContext);
+                queryHelper.insertIfUnique(voicemail);
                 break;
             case OmtpConstants.MAILBOX_UPDATE:
                 // Needs a total resync
diff --git a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
index 151afed..f844e36 100644
--- a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
+++ b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
@@ -23,16 +23,19 @@
 import android.net.Uri;
 import android.provider.VoicemailContract;
 import android.provider.VoicemailContract.Voicemails;
+import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
+import android.util.Log;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 /**
  * Construct a queries to interact with the voicemails table.
  */
 public class VoicemailsQueryHelper {
+    private static final String TAG = "VoicemailsQueryHelper";
+
     final static String[] PROJECTION = new String[] {
             Voicemails._ID,              // 0
             Voicemails.SOURCE_DATA,      // 1
@@ -168,4 +171,56 @@
         contentValues.put(Voicemails.IS_READ, "1");
         mContentResolver.update(uri, contentValues, null, null);
     }
+
+
+    /**
+     * Check if a particular voicemail has already been inserted. If not, insert the new voicemail.
+     * @param voicemail The voicemail to insert.
+     */
+    public void insertIfUnique(Voicemail voicemail) {
+        if (isVoicemailUnique(voicemail)) {
+            VoicemailContract.Voicemails.insert(mContext, voicemail);
+        } else {
+            Log.w(TAG, "Voicemail already exists.");
+        }
+    }
+
+    /**
+     * Voicemail is unique if the tuple of (phone account component name, phone account id, source
+     * data) is unique. If the phone account is missing, we also consider this unique since it's
+     * simply an "unknown" account.
+     * @param voicemail The voicemail to check if it is unique.
+     * @return {@code true} if the voicemail is unique, {@code false} otherwise.
+     */
+    private boolean isVoicemailUnique(Voicemail voicemail) {
+        Cursor cursor = null;
+        PhoneAccountHandle phoneAccount = voicemail.getPhoneAccount();
+        if (phoneAccount != null) {
+            String phoneAccountComponentName = phoneAccount.getComponentName().flattenToString();
+            String phoneAccountId = phoneAccount.getId();
+            String sourceData = voicemail.getSourceData();
+            if (phoneAccountComponentName == null || phoneAccountId == null || sourceData == null) {
+                return true;
+            }
+            try {
+                String whereClause =
+                        Voicemails.PHONE_ACCOUNT_COMPONENT_NAME + "=? AND " +
+                        Voicemails.PHONE_ACCOUNT_ID + "=? AND " + Voicemails.SOURCE_DATA + "=?";
+                String[] whereArgs = { phoneAccountComponentName, phoneAccountId, sourceData };
+                cursor = mContentResolver.query(
+                        mSourceUri, PROJECTION, whereClause, whereArgs, null);
+                if (cursor.getCount() == 0) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+            finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+        return true;
+    }
 }