Automatically adding suggested contact to My Contacts on switch

If the user creates a new contact, gets an aggregation
suggestion and clicks on it - we switch to the selected
contact, but now also adding it to the My Contacts group
if applicable.

Bug: 3140599
Change-Id: I29a18fde42f62297236d1eae88fb149cc7a204b7
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 724fdac..0b6213f 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -164,6 +164,7 @@
             Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
             intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                     | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            intent.putExtra(ContactEditorFragment.INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY, "");
 
             // Pass on all the data that has been entered so far
             if (values != null && values.size() != 0) {
diff --git a/src/com/android/contacts/views/editor/ContactEditorFragment.java b/src/com/android/contacts/views/editor/ContactEditorFragment.java
index 77e61be..54c7452 100644
--- a/src/com/android/contacts/views/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/views/editor/ContactEditorFragment.java
@@ -117,6 +117,12 @@
     private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions";
 
     /**
+     * An intent extra that forces the editor to add the edited contact
+     * to the default group (e.g. "My Contacts").
+     */
+    public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
+
+    /**
      * Modes that specify what the AsyncTask has to perform after saving
      */
     private interface SaveMode {
@@ -217,6 +223,8 @@
     private long mAggregationSuggestionsRawContactId;
     private View mAggregationSuggestionView;
 
+    private boolean mAutoAddToDefaultGroup;
+
     public ContactEditorFragment() {
     }
 
@@ -295,6 +303,8 @@
         mAction = action;
         mLookupUri = lookupUri;
         mIntentExtras = intentExtras;
+        mAutoAddToDefaultGroup = mIntentExtras != null
+                && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
     }
 
     public void setListener(Listener value) {
@@ -503,6 +513,7 @@
             });
 
             mContent.addView(editor);
+
             editor.setState(entity, source, mViewIdGenerator);
 
             if (editor instanceof RawContactEditorView) {
@@ -520,6 +531,8 @@
                     }
                 });
 
+                rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup);
+
                 if (rawContactId == mAggregationSuggestionsRawContactId) {
                     acquireAggregationSuggestions(rawContactEditor);
                 }
diff --git a/src/com/android/contacts/views/editor/RawContactEditorView.java b/src/com/android/contacts/views/editor/RawContactEditorView.java
index 609132c..c49f20f 100644
--- a/src/com/android/contacts/views/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/views/editor/RawContactEditorView.java
@@ -18,21 +18,22 @@
 
 import com.android.contacts.R;
 import com.android.contacts.model.BaseAccountType;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
 import com.android.contacts.model.BaseAccountType.DataKind;
 import com.android.contacts.model.BaseAccountType.EditType;
+import com.android.contacts.model.EntityDelta;
 import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.model.EntityModifier;
+import com.android.contacts.views.GroupMetaDataLoader;
 
 import android.content.Context;
 import android.content.Entity;
 import android.database.Cursor;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -75,6 +76,10 @@
     private boolean mExpanded = true;
 
     private long mRawContactId = -1;
+    private boolean mAutoAddToDefaultGroup = true;
+    private Cursor mGroupMetaData;
+    private DataKind mGroupMembershipKind;
+    private EntityDelta mState;
 
     public RawContactEditorView(Context context) {
         super(context);
@@ -130,6 +135,8 @@
      */
     @Override
     public void setState(EntityDelta state, BaseAccountType source, ViewIdGenerator vig) {
+        mState = state;
+
         // Remove any existing sections
         mFields.removeAllViews();
 
@@ -168,11 +175,11 @@
         mFields.setVisibility(View.VISIBLE);
         mName.setVisibility(View.VISIBLE);
 
-        DataKind groupMembershipKind = source.getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
-        if (groupMembershipKind != null) {
+        mGroupMembershipKind = source.getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
+        if (mGroupMembershipKind != null) {
             mGroupMembershipView = (GroupMembershipView)mInflater.inflate(
                     R.layout.item_group_membership, mFields, false);
-            mGroupMembershipView.setKind(groupMembershipKind);
+            mGroupMembershipView.setKind(mGroupMembershipKind);
         }
 
         // Create editor sections for each possible data kind
@@ -207,15 +214,78 @@
         if (mGroupMembershipView != null) {
             mFields.addView(mGroupMembershipView);
         }
+
+        addToDefaultGroupIfNeeded();
     }
 
     @Override
     public void setGroupMetaData(Cursor groupMetaData) {
+        mGroupMetaData = groupMetaData;
+        addToDefaultGroupIfNeeded();
         if (mGroupMembershipView != null) {
             mGroupMembershipView.setGroupMetaData(groupMetaData);
         }
     }
 
+    public void setAutoAddToDefaultGroup(boolean flag) {
+        this.mAutoAddToDefaultGroup = flag;
+    }
+
+    /**
+     * If automatic addition to the default group was requested (see
+     * {@link #setAutoAddToDefaultGroup}, checks if the raw contact is in any
+     * group and if it is not adds it to the default group (in case of Google
+     * contacts that's "My Contacts").
+     */
+    private void addToDefaultGroupIfNeeded() {
+        if (!mAutoAddToDefaultGroup || mGroupMetaData == null || mGroupMetaData.isClosed()
+                || mState == null) {
+            return;
+        }
+
+        boolean hasGroupMembership = false;
+        ArrayList<ValuesDelta> entries = mState.getMimeEntries(GroupMembership.CONTENT_ITEM_TYPE);
+        if (entries != null) {
+            for (ValuesDelta values : entries) {
+                Long id = values.getAsLong(GroupMembership.GROUP_ROW_ID);
+                if (id != null && id.longValue() != 0) {
+                    hasGroupMembership = true;
+                    break;
+                }
+            }
+        }
+
+        if (!hasGroupMembership) {
+            long defaultGroupId = getDefaultGroupId();
+            if (defaultGroupId != -1) {
+                ValuesDelta entry = EntityModifier.insertChild(mState, mGroupMembershipKind);
+                entry.put(GroupMembership.GROUP_ROW_ID, defaultGroupId);
+            }
+        }
+    }
+
+    /**
+     * Returns the default group (e.g. "My Contacts") for the current raw contact's
+     * account.  Returns -1 if there is no such group.
+     */
+    private long getDefaultGroupId() {
+        String accountType = mState.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
+        String accountName = mState.getValues().getAsString(RawContacts.ACCOUNT_NAME);
+        mGroupMetaData.moveToPosition(-1);
+        while (mGroupMetaData.moveToNext()) {
+            String name = mGroupMetaData.getString(GroupMetaDataLoader.ACCOUNT_NAME);
+            String type = mGroupMetaData.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
+            if (name.equals(accountName) && type.equals(accountType)) {
+                long groupId = mGroupMetaData.getLong(GroupMetaDataLoader.GROUP_ID);
+                if (!mGroupMetaData.isNull(GroupMetaDataLoader.AUTO_ADD)
+                            && mGroupMetaData.getInt(GroupMetaDataLoader.AUTO_ADD) != 0) {
+                    return groupId;
+                }
+            }
+        }
+        return -1;
+    }
+
     public TextFieldsEditorView getNameEditor() {
         return mName;
     }