SearchIndexManager.java revision 05e50fbf9809bf04eceec3d2a2753630dc4f9315
1f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov/* 2f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * Copyright (C) 2011 The Android Open Source Project 3f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * 4f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * you may not use this file except in compliance with the License. 6f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * You may obtain a copy of the License at 7f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * 8f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * 10f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * See the License for the specific language governing permissions and 14f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * limitations under the License 15f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov */ 16f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovpackage com.android.providers.contacts; 17f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 18f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 19f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 20f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns; 21f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 22f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 23f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.content.ContentValues; 24f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.database.Cursor; 25f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 2605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikovimport android.os.SystemClock; 2705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 28f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.provider.ContactsContract.Data; 2905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 3005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 31f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.text.TextUtils; 32f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport android.util.Log; 33f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 34f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport java.util.HashSet; 35f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovimport java.util.Set; 36f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 37f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov/** 38f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * Maintains a search index for comprehensive contact search. 39f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov */ 40f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikovpublic class SearchIndexManager { 41f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private static final String TAG = "ContactsFTS"; 42f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 4305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final String PROPERTY_SEARCH_INDEX_VERSION = "search_index"; 4405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int SEARCH_INDEX_VERSION = 1; 4505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 46f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private static final class ContactIndexQuery { 47f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final String[] COLUMNS = { 48f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Data.CONTACT_ID, 49f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov MimetypesColumns.MIMETYPE, 50f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5, 51f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11, 52f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Data.DATA12, Data.DATA13, Data.DATA14 53f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov }; 54f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 55f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final int MIMETYPE = 1; 56f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 57f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 58f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static class IndexBuilder { 59f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final int SEPARATOR_SPACE = 0; 60f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final int SEPARATOR_PARENTHESES = 1; 61f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final int SEPARATOR_SLASH = 2; 62f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public static final int SEPARATOR_COMMA = 3; 63f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 64f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private StringBuilder mSbContent = new StringBuilder(); 65f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private StringBuilder mSbTokens = new StringBuilder(); 66f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private StringBuilder mSbElementContent = new StringBuilder(); 67f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private HashSet<String> mUniqueElements = new HashSet<String>(); 68f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private Cursor mCursor; 69f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 70f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov void setCursor(Cursor cursor) { 71f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov this.mCursor = cursor; 72f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 73f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 74f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov void reset() { 75f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSbContent.setLength(0); 76f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSbTokens.setLength(0); 77f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSbElementContent.setLength(0); 78f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mUniqueElements.clear(); 79f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 80f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 81f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public String getContent() { 82f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return mSbContent.length() == 0 ? null : mSbContent.toString(); 83f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 84f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 85f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public String getTokens() { 86f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return mSbTokens.length() == 0 ? null : mSbTokens.toString(); 87f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 88f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 89eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov public String getString(String columnName) { 90eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov return mCursor.getString(mCursor.getColumnIndex(columnName)); 91eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov } 92eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov 936d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov public int getInt(String columnName) { 946d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov return mCursor.getInt(mCursor.getColumnIndex(columnName)); 956d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov } 966d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov 97f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov @Override 98f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public String toString() { 99f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return "Content: " + mSbContent + "\n Tokens: " + mSbTokens; 100f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 101f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 102f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void commit() { 103f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (mSbElementContent.length() != 0) { 104eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov String content = mSbElementContent.toString().replace('\n', ' '); 105f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (!mUniqueElements.contains(content)) { 106f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (mSbContent.length() != 0) { 107f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSbContent.append('\n'); 108f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 109f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSbContent.append(content); 110f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mUniqueElements.add(content); 111f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 112eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.setLength(0); 113f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 114f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 115f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 116f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void appendContentFromColumn(String columnName) { 117f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov appendContentFromColumn(columnName, SEPARATOR_SPACE); 118f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 119f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 120f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void appendContentFromColumn(String columnName, int format) { 121eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov appendContent(getString(columnName), format); 122eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov } 123eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov 124eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov public void appendContent(String value) { 125eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov appendContent(value, SEPARATOR_SPACE); 126f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 127f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 128f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void appendContent(String value, int format) { 129f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (TextUtils.isEmpty(value)) { 130f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return; 131f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 132f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 133f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov switch (format) { 134f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov case SEPARATOR_SPACE: 135eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov if (mSbElementContent.length() > 0) { 136eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append(' '); 137f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 138eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append(value); 139f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov break; 140f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 141f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov case SEPARATOR_SLASH: 142eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append('/').append(value); 143f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov break; 144f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 145f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov case SEPARATOR_PARENTHESES: 146eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov if (mSbElementContent.length() > 0) { 147eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append(' '); 148f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 149eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append('(').append(value).append(')'); 150f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov break; 151f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 152f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov case SEPARATOR_COMMA: 153eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov if (mSbElementContent.length() > 0) { 154eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append(", "); 155f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 156eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbElementContent.append(value); 157f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov break; 158f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 159f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 160eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov 161eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov public void appendToken(String token) { 162eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov if (mSbTokens.length() != 0) { 163eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbTokens.append(' '); 164eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov } 165eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov mSbTokens.append(token); 166eeeed5669d98897501bf2b18c88579c7effd0955Dmitri Plotnikov } 167f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 168f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 169f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private final ContactsProvider2 mContactsProvider; 170f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private final ContactsDatabaseHelper mDbHelper; 171f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 172f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private IndexBuilder mIndexBuilder = new IndexBuilder(); 173f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 174f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 175f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 176f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public SearchIndexManager(ContactsProvider2 contactsProvider) { 177f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov this.mContactsProvider = contactsProvider; 178f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mDbHelper = (ContactsDatabaseHelper) mContactsProvider.getDatabaseHelper(); 179f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 180f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 18105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov public void updateIndex() { 18205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov if (getSearchIndexVersion() == SEARCH_INDEX_VERSION) { 18305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov return; 18405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 18505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getWritableDatabase(); 18605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov db.beginTransaction(); 18705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov try { 18805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov if (getSearchIndexVersion() != SEARCH_INDEX_VERSION) { 18905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov rebuildIndex(db); 19005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov setSearchIndexVersion(SEARCH_INDEX_VERSION); 19105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov db.setTransactionSuccessful(); 19205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 19305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } finally { 19405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov db.endTransaction(); 19505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 19605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 19705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 19805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private void rebuildIndex(SQLiteDatabase db) { 19905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mContactsProvider.setProviderStatus(ProviderStatus.STATUS_UPGRADING); 20005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 20105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov int count = 0; 20205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov try { 20305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mDbHelper.createSearchIndexTable(db); 20405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov count = buildIndex(db, RawContacts.CONTACT_ID + " IN " 20505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov + "(SELECT " + Contacts._ID + " FROM " + Tables.DEFAULT_DIRECTORY + ")", false); 20605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } finally { 20705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mContactsProvider.setProviderStatus(ProviderStatus.STATUS_NORMAL); 20805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 20905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 21005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov Log.i(TAG, "Rebuild contact search index in " + (end - start) + "ms, " 21105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov + count + " contacts"); 21205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 21305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 21405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 215f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void updateIndexForRawContacts(Set<Long> rawContactIds) { 216f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSb.setLength(0); 217f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSb.append(Data.RAW_CONTACT_ID + " IN ("); 218f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov for (Long rawContactId : rawContactIds) { 219f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSb.append(rawContactId).append(","); 220f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 221f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSb.setLength(mSb.length() - 1); 222f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSb.append(')'); 223f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 22405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov buildIndex(mDbHelper.getWritableDatabase(), mSb.toString(), true); 22505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 22605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 22705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private int buildIndex(SQLiteDatabase db, String selection, boolean replace) { 22805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov int count = 0; 229f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Cursor cursor = db.query(Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS, 23005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov ContactIndexQuery.COLUMNS, selection, null, null, null, 231f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov Data.CONTACT_ID + ", " + DataColumns.MIMETYPE_ID + ", " + Data.IS_SUPER_PRIMARY 232f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov + ", " + DataColumns.CONCRETE_ID); 233f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mIndexBuilder.setCursor(cursor); 234f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mIndexBuilder.reset(); 235f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov try { 236f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov long currentContactId = -1; 237f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov while (cursor.moveToNext()) { 238f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov long contactId = cursor.getLong(0); 239f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (contactId != currentContactId) { 240f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (currentContactId != -1) { 24105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov saveContactIndex(db, currentContactId, mIndexBuilder, replace); 24205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov count++; 243f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 244f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov currentContactId = contactId; 245f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mIndexBuilder.reset(); 246f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 247f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov String mimetype = cursor.getString(ContactIndexQuery.MIMETYPE); 248f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov DataRowHandler dataRowHandler = mContactsProvider.getDataRowHandler(mimetype); 249f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (dataRowHandler.hasSearchableData()) { 250f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov dataRowHandler.appendSearchableData(mIndexBuilder); 251f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mIndexBuilder.commit(); 252f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 253f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 254f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (currentContactId != -1) { 25505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov saveContactIndex(db, currentContactId, mIndexBuilder, replace); 25605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov count++; 257f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 258f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } finally { 259f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov cursor.close(); 260f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 26105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov return count; 262f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 263f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 26405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private void saveContactIndex( 26505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov SQLiteDatabase db, long contactId, IndexBuilder builder, boolean replace) { 266f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mValues.clear(); 267f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mValues.put(SearchIndexColumns.CONTENT, builder.getContent()); 268f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mValues.put(SearchIndexColumns.TOKENS, builder.getTokens()); 26905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov if (replace) { 27005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 27105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov int count = db.update(Tables.SEARCH_INDEX, mValues, 27205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov SearchIndexColumns.CONTACT_ID + "=CAST(? AS int)", mSelectionArgs1); 27305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov if (count == 0) { 27405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mValues.put(SearchIndexColumns.CONTACT_ID, contactId); 27505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov db.insert(Tables.SEARCH_INDEX, null, mValues); 27605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 27705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } else { 278f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mValues.put(SearchIndexColumns.CONTACT_ID, contactId); 279f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov db.insert(Tables.SEARCH_INDEX, null, mValues); 280f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 281f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 28205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private int getSearchIndexVersion() { 28305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov return Integer.parseInt(mDbHelper.getProperty(PROPERTY_SEARCH_INDEX_VERSION, "0")); 28405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 28505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 28605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private void setSearchIndexVersion(int version) { 28705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mDbHelper.setProperty(PROPERTY_SEARCH_INDEX_VERSION, String.valueOf(version)); 28805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 289f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov} 290