Throttle view notifications

Only post the notification per loader instance, per raw contact.
This means:
- When you open a contact card, we post the notification for the contact.
- If the contact card reloads itself, we do *not* post the notification,
  as we use the same loader instance for this.
- (If you close the contact card and re-open it, we do post the notifictaion,
  of course)
- If you're opening cotact card, and the current cotnact got a new raw contact
  as a result of background sync, we *do* post the notification for the new
  raw contact, not not for existing raw contacts.

Bug 5153847

Change-Id: Id8ef9ece7f2aa991d0c625072b7c58f839e05bb3
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index ceaa246..4b4d50d 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -23,6 +23,7 @@
 import com.android.contacts.util.StreamItemPhotoEntry;
 import com.google.android.collect.Lists;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Sets;
 
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -62,6 +63,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Loads a single Contact and all it constituent RawContacts.
@@ -76,7 +78,7 @@
     private Result mContact;
     private ForceLoadContentObserver mObserver;
     private boolean mDestroyed;
-
+    private final Set<Long> mNotifiedRawContactIds = Sets.newHashSet();
 
     public interface Listener {
         public void onContactLoaded(Result contact);
@@ -1115,6 +1117,11 @@
         Context context = getContext();
         for (Entity entity : mContact.getEntities()) {
             final ContentValues entityValues = entity.getEntityValues();
+            final long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
+            if (mNotifiedRawContactIds.contains(rawContactId)) {
+                continue; // Already notified for this raw contact.
+            }
+            mNotifiedRawContactIds.add(rawContactId);
             final String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
             final String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
             final AccountType accountType = AccountTypeManager.getInstance(context ).getAccountType(
@@ -1122,7 +1129,6 @@
             final String serviceName = accountType.getViewContactNotifyServiceClassName();
             final String resPackageName = accountType.resPackageName;
             if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(resPackageName)) {
-                final long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
                 final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
                 final Intent intent = new Intent();
                 intent.setClassName(resPackageName, serviceName);