Merge "Change the code around vCard import + Service."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cbff3ae..f8fccae 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -242,6 +242,13 @@
             <intent-filter>
                 <action android:name="android.intent.action.SEARCH" />
                 <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="vnd.android.cursor.dir/contact" android:host="com.android.contacts" />
+            </intent-filter>
+
+            <intent-filter>
+                <action android:name="com.android.contacts.action.FILTER_CONTACTS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="vnd.android.cursor.dir/contact" android:host="com.android.contacts" />
             </intent-filter>
 
             <meta-data android:name="android.app.searchable"
@@ -311,24 +318,6 @@
             </intent-filter>
         </activity>
 
-        <!-- The contacts search/filter UI -->
-        <activity android:name=".activities.ContactSearchActivity"
-            android:theme="@style/ContactsSearchTheme"
-            android:windowSoftInputMode="stateAlwaysVisible"
-        >
-            <intent-filter>
-                <action android:name="com.android.contacts.action.FILTER_CONTACTS" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.cursor.dir/contact" android:host="com.android.contacts" />
-            </intent-filter>
-
-        </activity>
-
-        <!-- The contacts search/filter UI -->
-        <activity-alias android:name="SearchResultsActivity"
-            android:targetActivity=".activities.ContactBrowserActivity">
-        </activity-alias>
-
         <!-- Used to set options -->
         <activity
             android:name=".preference.ContactsPreferenceActivity"
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/activities/ContactSearchActivity.java b/src/com/android/contacts/activities/ContactSearchActivity.java
deleted file mode 100644
index 615f182..0000000
--- a/src/com/android/contacts/activities/ContactSearchActivity.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.activities;
-
-import com.android.contacts.R;
-import com.android.contacts.interactions.ContactDeletionInteraction;
-import com.android.contacts.interactions.PhoneNumberInteraction;
-import com.android.contacts.list.ContactBrowseListContextMenuAdapter;
-import com.android.contacts.list.ContactBrowseListFragment;
-import com.android.contacts.list.ContactsIntentResolver;
-import com.android.contacts.list.ContactsRequest;
-import com.android.contacts.list.DefaultContactBrowseListFragment;
-import com.android.contacts.list.DirectoryListLoader;
-import com.android.contacts.list.OnContactBrowserActionListener;
-import com.android.contacts.widget.SearchEditText;
-import com.android.contacts.widget.SearchEditText.OnFilterTextListener;
-
-import android.app.Activity;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-
-public class ContactSearchActivity extends Activity {
-
-    private ContactsIntentResolver mIntentResolver;
-    private ContactsRequest mRequest;
-    private ContactBrowseListFragment mListFragment;
-    private PhoneNumberInteraction mPhoneNumberCallInteraction;
-    private PhoneNumberInteraction mSendTextMessageInteraction;
-    private ContactDeletionInteraction mContactDeletionInteraction;
-    private SearchEditText mSearchEditText;
-
-    public ContactSearchActivity() {
-        mIntentResolver = new ContactsIntentResolver(this);
-    }
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        // Extract relevant information from the intent
-        mRequest = mIntentResolver.resolveIntent(getIntent());
-        if (!mRequest.isValid()) {
-            setResult(RESULT_CANCELED);
-            finish();
-            return;
-        }
-
-        setTitle(mRequest.getActivityTitle());
-
-        setContentView(R.layout.contacts_search_content);
-
-        if (mListFragment == null) {
-            mListFragment = createContactSearchFragment();
-            getFragmentManager().openTransaction()
-                    .replace(R.id.list_container, mListFragment)
-                    .commit();
-        }
-
-        mSearchEditText = (SearchEditText)findViewById(R.id.search_src_text);
-        mSearchEditText.setText(mRequest.getQueryString());
-        mSearchEditText.setOnFilterTextListener(new OnFilterTextListener() {
-            @Override
-            public void onFilterChange(String queryString) {
-                mListFragment.setQueryString(queryString);
-            }
-
-            @Override
-            public void onCancelSearch() {
-                finish();
-            }
-        });
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mSearchEditText.requestFocus();
-    }
-
-
-    private ContactBrowseListFragment createContactSearchFragment() {
-        DefaultContactBrowseListFragment fragment = new DefaultContactBrowseListFragment();
-        fragment.setOnContactListActionListener(new ContactBrowserActionListener());
-        fragment.setContextMenuAdapter(new ContactBrowseListContextMenuAdapter(fragment));
-        fragment.setSearchMode(true);
-        fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DEFAULT);
-        fragment.setAizyEnabled(false);
-        fragment.setSelectionVisible(true);
-        return fragment;
-    }
-
-    private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
-        @Override
-        public void onViewContactAction(Uri contactLookupUri) {
-            startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
-        }
-
-        @Override
-        public void onCreateNewContactAction() {
-        }
-
-        @Override
-        public void onEditContactAction(Uri contactLookupUri) {
-            Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
-            Bundle extras = getIntent().getExtras();
-            if (extras != null) {
-                intent.putExtras(extras);
-            }
-            startActivity(intent);
-        }
-
-        @Override
-        public void onAddToFavoritesAction(Uri contactUri) {
-            ContentValues values = new ContentValues(1);
-            values.put(Contacts.STARRED, 1);
-            getContentResolver().update(contactUri, values, null, null);
-        }
-
-        @Override
-        public void onRemoveFromFavoritesAction(Uri contactUri) {
-            ContentValues values = new ContentValues(1);
-            values.put(Contacts.STARRED, 0);
-            getContentResolver().update(contactUri, values, null, null);
-        }
-
-        @Override
-        public void onCallContactAction(Uri contactUri) {
-            getPhoneNumberCallInteraction().startInteraction(contactUri);
-        }
-
-        @Override
-        public void onSmsContactAction(Uri contactUri) {
-            getSendTextMessageInteraction().startInteraction(contactUri);
-        }
-
-        @Override
-        public void onDeleteContactAction(Uri contactUri) {
-            getContactDeletionInteraction().deleteContact(contactUri);
-        }
-
-        @Override
-        public void onFinishAction() {
-            onBackPressed();
-        }
-
-        @Override
-        public void onInvalidSelection() {
-        }
-    }
-
-    private PhoneNumberInteraction getPhoneNumberCallInteraction() {
-        if (mPhoneNumberCallInteraction == null) {
-            mPhoneNumberCallInteraction = new PhoneNumberInteraction(this, false, null);
-        }
-        return mPhoneNumberCallInteraction;
-    }
-
-    private PhoneNumberInteraction getSendTextMessageInteraction() {
-        if (mSendTextMessageInteraction == null) {
-            mSendTextMessageInteraction = new PhoneNumberInteraction(this, true, null);
-        }
-        return mSendTextMessageInteraction;
-    }
-
-    private ContactDeletionInteraction getContactDeletionInteraction() {
-        if (mContactDeletionInteraction == null) {
-            mContactDeletionInteraction = new ContactDeletionInteraction();
-            mContactDeletionInteraction.attachToActivity(this);
-        }
-        return mContactDeletionInteraction;
-    }
-}
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;
     }
diff --git a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
index 4cc9cc8..9d7f926 100644
--- a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
@@ -60,8 +60,6 @@
 
     private static final String CONTACT_LIST_ACTIVITY_CLASS_NAME =
             "com.android.contacts.activities.ContactBrowserActivity";
-    private static final String SEARCH_RESULTS_ACTIVITY_CLASS_NAME =
-            "com.android.contacts.SearchResultsActivity";
     private static final String MULTIPLE_PHONE_PICKER_ACTIVITY_CLASS_NAME =
             "com.android.contacts.MultiplePhonePickerActivity";
 
@@ -331,19 +329,16 @@
             case ACTION_SEARCH_CONTACT: {
                 Intent intent = new Intent(Intent.ACTION_SEARCH);
                 intent.putExtra(SearchManager.QUERY, "a");
+                intent.setType(Contacts.CONTENT_TYPE);
                 startSearchResultActivity(intent);
                 break;
             }
             case ACTION_SEARCH_EMAIL: {
-                Intent intent = new Intent(Intent.ACTION_SEARCH);
-                intent.putExtra(Insert.EMAIL, "a");
-                startSearchResultActivity(intent);
+                Toast.makeText(this, "Unsupported", Toast.LENGTH_SHORT).show();
                 break;
             }
             case ACTION_SEARCH_PHONE: {
-                Intent intent = new Intent(Intent.ACTION_SEARCH);
-                intent.putExtra(Insert.PHONE, "800");
-                startSearchResultActivity(intent);
+                Toast.makeText(this, "Unsupported", Toast.LENGTH_SHORT).show();
                 break;
             }
             case SEARCH_SUGGESTION_CLICKED_CALL_BUTTON: {
@@ -574,8 +569,6 @@
     }
 
     private void startSearchResultActivity(Intent intent) {
-        intent.setComponent(
-                new ComponentName(ANDROID_CONTACTS_PACKAGE, SEARCH_RESULTS_ACTIVITY_CLASS_NAME));
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(intent);
     }