16f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio/* 26f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project 36f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * 46f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 56f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * you may not use this file except in compliance with the License. 66f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * You may obtain a copy of the License at 76f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * 86f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 96f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * 106f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 116f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 126f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * See the License for the specific language governing permissions and 146f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * limitations under the License. 156f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio */ 166f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 17fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Megliopackage com.android.settings.search; 186f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 19fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.content.ContentResolver; 206f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.content.ContentValues; 216f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.content.Context; 22fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.content.Intent; 23b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglioimport android.content.pm.ApplicationInfo; 24b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglioimport android.content.pm.PackageInfo; 25fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.content.pm.PackageManager; 26fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.content.pm.ResolveInfo; 276f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.content.res.TypedArray; 286f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.content.res.XmlResourceParser; 296f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.database.Cursor; 306f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.database.DatabaseUtils; 31b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglioimport android.database.MergeCursor; 326f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.database.sqlite.SQLiteDatabase; 33dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglioimport android.database.sqlite.SQLiteException; 34ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monkimport android.database.sqlite.SQLiteFullException; 35fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.net.Uri; 366f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.os.AsyncTask; 37fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.provider.SearchIndexableData; 38fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.provider.SearchIndexableResource; 39fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglioimport android.provider.SearchIndexablesContract; 406f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.text.TextUtils; 416f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.util.AttributeSet; 426f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.util.Log; 436f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.util.TypedValue; 446f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport android.util.Xml; 4539b467482d1bf256a111c757e9b7621c6f523271Jason Monk 466f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport com.android.settings.R; 4739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.search.IndexDatabaseHelper.IndexColumns; 4839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.search.IndexDatabaseHelper.Tables; 4939b467482d1bf256a111c757e9b7621c6f523271Jason Monk 506f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport org.xmlpull.v1.XmlPullParser; 516f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport org.xmlpull.v1.XmlPullParserException; 526f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 536f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.io.IOException; 54b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglioimport java.lang.reflect.Field; 55363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglioimport java.text.Normalizer; 566f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.util.ArrayList; 5745f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglioimport java.util.Collections; 58d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglioimport java.util.Date; 59df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglioimport java.util.HashMap; 606f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.util.List; 616f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.util.Locale; 62df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglioimport java.util.Map; 636f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.util.concurrent.ExecutionException; 646f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglioimport java.util.concurrent.atomic.AtomicBoolean; 65363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglioimport java.util.regex.Pattern; 666f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 67df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; 68b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME; 6939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES; 70b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID; 71b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION; 72b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS; 7339b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE; 74b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY; 7539b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS; 7639b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_RANK; 7739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE; 7839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF; 7939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON; 8039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE; 81957ccf30b9c969a6362fccb293d2c2df8bd1ad32Fabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID; 82b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME; 83b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID; 84b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION; 85b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglioimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS; 8639b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE; 8739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK; 8839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID; 896f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 906f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Megliopublic class Index { 916f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 92b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio private static final String LOG_TAG = "Index"; 936f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 946f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio // Those indices should match the indices of SELECT_COLUMNS ! 957d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_RANK = 0; 966f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio public static final int COLUMN_INDEX_TITLE = 1; 979593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio public static final int COLUMN_INDEX_SUMMARY_ON = 2; 989593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio public static final int COLUMN_INDEX_SUMMARY_OFF = 3; 99a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio public static final int COLUMN_INDEX_ENTRIES = 4; 1007d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_KEYWORDS = 5; 1017d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_CLASS_NAME = 6; 1027d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_SCREEN_TITLE = 7; 1037d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_ICON = 8; 1047d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_INTENT_ACTION = 9; 1057d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10; 1067d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11; 1077d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_ENABLED = 12; 1087d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio public static final int COLUMN_INDEX_KEY = 13; 109957ccf30b9c969a6362fccb293d2c2df8bd1ad32Fabrice Di Meglio public static final int COLUMN_INDEX_USER_ID = 14; 1106f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 1118f5c65fd010d249770fda81c1129c1d7555a3299Fabrice Di Meglio public static final String ENTRIES_SEPARATOR = "|"; 1128f5c65fd010d249770fda81c1129c1d7555a3299Fabrice Di Meglio 1136f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values 1146f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio private static final String[] SELECT_COLUMNS = new String[] { 1159593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_RANK, // 0 1169593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_TITLE, // 1 1179593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_ON, // 2 1189593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_OFF, // 3 119a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio IndexColumns.DATA_ENTRIES, // 4 1207d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.DATA_KEYWORDS, // 5 1217d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.CLASS_NAME, // 6 1227d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.SCREEN_TITLE, // 7 1237d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.ICON, // 8 1247d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.INTENT_ACTION, // 9 1257d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.INTENT_TARGET_PACKAGE, // 10 1267d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.INTENT_TARGET_CLASS, // 11 1277d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.ENABLED, // 12 1287d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio IndexColumns.DATA_KEY_REF // 13 1296f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio }; 1306f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 131b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio private static final String[] MATCH_COLUMNS_PRIMARY = { 1320d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio IndexColumns.DATA_TITLE, 133e6b336d1a05752b546319a33a5f5b5c65bccf4e9Fabrice Di Meglio IndexColumns.DATA_TITLE_NORMALIZED, 134e6b336d1a05752b546319a33a5f5b5c65bccf4e9Fabrice Di Meglio IndexColumns.DATA_KEYWORDS 135b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio }; 136b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio 137b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio private static final String[] MATCH_COLUMNS_SECONDARY = { 1389593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_ON, 1399593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_ON_NORMALIZED, 1409593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_OFF, 1419593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, 142e6b336d1a05752b546319a33a5f5b5c65bccf4e9Fabrice Di Meglio IndexColumns.DATA_ENTRIES 1430d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio }; 1440d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio 145d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio // Max number of saved search queries (who will be used for proposing suggestions) 146d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private static long MAX_SAVED_SEARCH_QUERY = 64; 147d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio // Max number of proposed suggestions 148d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private static final int MAX_PROPOSED_SUGGESTIONS = 5; 149d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 150dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio private static final String BASE_AUTHORITY = "com.android.settings"; 151dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio 1526f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio private static final String EMPTY = ""; 1536f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio private static final String NON_BREAKING_HYPHEN = "\u2011"; 15435c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette private static final String LIST_DELIMITERS = "[,]\\s*"; 1556f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio private static final String HYPHEN = "-"; 15635c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette private static final String SPACE = " "; 1576f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 1589593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER = 1599593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio "SEARCH_INDEX_DATA_PROVIDER"; 1609593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 1619593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen"; 1629593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference"; 163a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference"; 1649593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 16545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio private static final List<String> EMPTY_LIST = Collections.<String>emptyList(); 16645f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 1676f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio private static Index sInstance; 168363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio 169363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio private static final Pattern REMOVE_DIACRITICALS_PATTERN 170363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); 171363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio 17251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio /** 17351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio * A private class to describe the update data for the Index database 17451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio */ 1759301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio private static class UpdateData { 17651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio public List<SearchIndexableData> dataToUpdate; 177724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio public List<SearchIndexableData> dataToDelete; 178df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio public Map<String, List<String>> nonIndexableKeys; 179df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 1805d219a2cfa320501a96968d8827fa9c195b04451Justin Klaassen public boolean forceUpdate; 1815d219a2cfa320501a96968d8827fa9c195b04451Justin Klaassen public boolean fullIndex; 1826f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 18351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio public UpdateData() { 18451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio dataToUpdate = new ArrayList<SearchIndexableData>(); 185724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio dataToDelete = new ArrayList<SearchIndexableData>(); 186df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio nonIndexableKeys = new HashMap<String, List<String>>(); 18751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 18851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 18972e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio public UpdateData(UpdateData other) { 19072e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio dataToUpdate = new ArrayList<SearchIndexableData>(other.dataToUpdate); 19172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio dataToDelete = new ArrayList<SearchIndexableData>(other.dataToDelete); 19272e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio nonIndexableKeys = new HashMap<String, List<String>>(other.nonIndexableKeys); 193f91b4dbc331d3c84e06bcfed3338e38a043f4a13Fabrice Di Meglio forceUpdate = other.forceUpdate; 1946c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk fullIndex = other.fullIndex; 19572e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio } 19672e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio 19772e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio public UpdateData copy() { 19872e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio return new UpdateData(this); 19972e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio } 20072e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio 20151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio public void clear() { 20251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio dataToUpdate.clear(); 20351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio dataToDelete.clear(); 204df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio nonIndexableKeys.clear(); 20551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio forceUpdate = false; 2066c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk fullIndex = false; 20751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 20851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 2096f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 2109301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio private final AtomicBoolean mIsAvailable = new AtomicBoolean(false); 2119301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio private final UpdateData mDataToProcess = new UpdateData(); 2129301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio private Context mContext; 2139301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio private final String mBaseAuthority; 2149301441e2af4f9ee1eca4236e6e04b4666c0d986Fabrice Di Meglio 2156f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio /** 2166f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * A basic singleton 2176f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio */ 2186f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio public static Index getInstance(Context context) { 2196f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio if (sInstance == null) { 2206c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk sInstance = new Index(context.getApplicationContext(), BASE_AUTHORITY); 2216f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 2226f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return sInstance; 2236f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 2246f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 225dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio public Index(Context context, String baseAuthority) { 2266f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio mContext = context; 227dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio mBaseAuthority = baseAuthority; 2286f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 2296f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 230d25314d3305ed1a07b53991a978cd71219ef2a10Fabrice Di Meglio public void setContext(Context context) { 231d25314d3305ed1a07b53991a978cd71219ef2a10Fabrice Di Meglio mContext = context; 232d25314d3305ed1a07b53991a978cd71219ef2a10Fabrice Di Meglio } 233d25314d3305ed1a07b53991a978cd71219ef2a10Fabrice Di Meglio 2346f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio public boolean isAvailable() { 2356f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return mIsAvailable.get(); 2366f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 2376f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 23851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio public Cursor search(String query) { 239b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio final SQLiteDatabase database = getReadableDatabase(); 240b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio final Cursor[] cursors = new Cursor[2]; 241b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio 242b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio final String primarySql = buildSearchSQL(query, MATCH_COLUMNS_PRIMARY, true); 243b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio Log.d(LOG_TAG, "Search primary query: " + primarySql); 244b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio cursors[0] = database.rawQuery(primarySql, null); 245b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio 246b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio // We need to use an EXCEPT operator as negate MATCH queries do not work. 247b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio StringBuilder sql = new StringBuilder( 248b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio buildSearchSQL(query, MATCH_COLUMNS_SECONDARY, false)); 249b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio sql.append(" EXCEPT "); 250b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio sql.append(primarySql); 251b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio 252b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio final String secondarySql = sql.toString(); 253b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio Log.d(LOG_TAG, "Search secondary query: " + secondarySql); 254b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio cursors[1] = database.rawQuery(secondarySql, null); 255b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio 256b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio return new MergeCursor(cursors); 257d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 258d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 259d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio public Cursor getSuggestions(String query) { 260d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final String sql = buildSuggestionsSQL(query); 261d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio Log.d(LOG_TAG, "Suggestions query: " + sql); 26251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return getReadableDatabase().rawQuery(sql, null); 26351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 26451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 265d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private String buildSuggestionsSQL(String query) { 266d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio StringBuilder sb = new StringBuilder(); 267d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 268d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append("SELECT "); 269d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY); 270d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(" FROM "); 271d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(Tables.TABLE_SAVED_QUERIES); 272d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 273d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio if (TextUtils.isEmpty(query)) { 274d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(" ORDER BY rowId DESC"); 275d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } else { 276d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(" WHERE "); 277d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY); 278d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(" LIKE "); 279d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append("'"); 280d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(query); 281d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append("%"); 282d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append("'"); 283d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 284d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 285d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(" LIMIT "); 286d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(MAX_PROPOSED_SUGGESTIONS); 287d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 288d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio return sb.toString(); 289d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 290d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 291d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio public long addSavedQuery(String query){ 292d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final SaveSearchQueryTask task = new SaveSearchQueryTask(); 293d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio task.execute(query); 294d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio try { 295d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio return task.get(); 296d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } catch (InterruptedException e) { 297d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio Log.e(LOG_TAG, "Cannot insert saved query: " + query, e); 298d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio return -1 ; 299d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } catch (ExecutionException e) { 300d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio Log.e(LOG_TAG, "Cannot insert saved query: " + query, e); 301d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio return -1; 302d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 303d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 304d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 30572e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio public void update() { 3066c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk AsyncTask.execute(new Runnable() { 3076c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk @Override 3086c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk public void run() { 3096c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk final Intent intent = new Intent(SearchIndexablesContract.PROVIDER_INTERFACE); 3106c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk List<ResolveInfo> list = 3116c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk mContext.getPackageManager().queryIntentContentProviders(intent, 0); 3126c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk 3136c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk final int size = list.size(); 3146c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk for (int n = 0; n < size; n++) { 3156c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk final ResolveInfo info = list.get(n); 3166c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk if (!isWellKnownProvider(info)) { 3176c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk continue; 3186c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 3196c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk final String authority = info.providerInfo.authority; 3206c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk final String packageName = info.providerInfo.packageName; 321df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 3226c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk addIndexablesFromRemoteProvider(packageName, authority); 3236c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk addNonIndexablesKeysFromRemoteProvider(packageName, authority); 3246c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 325df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 3266c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk mDataToProcess.fullIndex = true; 3276c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk updateInternal(); 3286c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 3296c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk }); 330df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 331df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 332df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private boolean addIndexablesFromRemoteProvider(String packageName, String authority) { 333df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio try { 334eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio final int baseRank = Ranking.getBaseRankForAuthority(authority); 335eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio 336dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio final Context context = mBaseAuthority.equals(authority) ? 337dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio mContext : mContext.createPackageContext(packageName, 0); 338df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 339df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Uri uriForResources = buildUriForXmlResources(authority); 340dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio addIndexablesForXmlResourceUri(context, packageName, uriForResources, 341eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, baseRank); 342df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 343df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Uri uriForRawData = buildUriForRawData(authority); 344dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio addIndexablesForRawDataUri(context, packageName, uriForRawData, 345eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, baseRank); 346df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return true; 347df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } catch (PackageManager.NameNotFoundException e) { 348df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio Log.w(LOG_TAG, "Could not create context for " + packageName + ": " 349df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio + Log.getStackTraceString(e)); 350df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return false; 351df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 352df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 353df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 354df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private void addNonIndexablesKeysFromRemoteProvider(String packageName, 355df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio String authority) { 356df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final List<String> keys = 357df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio getNonIndexablesKeysFromRemoteProvider(packageName, authority); 358df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio addNonIndexableKeys(packageName, keys); 359df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 360df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 361df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private List<String> getNonIndexablesKeysFromRemoteProvider(String packageName, 362df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio String authority) { 363df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio try { 364df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Context packageContext = mContext.createPackageContext(packageName, 0); 365df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 366df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Uri uriForNonIndexableKeys = buildUriForNonIndexableKeys(authority); 367df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return getNonIndexablesKeys(packageContext, uriForNonIndexableKeys, 368df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS); 369df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } catch (PackageManager.NameNotFoundException e) { 370df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio Log.w(LOG_TAG, "Could not create context for " + packageName + ": " 371df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio + Log.getStackTraceString(e)); 372df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return EMPTY_LIST; 373df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 374df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 375df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 376df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private List<String> getNonIndexablesKeys(Context packageContext, Uri uri, 377df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio String[] projection) { 378df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 379df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final ContentResolver resolver = packageContext.getContentResolver(); 380df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Cursor cursor = resolver.query(uri, projection, null, null, null); 381df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 382df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (cursor == null) { 383df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString()); 384df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return EMPTY_LIST; 385df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 386df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 387df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio List<String> result = new ArrayList<String>(); 388df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio try { 389df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final int count = cursor.getCount(); 390df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (count > 0) { 391df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio while (cursor.moveToNext()) { 392df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE); 393df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio result.add(key); 394df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 395df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 396df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return result; 397df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } finally { 398df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio cursor.close(); 399df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 400df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 401df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 402fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio public void addIndexableData(SearchIndexableData data) { 40351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio synchronized (mDataToProcess) { 40451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio mDataToProcess.dataToUpdate.add(data); 405fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 406fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 407fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 408fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio public void addIndexableData(SearchIndexableResource[] array) { 40951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio synchronized (mDataToProcess) { 410b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio final int count = array.length; 411b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio for (int n = 0; n < count; n++) { 41251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio mDataToProcess.dataToUpdate.add(array[n]); 413b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 414b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 415b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 416b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 417724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio public void deleteIndexableData(SearchIndexableData data) { 41851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio synchronized (mDataToProcess) { 419724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio mDataToProcess.dataToDelete.add(data); 420b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 421b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 422b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 423df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio public void addNonIndexableKeys(String authority, List<String> keys) { 424df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio synchronized (mDataToProcess) { 425df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio mDataToProcess.nonIndexableKeys.put(authority, keys); 42651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 42751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 42851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 429b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio /** 430b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio * Only allow a "well known" SearchIndexablesProvider. The provider should: 431b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio * 432b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio * - have read/write {@link android.Manifest.permission#READ_SEARCH_INDEXABLES} 433b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio * - be from a privileged package 434b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio */ 435b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio private boolean isWellKnownProvider(ResolveInfo info) { 436b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio final String authority = info.providerInfo.authority; 437b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio final String packageName = info.providerInfo.applicationInfo.packageName; 438b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 439b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio if (TextUtils.isEmpty(authority) || TextUtils.isEmpty(packageName)) { 440b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio return false; 441b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 442b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 443b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio final String readPermission = info.providerInfo.readPermission; 444b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio final String writePermission = info.providerInfo.writePermission; 445b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 446b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio if (TextUtils.isEmpty(readPermission) || TextUtils.isEmpty(writePermission)) { 447b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio return false; 448b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 449b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 450b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(readPermission) || 451b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio !android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(writePermission)) { 452b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio return false; 453b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 454b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 455b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio return isPrivilegedPackage(packageName); 456b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 457b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 458b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio private boolean isPrivilegedPackage(String packageName) { 459b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio final PackageManager pm = mContext.getPackageManager(); 460b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio try { 461b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio PackageInfo packInfo = pm.getPackageInfo(packageName, 0); 462cc254f4da96506901268c4a0b1d3cfacb5f44948Alex Klyubin return ((packInfo.applicationInfo.privateFlags 463cc254f4da96506901268c4a0b1d3cfacb5f44948Alex Klyubin & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0); 464b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } catch (PackageManager.NameNotFoundException e) { 465b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio return false; 466b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 467b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio } 468b1648e6c546523cd3ede111c6b494a96477de2f1Fabrice Di Meglio 46972e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio private void updateFromRemoteProvider(String packageName, String authority) { 47072e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio if (addIndexablesFromRemoteProvider(packageName, authority)) { 47172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio updateInternal(); 47251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 47351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 47451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 475490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio /** 476490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * Update the Index for a specific class name resources 477490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * 478490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * @param className the class name (typically a fragment name). 479490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * @param rebuild true means that you want to delete the data from the Index first. 480490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * @param includeInSearchResults true means that you want the bit "enabled" set so that the 481490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio * data will be seen included into the search results 482490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio */ 4836c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk public void updateFromClassNameResource(String className, final boolean rebuild, 484490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio boolean includeInSearchResults) { 48551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (className == null) { 48651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio throw new IllegalArgumentException("class name cannot be null!"); 48751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 48851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final SearchIndexableResource res = SearchIndexableResources.getResourceByName(className); 48951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (res == null ) { 49051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio Log.e(LOG_TAG, "Cannot find SearchIndexableResources for class name: " + className); 49172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio return; 492fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 49355638cb6c6730104ec04287e7566eae7f3e57385Fabrice Di Meglio res.context = mContext; 49451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio res.enabled = includeInSearchResults; 4956c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk AsyncTask.execute(new Runnable() { 4966c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk @Override 4976c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk public void run() { 4986c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk if (rebuild) { 4996c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk deleteIndexableData(res); 5006c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 5016c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk addIndexableData(res); 5026c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk mDataToProcess.forceUpdate = true; 5036c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk updateInternal(); 5046c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk res.enabled = false; 5056c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 5066c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk }); 50751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 508fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 50972e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio public void updateFromSearchIndexableData(SearchIndexableData data) { 5106c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk AsyncTask.execute(new Runnable() { 5116c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk @Override 5126c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk public void run() { 5136c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk addIndexableData(data); 5146c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk mDataToProcess.forceUpdate = true; 5156c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk updateInternal(); 5166c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 5176c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk }); 518fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 519fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 52051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private SQLiteDatabase getReadableDatabase() { 52151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return IndexDatabaseHelper.getInstance(mContext).getReadableDatabase(); 52251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 52351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 52451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private SQLiteDatabase getWritableDatabase() { 525dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio try { 526dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio return IndexDatabaseHelper.getInstance(mContext).getWritableDatabase(); 527dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio } catch (SQLiteException e) { 528dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio Log.e(LOG_TAG, "Cannot open writable database", e); 529dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio return null; 530dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio } 53151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 53251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 533fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio private static Uri buildUriForXmlResources(String authority) { 534fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio return Uri.parse("content://" + authority + "/" + 535fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio SearchIndexablesContract.INDEXABLES_XML_RES_PATH); 536fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 537fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 538fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio private static Uri buildUriForRawData(String authority) { 539fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio return Uri.parse("content://" + authority + "/" + 540fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio SearchIndexablesContract.INDEXABLES_RAW_PATH); 541fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 542fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 543df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private static Uri buildUriForNonIndexableKeys(String authority) { 544df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return Uri.parse("content://" + authority + "/" + 545df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH); 546df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 547df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 54872e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio private void updateInternal() { 54951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio synchronized (mDataToProcess) { 55051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final UpdateIndexTask task = new UpdateIndexTask(); 55172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio UpdateData copy = mDataToProcess.copy(); 55272e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio task.execute(copy); 55372e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio mDataToProcess.clear(); 55451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 55551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 556fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 55751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void addIndexablesForXmlResourceUri(Context packageContext, String packageName, 558b2385ea46286933add8ea3fb86db7870fe294334Fabrice Di Meglio Uri uri, String[] projection, int baseRank) { 55951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 56051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final ContentResolver resolver = packageContext.getContentResolver(); 561df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Cursor cursor = resolver.query(uri, projection, null, null, null); 562fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 563fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio if (cursor == null) { 564fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString()); 565fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio return; 566fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 567fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 568fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio try { 569fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio final int count = cursor.getCount(); 570fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio if (count > 0) { 571fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio while (cursor.moveToNext()) { 572eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio final int providerRank = cursor.getInt(COLUMN_INDEX_XML_RES_RANK); 573eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio final int rank = (providerRank > 0) ? baseRank + providerRank : baseRank; 574eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio 575b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final int xmlResId = cursor.getInt(COLUMN_INDEX_XML_RES_RESID); 576fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 577b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String className = cursor.getString(COLUMN_INDEX_XML_RES_CLASS_NAME); 578b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final int iconResId = cursor.getInt(COLUMN_INDEX_XML_RES_ICON_RESID); 579fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 580b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String action = cursor.getString(COLUMN_INDEX_XML_RES_INTENT_ACTION); 581b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String targetPackage = cursor.getString( 582b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE); 583b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String targetClass = cursor.getString( 584b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS); 585fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 5865135dce1429facfd764f4afffe69d60c19589750Fabrice Di Meglio SearchIndexableResource sir = new SearchIndexableResource(packageContext); 587fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.rank = rank; 588fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.xmlResId = xmlResId; 589fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.className = className; 590fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.packageName = packageName; 591fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.iconResId = iconResId; 592fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.intentAction = action; 593fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.intentTargetPackage = targetPackage; 594fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio sir.intentTargetClass = targetClass; 595fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 596fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio addIndexableData(sir); 597fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 598fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 599fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } finally { 600fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio cursor.close(); 601fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 602fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 603fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 60451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void addIndexablesForRawDataUri(Context packageContext, String packageName, 605b2385ea46286933add8ea3fb86db7870fe294334Fabrice Di Meglio Uri uri, String[] projection, int baseRank) { 606fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 60751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final ContentResolver resolver = packageContext.getContentResolver(); 608df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio final Cursor cursor = resolver.query(uri, projection, null, null, null); 609fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 610fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio if (cursor == null) { 611fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString()); 612fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio return; 613fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 614fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 615fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio try { 616fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio final int count = cursor.getCount(); 617fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio if (count > 0) { 618fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio while (cursor.moveToNext()) { 619eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio final int providerRank = cursor.getInt(COLUMN_INDEX_RAW_RANK); 620eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio final int rank = (providerRank > 0) ? baseRank + providerRank : baseRank; 621eed44c9d5f72a1981b7057ae8f1744863e036078Fabrice Di Meglio 622b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String title = cursor.getString(COLUMN_INDEX_RAW_TITLE); 623b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String summaryOn = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_ON); 624b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String summaryOff = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_OFF); 625b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String entries = cursor.getString(COLUMN_INDEX_RAW_ENTRIES); 626b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String keywords = cursor.getString(COLUMN_INDEX_RAW_KEYWORDS); 627fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 628b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String screenTitle = cursor.getString(COLUMN_INDEX_RAW_SCREEN_TITLE); 629fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 630b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String className = cursor.getString(COLUMN_INDEX_RAW_CLASS_NAME); 631b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final int iconResId = cursor.getInt(COLUMN_INDEX_RAW_ICON_RESID); 632fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 633b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String action = cursor.getString(COLUMN_INDEX_RAW_INTENT_ACTION); 634b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String targetPackage = cursor.getString( 635b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE); 636b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String targetClass = cursor.getString( 637b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio COLUMN_INDEX_RAW_INTENT_TARGET_CLASS); 638fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 639b914322590d74b508ff94b4426cb4b11a324e72cFabrice Di Meglio final String key = cursor.getString(COLUMN_INDEX_RAW_KEY); 640957ccf30b9c969a6362fccb293d2c2df8bd1ad32Fabrice Di Meglio final int userId = cursor.getInt(COLUMN_INDEX_RAW_USER_ID); 641c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio 6425135dce1429facfd764f4afffe69d60c19589750Fabrice Di Meglio SearchIndexableRaw data = new SearchIndexableRaw(packageContext); 643fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.rank = rank; 644fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.title = title; 6459593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio data.summaryOn = summaryOn; 6469593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio data.summaryOff = summaryOff; 647a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio data.entries = entries; 648fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.keywords = keywords; 649fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.screenTitle = screenTitle; 650fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.className = className; 651fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.packageName = packageName; 652fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.iconResId = iconResId; 653fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.intentAction = action; 654fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.intentTargetPackage = targetPackage; 655fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio data.intentTargetClass = targetClass; 656c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio data.key = key; 657957ccf30b9c969a6362fccb293d2c2df8bd1ad32Fabrice Di Meglio data.userId = userId; 658fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 659fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio addIndexableData(data); 660fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 661fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 662fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } finally { 663fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio cursor.close(); 664fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 665fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 666fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 667b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio private String buildSearchSQL(String query, String[] colums, boolean withOrderBy) { 6686f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio StringBuilder sb = new StringBuilder(); 669b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio sb.append(buildSearchSQLForColumn(query, colums)); 670b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio if (withOrderBy) { 671b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio sb.append(" ORDER BY "); 672b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio sb.append(IndexColumns.DATA_RANK); 673b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio } 6746f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return sb.toString(); 6756f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 6766f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 677d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private String buildSearchSQLForColumn(String query, String[] columnNames) { 6786f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio StringBuilder sb = new StringBuilder(); 6796f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append("SELECT "); 6806f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio for (int n = 0; n < SELECT_COLUMNS.length; n++) { 6816f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(SELECT_COLUMNS[n]); 6826f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio if (n < SELECT_COLUMNS.length - 1) { 6836f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(", "); 6846f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 6856f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 6866f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(" FROM "); 6876f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(Tables.TABLE_PREFS_INDEX); 6886f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(" WHERE "); 689d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio sb.append(buildSearchWhereStringForColumns(query, columnNames)); 6906f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 6916f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return sb.toString(); 6926f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 6936f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 694d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private String buildSearchWhereStringForColumns(String query, String[] columnNames) { 6950d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio final StringBuilder sb = new StringBuilder(Tables.TABLE_PREFS_INDEX); 6966f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(" MATCH "); 697d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio DatabaseUtils.appendEscapedSQLString(sb, 698d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio buildSearchMatchStringForColumns(query, columnNames)); 6996f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(" AND "); 7006f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(IndexColumns.LOCALE); 7016f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio sb.append(" = "); 7026f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio DatabaseUtils.appendEscapedSQLString(sb, Locale.getDefault().toString()); 70351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio sb.append(" AND "); 70451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio sb.append(IndexColumns.ENABLED); 70551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio sb.append(" = 1"); 7066f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return sb.toString(); 7076f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 7086f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 709d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private String buildSearchMatchStringForColumns(String query, String[] columnNames) { 7100d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio final String value = query + "*"; 7110d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio StringBuilder sb = new StringBuilder(); 7120d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio final int count = columnNames.length; 7130d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio for (int n = 0; n < count; n++) { 7140d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio sb.append(columnNames[n]); 7150d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio sb.append(":"); 7160d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio sb.append(value); 7170d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio if (n < count - 1) { 7180d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio sb.append(" OR "); 7190d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio } 7200d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio } 7210d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio return sb.toString(); 7220d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio } 7230d4005a1c755c4233bdf75d30a1b6ebc99856ec7Fabrice Di Meglio 72451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr, 725df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio SearchIndexableData data, Map<String, List<String>> nonIndexableKeys) { 72651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (data instanceof SearchIndexableResource) { 727df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys); 72851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } else if (data instanceof SearchIndexableRaw) { 72951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio indexOneRaw(database, localeStr, (SearchIndexableRaw) data); 73051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 7316f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 7326f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 733df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio private void indexOneRaw(SQLiteDatabase database, String localeStr, 734df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio SearchIndexableRaw raw) { 735df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio // Should be the same locale as the one we are processing 736df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { 737df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return; 738df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 739df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 740df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio updateOneRowWithFilteredData(database, localeStr, 741df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.title, 742df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.summaryOn, 743df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.summaryOff, 744df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.entries, 745df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.className, 746df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.screenTitle, 747df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.iconResId, 748df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.rank, 749df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.keywords, 750df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.intentAction, 751df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.intentTargetPackage, 752df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.intentTargetClass, 753df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio raw.enabled, 754d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio raw.key, 755d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio raw.userId); 756df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 757df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 7589a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio private static boolean isIndexableClass(final Class<?> clazz) { 7599a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return (clazz != null) && Indexable.class.isAssignableFrom(clazz); 7609a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } 7619a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 7629a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio private static Class<?> getIndexableClass(String className) { 7639a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio final Class<?> clazz; 7649a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio try { 7659a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio clazz = Class.forName(className); 7669a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } catch (ClassNotFoundException e) { 7679a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, "Cannot find class: " + className); 7689a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return null; 7699a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } 7709a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return isIndexableClass(clazz) ? clazz : null; 7719a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } 7729a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 77351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void indexOneResource(SQLiteDatabase database, String localeStr, 774df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio SearchIndexableResource sir, Map<String, List<String>> nonIndexableKeysFromResource) { 77545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 77645f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio if (sir == null) { 77745f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio Log.e(LOG_TAG, "Cannot index a null resource!"); 77845f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio return; 77945f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio } 78045f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 7819a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio final List<String> nonIndexableKeys = new ArrayList<String>(); 782df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 783a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (sir.xmlResId > SearchIndexableResources.NO_DATA_RES_ID) { 784df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio List<String> resNonIndxableKeys = nonIndexableKeysFromResource.get(sir.packageName); 785df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (resNonIndxableKeys != null && resNonIndxableKeys.size() > 0) { 786df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio nonIndexableKeys.addAll(resNonIndxableKeys); 78745f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio } 7889a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 78951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio indexFromResource(sir.context, database, localeStr, 79051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio sir.xmlResId, sir.className, sir.iconResId, sir.rank, 79145f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio sir.intentAction, sir.intentTargetPackage, sir.intentTargetClass, 792df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio nonIndexableKeys); 7939a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } else { 7949a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio if (TextUtils.isEmpty(sir.className)) { 7959a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.w(LOG_TAG, "Cannot index an empty Search Provider name!"); 7969a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return; 7979a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } 7989a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 7999a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio final Class<?> clazz = getIndexableClass(sir.className); 8009a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio if (clazz == null) { 8019a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className + 8029a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio "' should implement the " + Indexable.class.getName() + " interface!"); 8039a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return; 8049a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } 8059a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 8069a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio // Will be non null only for a Local provider implementing a 8079a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio // SEARCH_INDEX_DATA_PROVIDER field 8089a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio final Indexable.SearchIndexProvider provider = getSearchIndexProvider(clazz); 809df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (provider != null) { 810df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context); 811df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) { 812df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio nonIndexableKeys.addAll(providerNonIndexableKeys); 813df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 8149a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio 8159a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio indexFromProvider(mContext, database, localeStr, provider, sir.className, 8169a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio sir.iconResId, sir.rank, sir.enabled, nonIndexableKeys); 817df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 818df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 819df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } 820df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 8219a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio private Indexable.SearchIndexProvider getSearchIndexProvider(final Class<?> clazz) { 822df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio try { 8239a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER); 8249a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio return (Indexable.SearchIndexProvider) f.get(null); 825df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } catch (NoSuchFieldException e) { 8269a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); 8279a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } catch (SecurityException se) { 8289a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, 8299a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio "Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); 830df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio } catch (IllegalAccessException e) { 8319a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, 8329a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio "Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); 8339a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio } catch (IllegalArgumentException e) { 8349a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio Log.d(LOG_TAG, 8359a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio "Illegal argument when accessing field '" + 8369a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); 83751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 838df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio return null; 8396f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 8406f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 84151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void indexFromResource(Context context, SQLiteDatabase database, String localeStr, 84245f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio int xmlResId, String fragmentName, int iconResId, int rank, 84345f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio String intentAction, String intentTargetPackage, String intentTargetClass, 844df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio List<String> nonIndexableKeys) { 845b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 84651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio XmlResourceParser parser = null; 84751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio try { 84851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio parser = context.getResources().getXml(xmlResId); 84951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 85051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio int type; 85151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 85251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio && type != XmlPullParser.START_TAG) { 85351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio // Parse next until start tag is found 85451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 85551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 85651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio String nodeName = parser.getName(); 8579593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio if (!NODE_NAME_PREFERENCE_SCREEN.equals(nodeName)) { 85851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio throw new RuntimeException( 85951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio "XML document must start with <PreferenceScreen> tag; found" 86051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio + nodeName + " at " + parser.getPositionDescription()); 86151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 86251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 86351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final int outerDepth = parser.getDepth(); 86451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final AttributeSet attrs = Xml.asAttributeSet(parser); 86545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 86651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final String screenTitle = getDataTitle(context, attrs); 86751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 868c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio String key = getDataKey(context, attrs); 86951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 87045f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio String title; 87145f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio String summary; 87245f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio String keywords; 87345f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 87451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio // Insert rows for the main PreferenceScreen node. Rewrite the data for removing 87551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio // hyphens. 876df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (!nonIndexableKeys.contains(key)) { 87745f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio title = getDataTitle(context, attrs); 87845f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio summary = getDataSummary(context, attrs); 87945f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio keywords = getDataKeywords(context, attrs); 88045f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 88145f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio updateOneRowWithFilteredData(database, localeStr, title, summary, null, null, 88245f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio fragmentName, screenTitle, iconResId, rank, 883d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio keywords, intentAction, intentTargetPackage, intentTargetClass, true, 884d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio key, -1 /* default user id */); 88545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio } 88651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 88751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 88851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 88951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 89051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio continue; 89151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 89251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 8939593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio nodeName = parser.getName(); 8949593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 89545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio key = getDataKey(context, attrs); 896df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (nonIndexableKeys.contains(key)) { 89745f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio continue; 89845f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio } 89945f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 90051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio title = getDataTitle(context, attrs); 90151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio keywords = getDataKeywords(context, attrs); 90251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 9039593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) { 9049593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio summary = getDataSummary(context, attrs); 9059593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 906a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio String entries = null; 907dd41dfc483e830bdb33df858dec99e2c4c806bfcFabrice Di Meglio 908a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) { 909a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio entries = getDataEntries(context, attrs); 910a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 911a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio 9129593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio // Insert rows for the child nodes of PreferenceScreen 913a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries, 9147d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio fragmentName, screenTitle, iconResId, rank, 915c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio keywords, intentAction, intentTargetPackage, intentTargetClass, 916d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio true, key, -1 /* default user id */); 917c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio } else { 918b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio String summaryOn = getDataSummaryOn(context, attrs); 919b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio String summaryOff = getDataSummaryOff(context, attrs); 920b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio 921b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) { 922b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio summaryOn = getDataSummary(context, attrs); 923b7390ba5854c0f583858e085bff89eebe307eb39Fabrice Di Meglio } 9249593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 9259593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff, 9267d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio null, fragmentName, screenTitle, iconResId, rank, 927c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio keywords, intentAction, intentTargetPackage, intentTargetClass, 928d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio true, key, -1 /* default user id */); 9299593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio } 93051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 93151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 93251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } catch (XmlPullParserException e) { 93351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio throw new RuntimeException("Error parsing PreferenceScreen", e); 93451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } catch (IOException e) { 93551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio throw new RuntimeException("Error parsing PreferenceScreen", e); 93651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } finally { 93751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (parser != null) parser.close(); 938b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 93951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 940b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 9419a60d7b5697873a41810fe87a89e60824e3548daFabrice Di Meglio private void indexFromProvider(Context context, SQLiteDatabase database, String localeStr, 942df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio Indexable.SearchIndexProvider provider, String className, int iconResId, int rank, 943df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio boolean enabled, List<String> nonIndexableKeys) { 94445f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 945a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (provider == null) { 94645f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio Log.w(LOG_TAG, "Cannot find provider: " + className); 947a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio return; 948a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 949a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 95045f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(context, enabled); 95145f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 952a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (rawList != null) { 953a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio final int rawSize = rawList.size(); 954a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio for (int i = 0; i < rawSize; i++) { 955a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio SearchIndexableRaw raw = rawList.get(i); 956a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 957a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio // Should be the same locale as the one we are processing 958a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { 959a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio continue; 960a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 961a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 962df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio if (nonIndexableKeys.contains(raw.key)) { 96345f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio continue; 96445f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio } 96545f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio 966a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio updateOneRowWithFilteredData(database, localeStr, 967a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.title, 968a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.summaryOn, 969a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.summaryOff, 970a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.entries, 97145f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio className, 972a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.screenTitle, 97345f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio iconResId, 97445f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio rank, 975a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.keywords, 976a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.intentAction, 977a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.intentTargetPackage, 978a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.intentTargetClass, 979a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio raw.enabled, 980d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio raw.key, 981d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio raw.userId); 982a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 983a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 984a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 985a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio final List<SearchIndexableResource> resList = 98645f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio provider.getXmlResourcesToIndex(context, enabled); 987a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (resList != null) { 988a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio final int resSize = resList.size(); 989a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio for (int i = 0; i < resSize; i++) { 990a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio SearchIndexableResource item = resList.get(i); 991a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 992a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio // Should be the same locale as the one we are processing 993a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio if (!item.locale.toString().equalsIgnoreCase(localeStr)) { 994a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio continue; 995a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 996a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio 997caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav final int itemIconResId = (item.iconResId == 0) ? iconResId : item.iconResId; 998caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav final int itemRank = (item.rank == 0) ? rank : item.rank; 999caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav String itemClassName = (TextUtils.isEmpty(item.className)) 1000caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav ? className : item.className; 1001caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav 100245f754e50618076213ed6911ff1e6c37b4db0467Fabrice Di Meglio indexFromResource(context, database, localeStr, 1003caa0b54cbcb71b1124ea50cb0cf5abb6a4d1275fSvetoslav item.xmlResId, itemClassName, itemIconResId, itemRank, 1004a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio item.intentAction, item.intentTargetPackage, 1005df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio item.intentTargetClass, nonIndexableKeys); 1006a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 1007a9d37050cb427cca92587341f399606edfc8ef8dFabrice Di Meglio } 100851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 100951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 101051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale, 1011dd41dfc483e830bdb33df858dec99e2c4c806bfcFabrice Di Meglio String title, String summaryOn, String summaryOff, String entries, 10127d39310c8d159190cfcc63aa6647714c056d76f6Fabrice Di Meglio String className, 1013a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio String screenTitle, int iconResId, int rank, String keywords, 101451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio String intentAction, String intentTargetPackage, String intentTargetClass, 1015d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio boolean enabled, String key, int userId) { 101651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 1017363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String updatedTitle = normalizeHyphen(title); 1018363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String updatedSummaryOn = normalizeHyphen(summaryOn); 1019363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String updatedSummaryOff = normalizeHyphen(summaryOff); 102051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 1021363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String normalizedTitle = normalizeString(updatedTitle); 1022363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String normalizedSummaryOn = normalizeString(updatedSummaryOn); 1023363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String normalizedSummaryOff = normalizeString(updatedSummaryOff); 102451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 102535c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette final String spaceDelimitedKeywords = normalizeKeywords(keywords); 102635c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette 102751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio updateOneRow(database, locale, 10289593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn, 102935c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId, 103035c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette rank, spaceDelimitedKeywords, intentAction, intentTargetPackage, intentTargetClass, 103135c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette enabled, key, userId); 103251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 103351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 1034a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio private static String normalizeHyphen(String input) { 1035a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY; 1036a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio } 1037a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio 1038a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio private static String normalizeString(String input) { 1039363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String nohyphen = (input != null) ? input.replaceAll(HYPHEN, EMPTY) : EMPTY; 1040363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio final String normalized = Normalizer.normalize(nohyphen, Normalizer.Form.NFD); 1041363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio 1042363348dd8bd1e58d8b7faa8a9405589e41d28e48Fabrice Di Meglio return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase(); 1043a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio } 1044a8ac78b3925a0b463c2df37a7c83d8f15222a601Fabrice Di Meglio 104535c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette private static String normalizeKeywords(String input) { 104635c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY; 104735c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette } 104835c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette 104935c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette private void updateOneRow(SQLiteDatabase database, String locale, String updatedTitle, 105035c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette String normalizedTitle, String updatedSummaryOn, String normalizedSummaryOn, 105135c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette String updatedSummaryOff, String normalizedSummaryOff, String entries, String className, 105235c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette String screenTitle, int iconResId, int rank, String spaceDelimitedKeywords, 105351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio String intentAction, String intentTargetPackage, String intentTargetClass, 1054d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio boolean enabled, String key, int userId) { 105551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 105651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (TextUtils.isEmpty(updatedTitle)) { 105751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return; 105851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 105951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 106014be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio // The DocID should contains more than the title string itself (you may have two settings 106114be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio // with the same title). So we need to use a combination of the title and the screenTitle. 106214be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio StringBuilder sb = new StringBuilder(updatedTitle); 106314be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio sb.append(screenTitle); 106414be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio int docId = sb.toString().hashCode(); 106514be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio 106651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio ContentValues values = new ContentValues(); 106714be7d23a2ee023796126453bba55f4bc84ba065Fabrice Di Meglio values.put(IndexColumns.DOCID, docId); 106851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.LOCALE, locale); 106951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.DATA_RANK, rank); 107051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.DATA_TITLE, updatedTitle); 107151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle); 10729593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio values.put(IndexColumns.DATA_SUMMARY_ON, updatedSummaryOn); 10739593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio values.put(IndexColumns.DATA_SUMMARY_ON_NORMALIZED, normalizedSummaryOn); 10749593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio values.put(IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff); 10759593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio values.put(IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, normalizedSummaryOff); 1076a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio values.put(IndexColumns.DATA_ENTRIES, entries); 107735c3454808a8c9e5ca7826644470798dedda5b26Alan Viverette values.put(IndexColumns.DATA_KEYWORDS, spaceDelimitedKeywords); 107851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.CLASS_NAME, className); 107951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.SCREEN_TITLE, screenTitle); 108051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.INTENT_ACTION, intentAction); 108151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage); 108251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.INTENT_TARGET_CLASS, intentTargetClass); 108351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.ICON, iconResId); 108451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio values.put(IndexColumns.ENABLED, enabled); 1085c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio values.put(IndexColumns.DATA_KEY_REF, key); 1086d17a15bbc473a7262755ff136b15a3587f4c7ddbFabrice Di Meglio values.put(IndexColumns.USER_ID, userId); 108751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 108851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio database.replaceOrThrow(Tables.TABLE_PREFS_INDEX, null, values); 108951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 109051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 1091c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio private String getDataKey(Context context, AttributeSet attrs) { 1092c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio return getData(context, attrs, 1093c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio com.android.internal.R.styleable.Preference, 1094c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio com.android.internal.R.styleable.Preference_key); 1095c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio } 1096c1457323d271309d5d1955743cd806417c84b9d6Fabrice Di Meglio 109751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private String getDataTitle(Context context, AttributeSet attrs) { 109851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return getData(context, attrs, 109951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio com.android.internal.R.styleable.Preference, 110051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio com.android.internal.R.styleable.Preference_title); 110151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 110251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 110351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private String getDataSummary(Context context, AttributeSet attrs) { 110451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return getData(context, attrs, 110551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio com.android.internal.R.styleable.Preference, 110651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio com.android.internal.R.styleable.Preference_summary); 110751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 110851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 11099593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio private String getDataSummaryOn(Context context, AttributeSet attrs) { 11109593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio return getData(context, attrs, 11119593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio com.android.internal.R.styleable.CheckBoxPreference, 11129593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio com.android.internal.R.styleable.CheckBoxPreference_summaryOn); 11139593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio } 11149593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 11159593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio private String getDataSummaryOff(Context context, AttributeSet attrs) { 11169593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio return getData(context, attrs, 11179593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio com.android.internal.R.styleable.CheckBoxPreference, 11189593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio com.android.internal.R.styleable.CheckBoxPreference_summaryOff); 11199593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio } 11209593782d154f378a0c911cd015d410c18fe74a92Fabrice Di Meglio 1121a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio private String getDataEntries(Context context, AttributeSet attrs) { 1122a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio return getDataEntries(context, attrs, 1123a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio com.android.internal.R.styleable.ListPreference, 1124a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio com.android.internal.R.styleable.ListPreference_entries); 1125a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1126a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio 112751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private String getDataKeywords(Context context, AttributeSet attrs) { 112851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords); 112951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 113051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 113151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private String getData(Context context, AttributeSet set, int[] attrs, int resId) { 113251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final TypedArray sa = context.obtainStyledAttributes(set, attrs); 113351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final TypedValue tv = sa.peekValue(resId); 113451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 113551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio CharSequence data = null; 113651bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (tv != null && tv.type == TypedValue.TYPE_STRING) { 113751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio if (tv.resourceId != 0) { 113851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio data = context.getText(tv.resourceId); 113951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } else { 114051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio data = tv.string; 114151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 1142b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 114351bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return (data != null) ? data.toString() : null; 1144b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1145b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 1146a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio private String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) { 1147a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio final TypedArray sa = context.obtainStyledAttributes(set, attrs); 1148a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio final TypedValue tv = sa.peekValue(resId); 1149a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio 1150a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio String[] data = null; 1151a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) { 1152a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio if (tv.resourceId != 0) { 1153a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio data = context.getResources().getStringArray(tv.resourceId); 1154a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1155a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1156a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio final int count = (data == null ) ? 0 : data.length; 1157a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio if (count == 0) { 1158a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio return null; 1159a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1160a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio final StringBuilder result = new StringBuilder(); 1161a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio for (int n = 0; n < count; n++) { 1162a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio result.append(data[n]); 11638f5c65fd010d249770fda81c1129c1d7555a3299Fabrice Di Meglio result.append(ENTRIES_SEPARATOR); 1164a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1165a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio return result.toString(); 1166a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio } 1167a41707200b6628376e8fb575e782d8228c0d32a2Fabrice Di Meglio 1168b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio /** 11696f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio * A private class for updating the Index database 11706f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio */ 117172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio private class UpdateIndexTask extends AsyncTask<UpdateData, Integer, Void> { 11726f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 11736f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio @Override 11746f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio protected void onPreExecute() { 11756f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio super.onPreExecute(); 11766f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio mIsAvailable.set(false); 11776f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 11786f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 11796f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio @Override 118072e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio protected void onPostExecute(Void aVoid) { 118172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio super.onPostExecute(aVoid); 11826f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio mIsAvailable.set(true); 11836f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 11846f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 11856f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio @Override 118672e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio protected Void doInBackground(UpdateData... params) { 1187ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk try { 1188ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final List<SearchIndexableData> dataToUpdate = params[0].dataToUpdate; 1189ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final List<SearchIndexableData> dataToDelete = params[0].dataToDelete; 1190ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final Map<String, List<String>> nonIndexableKeys = params[0].nonIndexableKeys; 1191df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 1192ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final boolean forceUpdate = params[0].forceUpdate; 1193ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final boolean fullIndex = params[0].fullIndex; 1194df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio 1195ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final SQLiteDatabase database = getWritableDatabase(); 1196ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk if (database == null) { 1197ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk Log.e(LOG_TAG, "Cannot update Index as I cannot get a writable database"); 1198ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk return null; 1199ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk } 1200ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk final String localeStr = Locale.getDefault().toString(); 1201b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 1202ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk try { 1203ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk database.beginTransaction(); 1204ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk if (dataToDelete.size() > 0) { 1205ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk processDataToDelete(database, localeStr, dataToDelete); 1206ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk } 1207ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk if (dataToUpdate.size() > 0) { 1208ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk processDataToUpdate(database, localeStr, dataToUpdate, nonIndexableKeys, 1209ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk forceUpdate); 1210ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk } 1211ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk database.setTransactionSuccessful(); 1212ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk } finally { 1213ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk database.endTransaction(); 1214490099b1352f9a4dd5c3f2becf3707d5c0d78452Fabrice Di Meglio } 1215ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk if (fullIndex) { 1216ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk IndexDatabaseHelper.setLocaleIndexed(mContext, localeStr); 1217b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1218ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk } catch (SQLiteFullException e) { 1219ef71f605f3290be8c5d2158ead21ae6f9ead2d86Jason Monk Log.e(LOG_TAG, "Unable to index search, out of space", e); 12206c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk } 122172e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio 122272e07cf21c33c453bd3a3bd8756f52908432ee0dFabrice Di Meglio return null; 1223b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1224b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 122551bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private boolean processDataToUpdate(SQLiteDatabase database, String localeStr, 1226df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio List<SearchIndexableData> dataToUpdate, Map<String, List<String>> nonIndexableKeys, 1227df278aa959b5e0a5d2b5d9152b7013d22757cd17Fabrice Di Meglio boolean forceUpdate) { 122851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio 122918fbdd023bfbd9ea7747894c2d9464f66075b703Jason Monk if (!forceUpdate && IndexDatabaseHelper.isLocaleAlreadyIndexed(mContext, localeStr)) { 123051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed"); 123151bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return true; 123251bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio } 1233b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 1234b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio boolean result = false; 1235b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio final long current = System.currentTimeMillis(); 1236b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 123751bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final int count = dataToUpdate.size(); 1238b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio for (int n = 0; n < count; n++) { 123951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final SearchIndexableData data = dataToUpdate.get(n); 1240dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio try { 1241dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio indexOneSearchIndexableData(database, localeStr, data, nonIndexableKeys); 1242dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio } catch (Exception e) { 12436c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data) 12446c9e884aa04b19634722d95cb65d7df1050a0c28Jason Monk + " for locale: " + localeStr, e); 1245dba577f8f017baac0086c185579340db1c9281d9Fabrice Di Meglio } 1246b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1247b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 1248b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio final long now = System.currentTimeMillis(); 124951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " + 1250b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio (now - current) + " millis"); 1251b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio return result; 1252b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1253b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 125451bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio private boolean processDataToDelete(SQLiteDatabase database, String localeStr, 1255724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio List<SearchIndexableData> dataToDelete) { 1256b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 1257b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio boolean result = false; 1258b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio final long current = System.currentTimeMillis(); 1259b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 126051bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio final int count = dataToDelete.size(); 1261b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio for (int n = 0; n < count; n++) { 1262724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio final SearchIndexableData data = dataToDelete.get(n); 1263724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio if (data == null) { 1264724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio continue; 1265724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio } 1266724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio if (!TextUtils.isEmpty(data.className)) { 1267724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio delete(database, IndexColumns.CLASS_NAME, data.className); 1268724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio } else { 1269724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio if (data instanceof SearchIndexableRaw) { 1270724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio final SearchIndexableRaw raw = (SearchIndexableRaw) data; 1271724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio if (!TextUtils.isEmpty(raw.title)) { 1272724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio delete(database, IndexColumns.DATA_TITLE, raw.title); 1273724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio } 1274724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio } 1275724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio } 1276b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio } 1277b8dfbf140986a9c0781f268ea40914063f026436Fabrice Di Meglio 12786f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio final long now = System.currentTimeMillis(); 127951bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio Log.d(LOG_TAG, "Deleting data for locale '" + localeStr + "' took " + 12806f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio (now - current) + " millis"); 12816f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio return result; 12826f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 12836f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio 1284724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio private int delete(SQLiteDatabase database, String columName, String value) { 1285724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio final String whereClause = columName + "=?"; 1286724b702a8627c933cef536e40d2db5918bf45ccbFabrice Di Meglio final String[] whereArgs = new String[] { value }; 1287fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio 128851bfee595c3ce587e2e26565fd9e8f4ae02c3482Fabrice Di Meglio return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs); 1289fa7dc240e978b1b77bb5c80a78cd1f8c77648301Fabrice Di Meglio } 12906f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio } 1291d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1292d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio /** 1293b86a2bc745c1fbbdf23e470e946b7e57f7e090a9Fabrice Di Meglio * A basic AsyncTask for saving a Search query into the database 1294d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio */ 1295d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio private class SaveSearchQueryTask extends AsyncTask<String, Void, Long> { 1296d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1297d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio @Override 1298d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio protected Long doInBackground(String... params) { 1299d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final long now = new Date().getTime(); 1300d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1301d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final ContentValues values = new ContentValues(); 1302d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio values.put(IndexDatabaseHelper.SavedQueriesColums.QUERY, params[0]); 1303d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio values.put(IndexDatabaseHelper.SavedQueriesColums.TIME_STAMP, now); 1304d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1305d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final SQLiteDatabase database = getWritableDatabase(); 1306dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio if (database == null) { 1307dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio Log.e(LOG_TAG, "Cannot save Search queries as I cannot get a writable database"); 1308dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio return -1L; 1309dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio } 1310d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1311dff3faaf30bd6d695e4d9f632af53dbc73cf6506Fabrice Di Meglio long lastInsertedRowId = -1L; 1312d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio try { 1313b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio // First, delete all saved queries that are the same 1314b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio database.delete(Tables.TABLE_SAVED_QUERIES, 1315b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio IndexDatabaseHelper.SavedQueriesColums.QUERY + " = ?", 1316b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio new String[] { params[0] }); 1317b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio 1318b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio // Second, insert the saved query 1319d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio lastInsertedRowId = 1320b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio database.insertOrThrow(Tables.TABLE_SAVED_QUERIES, null, values); 1321d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1322b58b28e13e2771cbe5dc102488cdd86dea14e5b2Fabrice Di Meglio // Last, remove "old" saved queries 1323d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY; 1324d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio if (delta > 0) { 1325d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio int count = database.delete(Tables.TABLE_SAVED_QUERIES, "rowId <= ?", 1326d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio new String[] { Long.toString(delta) }); 1327d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)"); 1328d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 1329d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } catch (Exception e) { 1330d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio Log.d(LOG_TAG, "Cannot update saved Search queries", e); 1331d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 1332d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio 1333d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio return lastInsertedRowId; 1334d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 1335d297a5840230b769a3c7ad8b85232968a7077f64Fabrice Di Meglio } 13366f0739a3d9a9eca1591ae6bada1dd4d1d92c0defFabrice Di Meglio} 1337