1f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov/* 2f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 3f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * 4f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * you may not use this file except in compliance with the License. 6f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * You may obtain a copy of the License at 7f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * 8f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * 10f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * See the License for the specific language governing permissions and 14f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * limitations under the License 15f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 16f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 19f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.content.ContentResolver; 20f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.content.Context; 21d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikovimport android.database.ContentObserver; 22f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.database.Cursor; 23f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.net.Uri; 24f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.os.Handler; 25f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.os.HandlerThread; 26f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.os.Message; 27f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.os.Process; 28f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 29f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 30f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 31f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 32f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 33f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 34f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 35f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions.Builder; 36f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Data; 37c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 38f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.text.TextUtils; 39f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 40738ff8623dc77dd91a1b9023861e924ba5e4c27eChiao Chengimport com.android.contacts.common.model.ValuesDelta; 41e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 42e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 43f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.ArrayList; 44f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.Arrays; 45f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 46f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 47f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov/** 48f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Runs asynchronous queries to obtain aggregation suggestions in the as-you-type mode. 49f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 50f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovpublic class AggregationSuggestionEngine extends HandlerThread { 51f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final String TAG = "AggregationSuggestionEngine"; 52f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 53f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public interface Listener { 54f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov void onAggregationSuggestionChange(); 55f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 56f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 57c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public static final class RawContact { 58c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public long rawContactId; 59c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public String accountType; 60c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public String accountName; 612b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public String dataSet; 62c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov 63c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov @Override 64c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public String toString() { 652b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return "ID: " + rawContactId + " account: " + accountType + "/" + accountName 662b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro + " dataSet: " + dataSet; 67c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 68c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 69c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov 70f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final class Suggestion { 71c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov 72f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public long contactId; 73f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String lookupKey; 74f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String name; 75f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String phoneNumber; 76f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String emailAddress; 77f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String nickname; 78f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public byte[] photo; 79c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public List<RawContact> rawContacts; 80f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 81f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 82f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public String toString() { 83c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov return "ID: " + contactId + " rawContacts: " + rawContacts + " name: " + name 84d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov + " phone: " + phoneNumber + " email: " + emailAddress + " nickname: " 85d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov + nickname + (photo != null ? " [has photo]" : ""); 86d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 87d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 88d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 89d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private final class SuggestionContentObserver extends ContentObserver { 90d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private SuggestionContentObserver(Handler handler) { 91d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov super(handler); 92d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 93d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 94d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov @Override 95d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov public void onChange(boolean selfChange) { 96d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov scheduleSuggestionLookup(); 97f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 98f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 99f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 100d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private static final int MESSAGE_RESET = 0; 101d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private static final int MESSAGE_NAME_CHANGE = 1; 102d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private static final int MESSAGE_DATA_CURSOR = 2; 103d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 104d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private static final long SUGGESTION_LOOKUP_DELAY_MILLIS = 300; 105d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 106d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private static final int MAX_SUGGESTION_COUNT = 3; 107d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 108d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private final Context mContext; 109d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 110d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private long[] mSuggestedContactIds = new long[0]; 111d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 112d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private Handler mMainHandler; 113d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private Handler mHandler; 114d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private long mContactId; 115d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private Listener mListener; 116d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private Cursor mDataCursor; 117d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private ContentObserver mContentObserver; 118d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov private Uri mSuggestionsUri; 119d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 120f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public AggregationSuggestionEngine(Context context) { 121f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super("AggregationSuggestions", Process.THREAD_PRIORITY_BACKGROUND); 1222828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki mContext = context.getApplicationContext(); 123f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mMainHandler = new Handler() { 124f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 125f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void handleMessage(Message msg) { 126f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov AggregationSuggestionEngine.this.deliverNotification((Cursor) msg.obj); 127f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 128f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov }; 129f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 130f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 131f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected Handler getHandler() { 132f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mHandler == null) { 133f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mHandler = new Handler(getLooper()) { 134f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 135f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void handleMessage(Message msg) { 136f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov AggregationSuggestionEngine.this.handleMessage(msg); 137f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 138f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov }; 139f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 140f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return mHandler; 141f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 142f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 143f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void setContactId(long contactId) { 144916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov if (contactId != mContactId) { 145916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mContactId = contactId; 146916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov reset(); 147916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov } 148f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 149f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 150f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void setListener(Listener listener) { 151f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mListener = listener; 152f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 153f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 154f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 155f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public boolean quit() { 156f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mDataCursor != null) { 157f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mDataCursor.close(); 158f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 159f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mDataCursor = null; 160d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov if (mContentObserver != null) { 161d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContext.getContentResolver().unregisterContentObserver(mContentObserver); 162d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContentObserver = null; 163d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 164f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return super.quit(); 165f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 166f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1679302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov public void reset() { 1689302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Handler handler = getHandler(); 1699302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov handler.removeMessages(MESSAGE_NAME_CHANGE); 1709302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov handler.sendEmptyMessage(MESSAGE_RESET); 1719302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1729302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 173f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onNameChange(ValuesDelta values) { 174d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mSuggestionsUri = buildAggregationSuggestionUri(values); 175d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov if (mSuggestionsUri != null) { 176d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov if (mContentObserver == null) { 177d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContentObserver = new SuggestionContentObserver(getHandler()); 178d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContext.getContentResolver().registerContentObserver( 179d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov Contacts.CONTENT_URI, true, mContentObserver); 180d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 181d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } else if (mContentObserver != null) { 182d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContext.getContentResolver().unregisterContentObserver(mContentObserver); 183d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov mContentObserver = null; 184d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 185d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov scheduleSuggestionLookup(); 186d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov } 187d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov 188d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov protected void scheduleSuggestionLookup() { 189f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Handler handler = getHandler(); 190f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov handler.removeMessages(MESSAGE_NAME_CHANGE); 191f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 192d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov if (mSuggestionsUri == null) { 193f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 194f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 195f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 196d52121b61b71230d0f695f9d3891eaf0cbb7c549Dmitri Plotnikov Message msg = handler.obtainMessage(MESSAGE_NAME_CHANGE, mSuggestionsUri); 197f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov handler.sendMessageDelayed(msg, SUGGESTION_LOOKUP_DELAY_MILLIS); 198f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 199f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 200f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private Uri buildAggregationSuggestionUri(ValuesDelta values) { 201f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov StringBuilder nameSb = new StringBuilder(); 202f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(nameSb, values, StructuredName.PREFIX); 203f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(nameSb, values, StructuredName.GIVEN_NAME); 204f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(nameSb, values, StructuredName.MIDDLE_NAME); 205f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(nameSb, values, StructuredName.FAMILY_NAME); 206f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(nameSb, values, StructuredName.SUFFIX); 207f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 208c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov if (nameSb.length() == 0) { 209c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov appendValue(nameSb, values, StructuredName.DISPLAY_NAME); 210c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov } 211c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov 212f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov StringBuilder phoneticNameSb = new StringBuilder(); 213f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(phoneticNameSb, values, StructuredName.PHONETIC_FAMILY_NAME); 214f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(phoneticNameSb, values, StructuredName.PHONETIC_MIDDLE_NAME); 215f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov appendValue(phoneticNameSb, values, StructuredName.PHONETIC_GIVEN_NAME); 216f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 217f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (nameSb.length() == 0 && phoneticNameSb.length() == 0) { 218f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return null; 219f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 220f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 221532df59787a7b0b41aa3177dc1e2a073f2b8c3c3Brian Attwell Builder builder = new AggregationSuggestions.Builder() 222f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov .setLimit(MAX_SUGGESTION_COUNT) 223f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov .setContactId(mContactId); 224f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 225f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (nameSb.length() != 0) { 226bd2db2d4a756d9ca02a945f6dcf720f6bf983e0aBrian Attwell builder.addNameParameter(nameSb.toString()); 227f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 228f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 229f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (phoneticNameSb.length() != 0) { 230bd2db2d4a756d9ca02a945f6dcf720f6bf983e0aBrian Attwell builder.addNameParameter(phoneticNameSb.toString()); 231f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 232f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 233f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return builder.build(); 234f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 235f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 236f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private void appendValue(StringBuilder sb, ValuesDelta values, String column) { 237f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov String value = values.getAsString(column); 238f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (!TextUtils.isEmpty(value)) { 239f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (sb.length() > 0) { 240f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.append(' '); 241f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 242f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.append(value); 243f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 244f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 245f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 246f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected void handleMessage(Message msg) { 2479302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov switch (msg.what) { 2489302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov case MESSAGE_RESET: 2499302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mSuggestedContactIds = new long[0]; 2509302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov break; 251f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov case MESSAGE_NAME_CHANGE: 252f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov loadAggregationSuggestions((Uri) msg.obj); 253f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov break; 254f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 255f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 256f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 257f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private static final class DataQuery { 258f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 259f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final String SELECTION_PREFIX = 260f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.MIMETYPE + " IN ('" 261f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + Phone.CONTENT_ITEM_TYPE + "','" 262f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + Email.CONTENT_ITEM_TYPE + "','" 263f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + StructuredName.CONTENT_ITEM_TYPE + "','" 264f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + Nickname.CONTENT_ITEM_TYPE + "','" 265f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + Photo.CONTENT_ITEM_TYPE + "')" 266f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov + " AND " + Data.CONTACT_ID + " IN ("; 267f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 268f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final String[] COLUMNS = { 269f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data._ID, 270f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.CONTACT_ID, 271f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.LOOKUP_KEY, 272f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.PHOTO_ID, 273f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.DISPLAY_NAME, 274f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.RAW_CONTACT_ID, 275f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.MIMETYPE, 276f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.DATA1, 277f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 278f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Photo.PHOTO, 279c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 280c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2812b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro RawContacts.DATA_SET 282f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov }; 283f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 284f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int ID = 0; 285f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int CONTACT_ID = 1; 286f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int LOOKUP_KEY = 2; 287f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int PHOTO_ID = 3; 288f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int DISPLAY_NAME = 4; 289f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int RAW_CONTACT_ID = 5; 290f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int MIMETYPE = 6; 291f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int DATA1 = 7; 292f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int IS_SUPERPRIMARY = 8; 293f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public static final int PHOTO = 9; 294c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public static final int ACCOUNT_TYPE = 10; 295c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public static final int ACCOUNT_NAME = 11; 2962b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public static final int DATA_SET = 12; 297f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 298f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 299f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private void loadAggregationSuggestions(Uri uri) { 300f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov ContentResolver contentResolver = mContext.getContentResolver(); 301f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Cursor cursor = contentResolver.query(uri, new String[]{Contacts._ID}, null, null, null); 30213c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner if (cursor == null) { 30313c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner return; 30413c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner } 305f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov try { 306f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov // If a new request is pending, chuck the result of the previous request 307f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (getHandler().hasMessages(MESSAGE_NAME_CHANGE)) { 308f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 309f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 310f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 311f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov boolean changed = updateSuggestedContactIds(cursor); 312f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (!changed) { 313f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 314f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 315f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 316f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov StringBuilder sb = new StringBuilder(DataQuery.SELECTION_PREFIX); 317f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov int count = mSuggestedContactIds.length; 318f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov for (int i = 0; i < count; i++) { 319f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (i > 0) { 320f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.append(','); 321f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 322f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.append(mSuggestedContactIds[i]); 323f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 324f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.append(')'); 325f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov sb.toString(); 326f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 327f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Cursor dataCursor = contentResolver.query(Data.CONTENT_URI, 328f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov DataQuery.COLUMNS, sb.toString(), null, Data.CONTACT_ID); 32913c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner if (dataCursor != null) { 33013c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner mMainHandler.sendMessage(mMainHandler.obtainMessage(MESSAGE_DATA_CURSOR, dataCursor)); 33113c42f4ebb1c7f31750262946ce3b390c93d5320Jay Shrauner } 332f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } finally { 333f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov cursor.close(); 334f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 335f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 336f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 3375a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner private boolean updateSuggestedContactIds(final Cursor cursor) { 3385a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner final int count = cursor.getCount(); 339f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov boolean changed = count != mSuggestedContactIds.length; 3405a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner final ArrayList<Long> newIds = new ArrayList<Long>(count); 3415a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner while (cursor.moveToNext()) { 3425a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner final long contactId = cursor.getLong(0); 3435a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner if (!changed && 3445a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner Arrays.binarySearch(mSuggestedContactIds, contactId) < 0) { 3455a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner changed = true; 346f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 3475a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner newIds.add(contactId); 348f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 349f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 350f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (changed) { 3515a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner mSuggestedContactIds = new long[newIds.size()]; 3525a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner int i = 0; 3535a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner for (final Long newId : newIds) { 3545a57e57c122edefbeea40a35102d53598aebfc1cJay Shrauner mSuggestedContactIds[i++] = newId; 355f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 356f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Arrays.sort(mSuggestedContactIds); 357f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 358f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 359f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return changed; 360f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 361f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 362f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected void deliverNotification(Cursor dataCursor) { 363f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mDataCursor != null) { 364f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mDataCursor.close(); 365f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 366f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mDataCursor = dataCursor; 367f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mListener != null) { 368f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mListener.onAggregationSuggestionChange(); 369f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 370f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 371f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 372f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public int getSuggestedContactCount() { 3739302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return mDataCursor != null ? mDataCursor.getCount() : 0; 374f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 375f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 376f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public List<Suggestion> getSuggestions() { 377f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov ArrayList<Suggestion> list = Lists.newArrayList(); 378f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mDataCursor != null) { 379f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Suggestion suggestion = null; 380f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov long currentContactId = -1; 381f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mDataCursor.moveToPosition(-1); 382f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov while (mDataCursor.moveToNext()) { 383f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov long contactId = mDataCursor.getLong(DataQuery.CONTACT_ID); 384f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (contactId != currentContactId) { 385f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion = new Suggestion(); 386f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.contactId = contactId; 387f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.name = mDataCursor.getString(DataQuery.DISPLAY_NAME); 388c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov suggestion.lookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY); 389c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov suggestion.rawContacts = Lists.newArrayList(); 390f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov list.add(suggestion); 391f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov currentContactId = contactId; 392f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 393f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 394c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID); 395c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov if (!containsRawContact(suggestion, rawContactId)) { 396c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov RawContact rawContact = new RawContact(); 397c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov rawContact.rawContactId = rawContactId; 398c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov rawContact.accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME); 399c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov rawContact.accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE); 4002b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro rawContact.dataSet = mDataCursor.getString(DataQuery.DATA_SET); 401c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov suggestion.rawContacts.add(rawContact); 402f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 403f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 404f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov String mimetype = mDataCursor.getString(DataQuery.MIMETYPE); 405f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) { 406f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov String data = mDataCursor.getString(DataQuery.DATA1); 407f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); 408f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (!TextUtils.isEmpty(data) 409f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov && (superprimary != 0 || suggestion.phoneNumber == null)) { 410f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.phoneNumber = data; 411f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 412f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) { 413f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov String data = mDataCursor.getString(DataQuery.DATA1); 414f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY); 415f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (!TextUtils.isEmpty(data) 416f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov && (superprimary != 0 || suggestion.emailAddress == null)) { 417f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.emailAddress = data; 418f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 419f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) { 420f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov String data = mDataCursor.getString(DataQuery.DATA1); 421f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (!TextUtils.isEmpty(data)) { 422f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.nickname = data; 423f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 424f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) { 425f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov long dataId = mDataCursor.getLong(DataQuery.ID); 426f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov long photoId = mDataCursor.getLong(DataQuery.PHOTO_ID); 427f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (dataId == photoId && !mDataCursor.isNull(DataQuery.PHOTO)) { 428f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestion.photo = mDataCursor.getBlob(DataQuery.PHOTO); 429f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 430f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 431f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 432f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 433f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return list; 434f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 435c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov 436c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov public boolean containsRawContact(Suggestion suggestion, long rawContactId) { 437c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov if (suggestion.rawContacts != null) { 438c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov int count = suggestion.rawContacts.size(); 439c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov for (int i = 0; i < count; i++) { 440c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov if (suggestion.rawContacts.get(i).rawContactId == rawContactId) { 441c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov return true; 442c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 443c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 444c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 445c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov return false; 446c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov } 447f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov} 448