Breaking global search support into a separate class and limiting search results to visible contacts only.
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 48cdac8..d8af3da 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -17,7 +17,6 @@
package com.android.providers.contacts;
import com.android.internal.content.SyncStateContentProviderHelper;
-import com.android.internal.database.ArrayListCursor;
import com.android.providers.contacts.OpenHelper.AggregationExceptionColumns;
import com.android.providers.contacts.OpenHelper.Clauses;
import com.android.providers.contacts.OpenHelper.ContactsColumns;
@@ -44,7 +43,6 @@
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteCursor;
@@ -56,7 +54,6 @@
import android.os.RemoteException;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
-import android.provider.Contacts.Intents;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
@@ -71,7 +68,6 @@
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Contacts.AggregationSuggestions;
@@ -80,8 +76,6 @@
import android.util.Log;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
/**
@@ -944,6 +938,7 @@
private ContactAggregator mContactAggregator;
private NameSplitter mNameSplitter;
private LegacyApiSupport mLegacyApiSupport;
+ private GlobalSearchSupport mGlobalSearchSupport;
private ContentValues mValues = new ContentValues();
@@ -963,7 +958,8 @@
final Context context = getContext();
mOpenHelper = getOpenHelper(context);
- mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this);
+ mGlobalSearchSupport = new GlobalSearchSupport(this);
+ mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport);
mContactAggregator = new ContactAggregator(context, mOpenHelper, mAggregationScheduler);
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
@@ -2276,7 +2272,7 @@
}
case SEARCH_SUGGESTIONS: {
- return handleSearchSuggestionsQuery(uri, limit);
+ return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit);
}
case SEARCH_SHORTCUT: {
@@ -2323,279 +2319,6 @@
}
}
-
- public Cursor handleSearchSuggestionsQuery(Uri url, String limit) {
- if (url.getPathSegments().size() <= 1) {
- return null;
- }
-
- final String searchClause = url.getLastPathSegment();
- if (TextUtils.isDigitsOnly(searchClause)) {
- return buildCursorForSearchSuggestionsBasedOnPhoneNumber(searchClause);
- } else {
- return buildCursorForSearchSuggestionsBasedOnName(searchClause, limit);
- }
- }
-
- private static final String[] SEARCH_SUGGESTIONS_BASED_ON_PHONE_NUMBER_COLUMNS = {
- "_id",
- SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_ICON_1,
- SearchManager.SUGGEST_COLUMN_INTENT_DATA,
- SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
- SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
- };
-
- private Cursor buildCursorForSearchSuggestionsBasedOnPhoneNumber(String searchClause) {
- Resources r = getContext().getResources();
- String s;
- int i;
-
- ArrayList<Object> dialNumber = new ArrayList<Object>();
- dialNumber.add(0); // _id
- s = r.getString(com.android.internal.R.string.dial_number_using, searchClause);
- i = s.indexOf('\n');
- if (i < 0) {
- dialNumber.add(s);
- dialNumber.add("");
- } else {
- dialNumber.add(s.substring(0, i));
- dialNumber.add(s.substring(i + 1));
- }
- dialNumber.add(String.valueOf(com.android.internal.R.drawable.call_contact));
- dialNumber.add("tel:" + searchClause);
- dialNumber.add(Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED);
- dialNumber.add(null);
-
- ArrayList<Object> createContact = new ArrayList<Object>();
- createContact.add(1); // _id
- s = r.getString(com.android.internal.R.string.create_contact_using, searchClause);
- i = s.indexOf('\n');
- if (i < 0) {
- createContact.add(s);
- createContact.add("");
- } else {
- createContact.add(s.substring(0, i));
- createContact.add(s.substring(i + 1));
- }
- createContact.add(String.valueOf(com.android.internal.R.drawable.create_contact));
- createContact.add("tel:" + searchClause);
- createContact.add(Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED);
- createContact.add(SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
-
- @SuppressWarnings({"unchecked"}) ArrayList<ArrayList> rows = new ArrayList<ArrayList>();
- rows.add(dialNumber);
- rows.add(createContact);
-
- return new ArrayListCursor(SEARCH_SUGGESTIONS_BASED_ON_PHONE_NUMBER_COLUMNS, rows);
- }
-
- private interface SearchSuggestionQuery {
- public static final String JOIN_RAW_CONTACTS =
- " JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) ";
-
- public static final String JOIN_CONTACTS =
- " JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
-
- public static final String JOIN_MIMETYPES =
- " JOIN mimetypes ON (data.mimetype_id = mimetypes._id AND mimetypes.mimetype IN ('"
- + StructuredName.CONTENT_ITEM_TYPE + "','" + Email.CONTENT_ITEM_TYPE + "','"
- + Phone.CONTENT_ITEM_TYPE + "','" + Organization.CONTENT_ITEM_TYPE + "','"
- + Photo.CONTENT_ITEM_TYPE + "','" + GroupMembership.CONTENT_ITEM_TYPE + "')) ";
-
- // TODO join with groups and ensure that suggestions are from the My Contacts group
- public static final String JOIN_GROUPS = " JOIN groups ON (mimetypes.mimetype='"
- + GroupMembership.CONTENT_ITEM_TYPE + "' " + " AND groups._id = data."
- + GroupMembership.GROUP_ROW_ID + ") ";
-
- public static final String TABLE = "data " + JOIN_RAW_CONTACTS + JOIN_MIMETYPES
- + JOIN_CONTACTS;
-
- public static final String PRESENCE_SQL = "(SELECT MAX(" + Presence.PRESENCE_STATUS
- + ") FROM " + Tables.PRESENCE + " WHERE " + Tables.PRESENCE + "."
- + Presence.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")";
-
- public static final String[] COLUMNS = {
- ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID,
- ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + Contacts.DISPLAY_NAME,
- PRESENCE_SQL + " AS " + Contacts.PRESENCE_STATUS,
- DataColumns.CONCRETE_ID + " AS data_id",
- MimetypesColumns.MIMETYPE,
- Data.IS_SUPER_PRIMARY,
- Data.DATA2,
- };
-
- public static final int CONTACT_ID = 0;
- public static final int DISPLAY_NAME = 1;
- public static final int PRESENCE_STATUS = 2;
- public static final int DATA_ID = 3;
- public static final int MIMETYPE = 4;
- public static final int IS_SUPER_PRIMARY = 5;
- public static final int DATA2 = 6;
- }
-
- private static class SearchSuggestion {
- String contactId;
- boolean titleIsName;
- String organization;
- String email;
- String phoneNumber;
- String photoUri;
- String normalizedName;
- int presence = -1;
- boolean processed;
- String text1;
- String text2;
- String icon1;
- String icon2;
-
- public SearchSuggestion(long contactId) {
- this.contactId = String.valueOf(contactId);
- }
-
- private void process() {
- if (processed) {
- return;
- }
-
- boolean hasOrganization = !TextUtils.isEmpty(organization);
- boolean hasEmail = !TextUtils.isEmpty(email);
- boolean hasPhone = !TextUtils.isEmpty(phoneNumber);
-
- boolean titleIsOrganization = !titleIsName && hasOrganization;
- boolean titleIsEmail = !titleIsName && !titleIsOrganization && hasEmail;
- boolean titleIsPhone = !titleIsName && !titleIsOrganization && !titleIsEmail
- && hasPhone;
-
- if (!titleIsOrganization && hasOrganization) {
- text2 = organization;
- } else if (!titleIsEmail && hasEmail) {
- text2 = email;
- } else if (!titleIsPhone && hasPhone) {
- text2 = phoneNumber;
- }
-
- if (photoUri != null) {
- icon1 = photoUri;
- } else {
- icon1 = String.valueOf(com.android.internal.R.drawable.ic_contact_picture);
- }
-
- if (presence != -1) {
- icon2 = String.valueOf(Presence.getPresenceIconResourceId(presence));
- }
-
- processed = true;
- }
-
- public String getSortKey() {
- if (normalizedName == null) {
- process();
- normalizedName = text1 == null ? "" : NameNormalizer.normalize(text1);
- }
- return normalizedName;
- }
-
- @SuppressWarnings({"unchecked"})
- public ArrayList asList() {
- process();
-
- ArrayList<Object> list = new ArrayList<Object>();
- list.add(contactId);
- list.add(text1);
- list.add(text2);
- list.add(icon1);
- list.add(icon2);
- list.add(contactId);
- list.add(contactId);
- return list;
- }
- }
-
- private static final String[] SEARCH_SUGGESTIONS_BASED_ON_NAME_COLUMNS = {
- "_id",
- SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_ICON_1,
- SearchManager.SUGGEST_COLUMN_ICON_2,
- SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID,
- SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
- };
-
- private Cursor buildCursorForSearchSuggestionsBasedOnName(String searchClause, String limit) {
- ArrayList<SearchSuggestion> suggestionList = new ArrayList<SearchSuggestion>();
- HashMap<Long, SearchSuggestion> suggestionMap = new HashMap<Long, SearchSuggestion>();
-
- StringBuilder selection = new StringBuilder();
- selection.append(getContactsRestrictionExceptions());
- selection.append(" AND " + DataColumns.CONCRETE_RAW_CONTACT_ID + " IN ");
- appendRawContactsByFilterAsNestedQuery(selection, searchClause, limit);
-
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor c = db.query(true, SearchSuggestionQuery.TABLE,
- SearchSuggestionQuery.COLUMNS, selection.toString(), null, null, null, null, null);
- try {
- while (c.moveToNext()) {
-
- long contactId = c.getLong(SearchSuggestionQuery.CONTACT_ID);
- SearchSuggestion suggestion = suggestionMap.get(contactId);
- if (suggestion == null) {
- suggestion = new SearchSuggestion(contactId);
- suggestionList.add(suggestion);
- suggestionMap.put(contactId, suggestion);
- }
-
- boolean isSuperPrimary = c.getInt(SearchSuggestionQuery.IS_SUPER_PRIMARY) != 0;
- suggestion.text1 = c.getString(SearchSuggestionQuery.DISPLAY_NAME);
-
- if (!c.isNull(SearchSuggestionQuery.PRESENCE_STATUS)) {
- suggestion.presence = c.getInt(SearchSuggestionQuery.PRESENCE_STATUS);
- }
-
- String mimetype = c.getString(SearchSuggestionQuery.MIMETYPE);
- if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) {
- suggestion.titleIsName = true;
- } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) {
- if (isSuperPrimary || suggestion.photoUri == null) {
-
- // TODO introduce a dedicate URI for contact photo: /contact/#/photo
- long dataId = c.getLong(SearchSuggestionQuery.DATA_ID);
- suggestion.photoUri =
- ContentUris.withAppendedId(Data.CONTENT_URI, dataId).toString();
- }
- } else if (Organization.CONTENT_ITEM_TYPE.equals(mimetype)) {
- if (isSuperPrimary || suggestion.organization == null) {
- suggestion.organization = c.getString(SearchSuggestionQuery.DATA2);
- }
- } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
- if (isSuperPrimary || suggestion.email == null) {
- suggestion.email = c.getString(SearchSuggestionQuery.DATA2);
- }
- } else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
- if (isSuperPrimary || suggestion.phoneNumber == null) {
- suggestion.phoneNumber = c.getString(SearchSuggestionQuery.DATA2);
- }
- }
- }
- } finally {
- c.close();
- }
-
- Collections.sort(suggestionList, new Comparator<SearchSuggestion>() {
- public int compare(SearchSuggestion row1, SearchSuggestion row2) {
- return row1.getSortKey().compareTo(row2.getSortKey());
- }
- });
-
- @SuppressWarnings({"unchecked"}) ArrayList<ArrayList> rows = new ArrayList<ArrayList>();
- for (int i = 0; i < suggestionList.size(); i++) {
- rows.add(suggestionList.get(i).asList());
- }
-
- return new ArrayListCursor(SEARCH_SUGGESTIONS_BASED_ON_NAME_COLUMNS, rows);
- }
-
/**
* List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
*/
@@ -2674,7 +2397,7 @@
qb.appendWhere(getContactsRestrictionExceptions());
}
- private String getContactsRestrictionExceptions() {
+ String getContactsRestrictionExceptions() {
if (hasRestrictedAccess()) {
return "1";
} else {
@@ -3157,7 +2880,7 @@
return sb.toString();
}
- private void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam,
+ public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam,
String limit) {
sb.append("(SELECT DISTINCT raw_contact_id FROM name_lookup WHERE normalized_name GLOB '");
sb.append(NameNormalizer.normalize(filterParam));
diff --git a/src/com/android/providers/contacts/GlobalSearchSupport.java b/src/com/android/providers/contacts/GlobalSearchSupport.java
new file mode 100644
index 0000000..40e1089
--- /dev/null
+++ b/src/com/android/providers/contacts/GlobalSearchSupport.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2009 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.providers.contacts;
+
+import com.android.internal.database.ArrayListCursor;
+import com.android.providers.contacts.OpenHelper.ContactsColumns;
+import com.android.providers.contacts.OpenHelper.DataColumns;
+import com.android.providers.contacts.OpenHelper.MimetypesColumns;
+import com.android.providers.contacts.OpenHelper.RawContactsColumns;
+import com.android.providers.contacts.OpenHelper.Tables;
+
+import android.app.SearchManager;
+import android.content.ContentUris;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.Contacts.Intents;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Presence;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+
+/**
+ * Support for global search integration for Contacts.
+ */
+public class GlobalSearchSupport {
+
+ private static final String[] SEARCH_SUGGESTIONS_BASED_ON_PHONE_NUMBER_COLUMNS = {
+ "_id",
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_ICON_1,
+ SearchManager.SUGGEST_COLUMN_INTENT_DATA,
+ SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
+ };
+
+ private static final String[] SEARCH_SUGGESTIONS_BASED_ON_NAME_COLUMNS = {
+ "_id",
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_ICON_1,
+ SearchManager.SUGGEST_COLUMN_ICON_2,
+ SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID,
+ SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
+ };
+
+ private interface SearchSuggestionQuery {
+ public static final String JOIN_RAW_CONTACTS =
+ " JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) ";
+
+ public static final String JOIN_CONTACTS =
+ " JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
+
+ public static final String JOIN_MIMETYPES =
+ " JOIN mimetypes ON (data.mimetype_id = mimetypes._id AND mimetypes.mimetype IN ('"
+ + StructuredName.CONTENT_ITEM_TYPE + "','" + Email.CONTENT_ITEM_TYPE + "','"
+ + Phone.CONTENT_ITEM_TYPE + "','" + Organization.CONTENT_ITEM_TYPE + "','"
+ + Photo.CONTENT_ITEM_TYPE + "','" + GroupMembership.CONTENT_ITEM_TYPE + "')) ";
+
+ public static final String TABLE = "data " + JOIN_RAW_CONTACTS + JOIN_MIMETYPES
+ + JOIN_CONTACTS;
+
+ public static final String PRESENCE_SQL = "(SELECT MAX(" + Presence.PRESENCE_STATUS
+ + ") FROM " + Tables.PRESENCE + " WHERE " + Tables.PRESENCE + "."
+ + Presence.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")";
+
+ public static final String[] COLUMNS = {
+ ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID,
+ ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + Contacts.DISPLAY_NAME,
+ PRESENCE_SQL + " AS " + Contacts.PRESENCE_STATUS,
+ DataColumns.CONCRETE_ID + " AS data_id",
+ MimetypesColumns.MIMETYPE,
+ Data.IS_SUPER_PRIMARY,
+ Data.DATA2,
+ };
+
+ public static final int CONTACT_ID = 0;
+ public static final int DISPLAY_NAME = 1;
+ public static final int PRESENCE_STATUS = 2;
+ public static final int DATA_ID = 3;
+ public static final int MIMETYPE = 4;
+ public static final int IS_SUPER_PRIMARY = 5;
+ public static final int DATA2 = 6;
+ }
+
+ private static class SearchSuggestion {
+ String contactId;
+ boolean titleIsName;
+ String organization;
+ String email;
+ String phoneNumber;
+ String photoUri;
+ String normalizedName;
+ int presence = -1;
+ boolean processed;
+ String text1;
+ String text2;
+ String icon1;
+ String icon2;
+
+ public SearchSuggestion(long contactId) {
+ this.contactId = String.valueOf(contactId);
+ }
+
+ private void process() {
+ if (processed) {
+ return;
+ }
+
+ boolean hasOrganization = !TextUtils.isEmpty(organization);
+ boolean hasEmail = !TextUtils.isEmpty(email);
+ boolean hasPhone = !TextUtils.isEmpty(phoneNumber);
+
+ boolean titleIsOrganization = !titleIsName && hasOrganization;
+ boolean titleIsEmail = !titleIsName && !titleIsOrganization && hasEmail;
+ boolean titleIsPhone = !titleIsName && !titleIsOrganization && !titleIsEmail
+ && hasPhone;
+
+ if (!titleIsOrganization && hasOrganization) {
+ text2 = organization;
+ } else if (!titleIsEmail && hasEmail) {
+ text2 = email;
+ } else if (!titleIsPhone && hasPhone) {
+ text2 = phoneNumber;
+ }
+
+ if (photoUri != null) {
+ icon1 = photoUri;
+ } else {
+ icon1 = String.valueOf(com.android.internal.R.drawable.ic_contact_picture);
+ }
+
+ if (presence != -1) {
+ icon2 = String.valueOf(Presence.getPresenceIconResourceId(presence));
+ }
+
+ processed = true;
+ }
+
+ public String getSortKey() {
+ if (normalizedName == null) {
+ process();
+ normalizedName = text1 == null ? "" : NameNormalizer.normalize(text1);
+ }
+ return normalizedName;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public ArrayList asList() {
+ process();
+
+ ArrayList<Object> list = new ArrayList<Object>();
+ list.add(contactId);
+ list.add(text1);
+ list.add(text2);
+ list.add(icon1);
+ list.add(icon2);
+ list.add(contactId);
+ list.add(contactId);
+ return list;
+ }
+ }
+
+ private final ContactsProvider2 mContactsProvider;
+
+ public GlobalSearchSupport(ContactsProvider2 contactsProvider) {
+ mContactsProvider = contactsProvider;
+ }
+
+ public Cursor handleSearchSuggestionsQuery(SQLiteDatabase db, Uri url, String limit) {
+ if (url.getPathSegments().size() <= 1) {
+ return null;
+ }
+
+ final String searchClause = url.getLastPathSegment();
+ if (TextUtils.isDigitsOnly(searchClause)) {
+ return buildCursorForSearchSuggestionsBasedOnPhoneNumber(searchClause);
+ } else {
+ return buildCursorForSearchSuggestionsBasedOnName(db, searchClause, limit);
+ }
+ }
+
+ private Cursor buildCursorForSearchSuggestionsBasedOnPhoneNumber(String searchClause) {
+ Resources r = mContactsProvider.getContext().getResources();
+ String s;
+ int i;
+
+ ArrayList<Object> dialNumber = new ArrayList<Object>();
+ dialNumber.add(0); // _id
+ s = r.getString(com.android.internal.R.string.dial_number_using, searchClause);
+ i = s.indexOf('\n');
+ if (i < 0) {
+ dialNumber.add(s);
+ dialNumber.add("");
+ } else {
+ dialNumber.add(s.substring(0, i));
+ dialNumber.add(s.substring(i + 1));
+ }
+ dialNumber.add(String.valueOf(com.android.internal.R.drawable.call_contact));
+ dialNumber.add("tel:" + searchClause);
+ dialNumber.add(Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED);
+ dialNumber.add(null);
+
+ ArrayList<Object> createContact = new ArrayList<Object>();
+ createContact.add(1); // _id
+ s = r.getString(com.android.internal.R.string.create_contact_using, searchClause);
+ i = s.indexOf('\n');
+ if (i < 0) {
+ createContact.add(s);
+ createContact.add("");
+ } else {
+ createContact.add(s.substring(0, i));
+ createContact.add(s.substring(i + 1));
+ }
+ createContact.add(String.valueOf(com.android.internal.R.drawable.create_contact));
+ createContact.add("tel:" + searchClause);
+ createContact.add(Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED);
+ createContact.add(SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
+
+ @SuppressWarnings({"unchecked"}) ArrayList<ArrayList> rows = new ArrayList<ArrayList>();
+ rows.add(dialNumber);
+ rows.add(createContact);
+
+ return new ArrayListCursor(SEARCH_SUGGESTIONS_BASED_ON_PHONE_NUMBER_COLUMNS, rows);
+ }
+
+ private Cursor buildCursorForSearchSuggestionsBasedOnName(SQLiteDatabase db,
+ String searchClause, String limit) {
+ ArrayList<SearchSuggestion> suggestionList = new ArrayList<SearchSuggestion>();
+ HashMap<Long, SearchSuggestion> suggestionMap = new HashMap<Long, SearchSuggestion>();
+
+ StringBuilder selection = new StringBuilder();
+ selection.append(mContactsProvider.getContactsRestrictionExceptions());
+ selection.append(" AND " + DataColumns.CONCRETE_RAW_CONTACT_ID + " IN ");
+ mContactsProvider.appendRawContactsByFilterAsNestedQuery(selection, searchClause, limit);
+ selection.append(" AND " + Contacts.IN_VISIBLE_GROUP + "=1");
+
+ Cursor c = db.query(true, SearchSuggestionQuery.TABLE,
+ SearchSuggestionQuery.COLUMNS, selection.toString(), null, null, null, null, null);
+ try {
+ while (c.moveToNext()) {
+
+ long contactId = c.getLong(SearchSuggestionQuery.CONTACT_ID);
+ SearchSuggestion suggestion = suggestionMap.get(contactId);
+ if (suggestion == null) {
+ suggestion = new SearchSuggestion(contactId);
+ suggestionList.add(suggestion);
+ suggestionMap.put(contactId, suggestion);
+ }
+
+ boolean isSuperPrimary = c.getInt(SearchSuggestionQuery.IS_SUPER_PRIMARY) != 0;
+ suggestion.text1 = c.getString(SearchSuggestionQuery.DISPLAY_NAME);
+
+ if (!c.isNull(SearchSuggestionQuery.PRESENCE_STATUS)) {
+ suggestion.presence = c.getInt(SearchSuggestionQuery.PRESENCE_STATUS);
+ }
+
+ String mimetype = c.getString(SearchSuggestionQuery.MIMETYPE);
+ if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) {
+ suggestion.titleIsName = true;
+ } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) {
+ if (isSuperPrimary || suggestion.photoUri == null) {
+
+ // TODO introduce a dedicated URI for contact photo: /contact/#/photo
+ long dataId = c.getLong(SearchSuggestionQuery.DATA_ID);
+ suggestion.photoUri =
+ ContentUris.withAppendedId(Data.CONTENT_URI, dataId).toString();
+ }
+ } else if (Organization.CONTENT_ITEM_TYPE.equals(mimetype)) {
+ if (isSuperPrimary || suggestion.organization == null) {
+ suggestion.organization = c.getString(SearchSuggestionQuery.DATA2);
+ }
+ } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
+ if (isSuperPrimary || suggestion.email == null) {
+ suggestion.email = c.getString(SearchSuggestionQuery.DATA2);
+ }
+ } else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
+ if (isSuperPrimary || suggestion.phoneNumber == null) {
+ suggestion.phoneNumber = c.getString(SearchSuggestionQuery.DATA2);
+ }
+ }
+ }
+ } finally {
+ c.close();
+ }
+
+ Collections.sort(suggestionList, new Comparator<SearchSuggestion>() {
+ public int compare(SearchSuggestion row1, SearchSuggestion row2) {
+ return row1.getSortKey().compareTo(row2.getSortKey());
+ }
+ });
+
+ @SuppressWarnings({"unchecked"}) ArrayList<ArrayList> rows = new ArrayList<ArrayList>();
+ for (int i = 0; i < suggestionList.size(); i++) {
+ rows.add(suggestionList.get(i).asList());
+ }
+
+ return new ArrayListCursor(SEARCH_SUGGESTIONS_BASED_ON_NAME_COLUMNS, rows);
+ }
+}
diff --git a/src/com/android/providers/contacts/LegacyApiSupport.java b/src/com/android/providers/contacts/LegacyApiSupport.java
index d04bf63..af4a74e 100644
--- a/src/com/android/providers/contacts/LegacyApiSupport.java
+++ b/src/com/android/providers/contacts/LegacyApiSupport.java
@@ -422,17 +422,20 @@
private final OpenHelper mOpenHelper;
private final ContactsProvider2 mContactsProvider;
private final NameSplitter mPhoneticNameSplitter;
+ private final GlobalSearchSupport mGlobalSearchSupport;
/** Precompiled sql statement for incrementing times contacted for a contact */
private final SQLiteStatement mLastTimeContactedUpdate;
private final ContentValues mValues = new ContentValues();
+
public LegacyApiSupport(Context context, OpenHelper openHelper,
- ContactsProvider2 contactsProvider) {
+ ContactsProvider2 contactsProvider, GlobalSearchSupport globalSearchSupport) {
mContext = context;
mContactsProvider = contactsProvider;
mOpenHelper = openHelper;
+ mGlobalSearchSupport = globalSearchSupport;
mOpenHelper.setDelegate(this);
mPhoneticNameSplitter = new NameSplitter("", "", "",
@@ -1302,7 +1305,7 @@
case SEARCH_SUGGESTIONS:
// No legacy compatibility for search suggestions
- return mContactsProvider.handleSearchSuggestionsQuery(uri, limit);
+ return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit);
case DELETED_PEOPLE:
case DELETED_GROUPS:
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index e4186d7..cc27428 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -23,6 +23,7 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
+import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
@@ -43,6 +44,9 @@
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.LargeTest;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -133,6 +137,7 @@
ContentValues values = new ContentValues();
values.put(Groups.SOURCE_ID, sourceId);
values.put(Groups.TITLE, title);
+ values.put(Groups.GROUP_VISIBLE, 1);
final Uri uri = maybeAddAccountQueryParameters(Groups.CONTENT_URI, account);
return ContentUris.parseId(mResolver.insert(uri, values));
}
@@ -579,4 +584,17 @@
c.close();
}
}
+
+ protected byte[] loadTestPhoto() throws IOException {
+ final Resources resources = getContext().getResources();
+ InputStream is =
+ resources.openRawResource(com.android.internal.R.drawable.ic_contact_picture);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1000];
+ int count;
+ while((count = is.read(buffer)) != -1) {
+ os.write(buffer, 0, count);
+ }
+ return os.toByteArray();
+ }
}
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index de9dd14..f6d5bd7 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -17,18 +17,14 @@
import com.android.internal.util.ArrayUtils;
-import android.app.SearchManager;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Entity;
import android.content.EntityIterator;
-import android.content.res.Resources;
import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
-import android.provider.Contacts.Intents;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
@@ -37,16 +33,10 @@
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.test.suitebuilder.annotation.LargeTest;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
/**
* Unit tests for {@link ContactsProvider2}.
*
@@ -477,212 +467,5 @@
version++;
assertEquals(version, getVersion(uri));
}
-
- // TODO fix and enable test
- public void __testSearchSuggestionsNotInMyContacts() throws Exception {
-
- long rawContactId = createRawContact();
- insertStructuredName(rawContactId, "Deer", "Dough");
-
- Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
- .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("D").build();
-
- // If the contact is not in the "my contacts" group, nothing should be found
- Cursor c = mResolver.query(searchUri, null, null, null, null);
- assertEquals(0, c.getCount());
- c.close();
- }
-
- public void testSearchSuggestionsByName() throws Exception {
- assertSearchSuggestion(
- true, // name
- true, // photo
- false, // organization
- false, // phone
- false, // email
- "D", // query
- true, // expect icon URI
- null, "Deer Dough", null);
-
- assertSearchSuggestion(
- true, // name
- true, // photo
- true, // organization
- false, // phone
- false, // email
- "D", // query
- true, // expect icon URI
- null, "Deer Dough", "Google");
-
- assertSearchSuggestion(
- true, // name
- true, // photo
- false, // organization
- true, // phone
- false, // email
- "D", // query
- true, // expect icon URI
- null, "Deer Dough", "1-800-4664-411");
-
- assertSearchSuggestion(
- true, // name
- true, // photo
- false, // organization
- false, // phone
- true, // email
- "D", // query
- true, // expect icon URI
- String.valueOf(Presence.getPresenceIconResourceId(Presence.OFFLINE)),
- "Deer Dough", "foo@acme.com");
-
- assertSearchSuggestion(
- true, // name
- false, // photo
- true, // organization
- false, // phone
- false, // email
- "D", // query
- false, // expect icon URI
- null, "Deer Dough", "Google");
- }
-
- private void assertSearchSuggestion(boolean name, boolean photo, boolean organization,
- boolean phone, boolean email, String query, boolean expectIcon1Uri, String expectedIcon2,
- String expectedText1, String expectedText2) throws IOException {
- ContentValues values = new ContentValues();
-
- long rawContactId = createRawContact();
-
- if (name) {
- insertStructuredName(rawContactId, "Deer", "Dough");
- }
-
-
- final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
- if (photo) {
- values.clear();
- byte[] photoData = loadTestPhoto();
- values.put(Data.RAW_CONTACT_ID, rawContactId);
- values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
- values.put(Photo.PHOTO, photoData);
- mResolver.insert(Data.CONTENT_URI, values);
- }
-
- if (organization) {
- values.clear();
- values.put(Data.RAW_CONTACT_ID, rawContactId);
- values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
- values.put(Organization.TYPE, Organization.TYPE_WORK);
- values.put(Organization.COMPANY, "Google");
- mResolver.insert(Data.CONTENT_URI, values);
- }
-
- if (email) {
- values.clear();
- values.put(Data.RAW_CONTACT_ID, rawContactId);
- values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
- values.put(Email.TYPE, Email.TYPE_WORK);
- values.put(Email.DATA, "foo@acme.com");
- mResolver.insert(Data.CONTENT_URI, values);
-
- values.clear();
- values.put(Presence.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
- values.put(Presence.IM_HANDLE, "foo@acme.com");
- values.put(Presence.IM_ACCOUNT, "foo");
- values.put(Presence.PRESENCE_STATUS, Presence.OFFLINE);
- values.put(Presence.PRESENCE_CUSTOM_STATUS, "Coding for Android");
- mResolver.insert(Presence.CONTENT_URI, values);
- }
-
- if (phone) {
- values.clear();
- values.put(Data.RAW_CONTACT_ID, rawContactId);
- values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
- values.put(Data.IS_PRIMARY, 1);
- values.put(Phone.TYPE, Phone.TYPE_HOME);
- values.put(Phone.NUMBER, "1-800-4664-411");
- mResolver.insert(Data.CONTENT_URI, values);
- }
-
- long contactId = queryContactId(rawContactId);
- Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
- .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath(query).build();
-
- Cursor c = mResolver.query(searchUri, null, null, null, null);
- DatabaseUtils.dumpCursor(c);
- assertEquals(1, c.getCount());
- c.moveToFirst();
- values.clear();
-
- // SearchManager does not declare a constant for _id
- values.put("_id", contactId);
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, expectedText1);
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, expectedText2);
-
- String icon1 = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1));
- if (expectIcon1Uri) {
- assertTrue(icon1.startsWith("content:"));
- } else {
- assertEquals(String.valueOf(com.android.internal.R.drawable.ic_contact_picture), icon1);
- }
-
- values.put(SearchManager.SUGGEST_COLUMN_ICON_2, expectedIcon2);
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, contactId);
- values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, contactId);
- assertCursorValues(c, values);
- c.close();
-
- // Cleanup
- mResolver.delete(rawContactUri, null, null);
- }
-
- public void testSearchSuggestionsByPhoneNumber() throws Exception {
- ContentValues values = new ContentValues();
-
- Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
- .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("12345").build();
-
- Cursor c = mResolver.query(searchUri, null, null, null, null);
- DatabaseUtils.dumpCursor(c);
- assertEquals(2, c.getCount());
- c.moveToFirst();
-
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Dial number");
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using 12345");
- values.put(SearchManager.SUGGEST_COLUMN_ICON_1,
- String.valueOf(com.android.internal.R.drawable.call_contact));
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
- Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED);
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345");
- values.putNull(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
- assertCursorValues(c, values);
-
- c.moveToNext();
- values.clear();
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Create contact");
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using 12345");
- values.put(SearchManager.SUGGEST_COLUMN_ICON_1,
- String.valueOf(com.android.internal.R.drawable.create_contact));
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
- Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED);
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345");
- values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
- SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
- assertCursorValues(c, values);
- c.close();
- }
-
- private byte[] loadTestPhoto() throws IOException {
- final Resources resources = getContext().getResources();
- InputStream is =
- resources.openRawResource(com.android.internal.R.drawable.ic_contact_picture);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- byte[] buffer = new byte[1000];
- int count;
- while((count = is.read(buffer)) != -1) {
- os.write(buffer, 0, count);
- }
- return os.toByteArray();
- }
}
diff --git a/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java b/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java
new file mode 100644
index 0000000..8921d41
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2009 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.providers.contacts;
+
+import android.app.SearchManager;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.Contacts.Intents;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Presence;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.io.IOException;
+
+/**
+ * Unit tests for {@link GlobalSearchSupport}.
+ *
+ * Run the test like this:
+ * <code>
+ * adb shell am instrument -w \
+ * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
+ * </code>
+ */
+@LargeTest
+public class GlobalSearchSupportTest extends BaseContactsProvider2Test {
+ public void testSearchSuggestionsNotInVisibleGroup() throws Exception {
+ long rawContactId = createRawContact();
+ insertStructuredName(rawContactId, "Deer", "Dough");
+
+ Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
+ .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("D").build();
+
+ // If the contact is not in the "my contacts" group, nothing should be found
+ Cursor c = mResolver.query(searchUri, null, null, null, null);
+ assertEquals(0, c.getCount());
+ c.close();
+ }
+
+ public void testSearchSuggestionsByName() throws Exception {
+ long groupId = createGroup(mAccount, "gsid1", "title1");
+
+ assertSearchSuggestion(groupId,
+ true, // name
+ true, // photo
+ false, // organization
+ false, // phone
+ false, // email
+ "D", // query
+ true, // expect icon URI
+ null, "Deer Dough", null);
+
+ assertSearchSuggestion(groupId,
+ true, // name
+ true, // photo
+ true, // organization
+ false, // phone
+ false, // email
+ "D", // query
+ true, // expect icon URI
+ null, "Deer Dough", "Google");
+
+ assertSearchSuggestion(groupId,
+ true, // name
+ true, // photo
+ false, // organization
+ true, // phone
+ false, // email
+ "D", // query
+ true, // expect icon URI
+ null, "Deer Dough", "1-800-4664-411");
+
+ assertSearchSuggestion(groupId,
+ true, // name
+ true, // photo
+ false, // organization
+ false, // phone
+ true, // email
+ "D", // query
+ true, // expect icon URI
+ String.valueOf(Presence.getPresenceIconResourceId(Presence.OFFLINE)),
+ "Deer Dough", "foo@acme.com");
+
+ assertSearchSuggestion(groupId,
+ true, // name
+ false, // photo
+ true, // organization
+ false, // phone
+ false, // email
+ "D", // query
+ false, // expect icon URI
+ null, "Deer Dough", "Google");
+ }
+
+ private void assertSearchSuggestion(long groupId, boolean name, boolean photo,
+ boolean organization, boolean phone, boolean email, String query,
+ boolean expectIcon1Uri, String expectedIcon2, String expectedText1, String expectedText2)
+ throws IOException {
+ ContentValues values = new ContentValues();
+
+ long rawContactId = createRawContact();
+ insertGroupMembership(rawContactId, groupId);
+
+ if (name) {
+ insertStructuredName(rawContactId, "Deer", "Dough");
+ }
+
+ final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
+ if (photo) {
+ values.clear();
+ byte[] photoData = loadTestPhoto();
+ values.put(Data.RAW_CONTACT_ID, rawContactId);
+ values.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
+ values.put(Photo.PHOTO, photoData);
+ mResolver.insert(Data.CONTENT_URI, values);
+ }
+
+ if (organization) {
+ values.clear();
+ values.put(Data.RAW_CONTACT_ID, rawContactId);
+ values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
+ values.put(Organization.TYPE, Organization.TYPE_WORK);
+ values.put(Organization.COMPANY, "Google");
+ mResolver.insert(Data.CONTENT_URI, values);
+ }
+
+ if (email) {
+ values.clear();
+ values.put(Data.RAW_CONTACT_ID, rawContactId);
+ values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ values.put(Email.TYPE, Email.TYPE_WORK);
+ values.put(Email.DATA, "foo@acme.com");
+ mResolver.insert(Data.CONTENT_URI, values);
+
+ int protocol = Im.PROTOCOL_GOOGLE_TALK;
+
+ values.clear();
+ values.put(Presence.IM_PROTOCOL, protocol);
+ values.put(Presence.IM_HANDLE, "foo@acme.com");
+ values.put(Presence.IM_ACCOUNT, "foo");
+ values.put(Presence.PRESENCE_STATUS, Presence.OFFLINE);
+ values.put(Presence.PRESENCE_CUSTOM_STATUS, "Coding for Android");
+ mResolver.insert(Presence.CONTENT_URI, values);
+ }
+
+ if (phone) {
+ values.clear();
+ values.put(Data.RAW_CONTACT_ID, rawContactId);
+ values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ values.put(Data.IS_PRIMARY, 1);
+ values.put(Phone.TYPE, Phone.TYPE_HOME);
+ values.put(Phone.NUMBER, "1-800-4664-411");
+ mResolver.insert(Data.CONTENT_URI, values);
+ }
+
+ long contactId = queryContactId(rawContactId);
+ Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
+ .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath(query).build();
+
+ Cursor c = mResolver.query(searchUri, null, null, null, null);
+ assertEquals(1, c.getCount());
+ c.moveToFirst();
+ values.clear();
+
+ // SearchManager does not declare a constant for _id
+ values.put("_id", contactId);
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, expectedText1);
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, expectedText2);
+
+ String icon1 = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1));
+ if (expectIcon1Uri) {
+ assertTrue(icon1.startsWith("content:"));
+ } else {
+ assertEquals(String.valueOf(com.android.internal.R.drawable.ic_contact_picture), icon1);
+ }
+
+ values.put(SearchManager.SUGGEST_COLUMN_ICON_2, expectedIcon2);
+ values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, contactId);
+ values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, contactId);
+ assertCursorValues(c, values);
+ c.close();
+
+ // Cleanup
+ mResolver.delete(rawContactUri, null, null);
+ }
+
+ public void testSearchSuggestionsByPhoneNumber() throws Exception {
+ ContentValues values = new ContentValues();
+
+ Uri searchUri = new Uri.Builder().scheme("content").authority(ContactsContract.AUTHORITY)
+ .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath("12345").build();
+
+ Cursor c = mResolver.query(searchUri, null, null, null, null);
+ DatabaseUtils.dumpCursor(c);
+ assertEquals(2, c.getCount());
+ c.moveToFirst();
+
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Dial number");
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using 12345");
+ values.put(SearchManager.SUGGEST_COLUMN_ICON_1,
+ String.valueOf(com.android.internal.R.drawable.call_contact));
+ values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED);
+ values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345");
+ values.putNull(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
+ assertCursorValues(c, values);
+
+ c.moveToNext();
+ values.clear();
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Create contact");
+ values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using 12345");
+ values.put(SearchManager.SUGGEST_COLUMN_ICON_1,
+ String.valueOf(com.android.internal.R.drawable.create_contact));
+ values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED);
+ values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:12345");
+ values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
+ SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
+ assertCursorValues(c, values);
+ c.close();
+ }
+}
+
diff --git a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
index 502010d..870c7d2 100644
--- a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
+++ b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
@@ -777,19 +777,6 @@
values.put(People.STARRED, 1);
}
- private byte[] loadTestPhoto() throws IOException {
- final Resources resources = getContext().getResources();
- InputStream is =
- resources.openRawResource(com.android.internal.R.drawable.ic_contact_picture);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- byte[] buffer = new byte[1000];
- int count;
- while((count = is.read(buffer)) != -1) {
- os.write(buffer, 0, count);
- }
- return os.toByteArray();
- }
-
private void assertFilteredContacts(String filter, String... expectedNames) {
Uri filterUri = Uri.withAppendedPath(People.CONTENT_FILTER_URI, filter);
Cursor c = mResolver.query(filterUri, null, null, null, null);