Loading src/com/android/settings/search/DatabaseIndexingManager.java +81 −10 Original line number Diff line number Diff line Loading @@ -23,7 +23,24 @@ import static com.android.settings.search.DatabaseResultLoader import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; import android.content.ContentValues; Loading @@ -38,10 +55,12 @@ import android.os.Build; import android.provider.SearchIndexableResource; import android.provider.SearchIndexablesContract; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.Log; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.indexing.IndexData; import com.android.settings.search.indexing.IndexDataConverter; import com.android.settings.search.indexing.PreIndexData; import com.android.settings.search.indexing.PreIndexDataCollector; Loading @@ -49,6 +68,7 @@ import com.android.settings.search.indexing.PreIndexDataCollector; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; Loading @@ -72,6 +92,7 @@ public class DatabaseIndexingManager { final AtomicBoolean mIsIndexingComplete = new AtomicBoolean(false); private PreIndexDataCollector mCollector; private IndexDataConverter mConverter; private Context mContext; Loading Loading @@ -182,8 +203,8 @@ public class DatabaseIndexingManager { * @param localeStr the default locale for the device. */ @VisibleForTesting void updateDatabase(PreIndexData indexData, boolean needsReindexing, String localeStr) { final Map<String, Set<String>> nonIndexableKeys = indexData.nonIndexableKeys; void updateDatabase(PreIndexData preIndexData, boolean needsReindexing, String localeStr) { final Map<String, Set<String>> nonIndexableKeys = preIndexData.nonIndexableKeys; final SQLiteDatabase database = getWritableDatabase(); if (database == null) { Loading @@ -194,8 +215,9 @@ public class DatabaseIndexingManager { try { database.beginTransaction(); // Add new data from Providers at initial index time, or inserted later. addIndaxebleDataToDatabase(database, localeStr, indexData); // Convert all Pre-index data to Index data. List<IndexData> indexData = getIndexData(localeStr, preIndexData); insertIndexData(database, indexData); // Only check for non-indexable key updates after initial index. // Enabled state with non-indexable keys is checked when items are first inserted. Loading @@ -209,14 +231,64 @@ public class DatabaseIndexingManager { } } @VisibleForTesting List<IndexData> getIndexData(String locale, PreIndexData data) { if (mConverter == null) { mConverter = new IndexDataConverter(mContext); } return mConverter.convertPreIndexDataToIndexData(data, locale); } /** * Inserts all of the entries in {@param indexData} into the {@param database} * as Search Data and as part of the Information Hierarchy. */ @VisibleForTesting void addIndaxebleDataToDatabase(SQLiteDatabase database, String locale, PreIndexData data) { if (data.dataToUpdate.size() == 0) { return; void insertIndexData(SQLiteDatabase database, List<IndexData> indexData) { ContentValues values; for (IndexData dataRow : indexData) { values = new ContentValues(); values.put(IndexDatabaseHelper.IndexColumns.DOCID, dataRow.getDocId()); values.put(LOCALE, dataRow.locale); values.put(DATA_TITLE, dataRow.updatedTitle); values.put(DATA_TITLE_NORMALIZED, dataRow.normalizedTitle); values.put(DATA_SUMMARY_ON, dataRow.updatedSummaryOn); values.put(DATA_SUMMARY_ON_NORMALIZED, dataRow.normalizedSummaryOn); values.put(DATA_ENTRIES, dataRow.entries); values.put(DATA_KEYWORDS, dataRow.spaceDelimitedKeywords); values.put(CLASS_NAME, dataRow.className); values.put(SCREEN_TITLE, dataRow.screenTitle); values.put(INTENT_ACTION, dataRow.intentAction); values.put(INTENT_TARGET_PACKAGE, dataRow.intentTargetPackage); values.put(INTENT_TARGET_CLASS, dataRow.intentTargetClass); values.put(ICON, dataRow.iconResId); values.put(ENABLED, dataRow.enabled); values.put(DATA_KEY_REF, dataRow.key); values.put(USER_ID, dataRow.userId); values.put(PAYLOAD_TYPE, dataRow.payloadType); values.put(PAYLOAD, dataRow.payload); database.replaceOrThrow(TABLE_PREFS_INDEX, null, values); if (!TextUtils.isEmpty(dataRow.className) && !TextUtils.isEmpty(dataRow.childClassName)) { ContentValues siteMapPair = new ContentValues(); final int pairDocId = Objects.hash(dataRow.className, dataRow.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, dataRow.className); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, dataRow.screenTitle); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, dataRow.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, dataRow.updatedTitle); database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null /* nullColumnHack */, siteMapPair); } } IndexDataConverter manager = new IndexDataConverter(mContext, database); manager.addDataToDatabase(locale, data.dataToUpdate, data.nonIndexableKeys); } /** Loading Loading @@ -288,7 +360,6 @@ public class DatabaseIndexingManager { disabledResults.close(); } /** * TODO (b/64951285): Deprecate this method * Loading src/com/android/settings/search/indexing/IndexDataConverter.java +47 −100 Original line number Diff line number Diff line Loading @@ -17,10 +17,8 @@ package com.android.settings.search.indexing; import android.content.ContentValues; import android.content.Context; import android.content.res.XmlResourceParser; import android.database.sqlite.SQLiteDatabase; import android.provider.SearchIndexableData; import android.provider.SearchIndexableResource; import android.support.annotation.DrawableRes; Loading @@ -32,7 +30,6 @@ import android.util.Xml; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.search.IndexDatabaseHelper; import com.android.settings.search.Indexable; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; Loading @@ -44,33 +41,10 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_RANK; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; /** * Helper class to convert {@link PreIndexData} to {@link IndexData}. * Loading @@ -86,56 +60,65 @@ public class IndexDataConverter { private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference"; private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference"; private Context mContext; private final Context mContext; private String mLocale; private SQLiteDatabase mDb; private List<IndexData> mIndexData; public IndexDataConverter(Context context, SQLiteDatabase database) { public IndexDataConverter(Context context) { mContext = context; mDb = database; mLocale = Locale.getDefault().toString(); } public List<IndexData> convertPreIndexDataToIndexData(PreIndexData preIndexData, String locale) { mLocale = locale; mIndexData = new ArrayList<>(); List<SearchIndexableData> dataToUpdate = preIndexData.dataToUpdate; Map<String, Set<String>> nonIndexableKeys = preIndexData.nonIndexableKeys; parsePreIndexData(dataToUpdate, nonIndexableKeys); return mIndexData; } /** * Inserts {@link SearchIndexableData} into the database. * * @param localeStr is the locale of the data to be inserted. * @param dataToUpdate is a {@link List} of the data to be inserted. * @param nonIndexableKeys is a {@link Map} from Package Name to a {@link Set} of keys which * identify search results which should not be surfaced. */ public void addDataToDatabase(String localeStr, List<SearchIndexableData> dataToUpdate, private void parsePreIndexData(List<SearchIndexableData> dataToUpdate, Map<String, Set<String>> nonIndexableKeys) { final long current = System.currentTimeMillis(); for (SearchIndexableData data : dataToUpdate) { try { indexOneSearchIndexableData(localeStr, data, nonIndexableKeys); addOneIndexData(data, nonIndexableKeys); } catch (Exception e) { Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data) + " for locale: " + localeStr, e); + " for locale: " + mLocale, e); } } final long now = System.currentTimeMillis(); Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " + Log.d(LOG_TAG, "Indexing locale '" + mLocale + "' took " + (now - current) + " millis"); } @VisibleForTesting void indexOneSearchIndexableData(String localeStr, SearchIndexableData data, private void addOneIndexData(SearchIndexableData data, Map<String, Set<String>> nonIndexableKeys) { if (data instanceof SearchIndexableResource) { indexOneResource(localeStr, (SearchIndexableResource) data, nonIndexableKeys); addOneResource((SearchIndexableResource) data, nonIndexableKeys); } else if (data instanceof SearchIndexableRaw) { indexOneRaw(localeStr, (SearchIndexableRaw) data, nonIndexableKeys); addOneRaw((SearchIndexableRaw) data, nonIndexableKeys); } } @VisibleForTesting void indexOneRaw(String localeStr, SearchIndexableRaw raw, Map<String, private void addOneRaw(SearchIndexableRaw raw, Map<String, Set<String>> nonIndexableKeysFromResource) { // Should be the same locale as the one we are processing if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { if (!raw.locale.toString().equalsIgnoreCase(mLocale)) { return; } Loading @@ -149,7 +132,7 @@ public class IndexDataConverter { IndexData.Builder builder = new IndexData.Builder(); builder.setTitle(raw.title) .setSummaryOn(raw.summaryOn) .setLocale(localeStr) .setLocale(mLocale) .setEntries(raw.entries) .setKeywords(raw.keywords) .setClassName(raw.className) Loading @@ -162,11 +145,10 @@ public class IndexDataConverter { .setKey(raw.key) .setUserId(raw.userId); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } @VisibleForTesting void indexOneResource(String localeStr, SearchIndexableResource sir, private void addOneResource(SearchIndexableResource sir, Map<String, Set<String>> nonIndexableKeysFromResource) { if (sir == null) { Loading @@ -182,7 +164,7 @@ public class IndexDataConverter { nonIndexableKeys.addAll(resNonIndexableKeys); } indexFromResource(localeStr, sir, nonIndexableKeys); addIndexDataFromResource(sir, nonIndexableKeys); } else { if (TextUtils.isEmpty(sir.className)) { Log.w(LOG_TAG, "Cannot index an empty Search Provider name!"); Loading @@ -202,17 +184,16 @@ public class IndexDataConverter { DatabaseIndexingUtils.getSearchIndexProvider(clazz); if (provider != null) { List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context); if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) { if (providerNonIndexableKeys != null) { nonIndexableKeys.addAll(providerNonIndexableKeys); } indexFromProvider(localeStr, provider, sir, nonIndexableKeys); addIndexDataFromProvider(provider, sir, nonIndexableKeys); } } } @VisibleForTesting void indexFromResource(String localeStr, SearchIndexableResource sir, private void addIndexDataFromResource(SearchIndexableResource sir, List<String> nonIndexableKeys) { final Context context = sir.context; XmlResourceParser parser = null; Loading Loading @@ -274,7 +255,7 @@ public class IndexDataConverter { headerBuilder.setTitle(headerTitle) .setSummaryOn(headerSummary) .setKeywords(headerKeywords) .setLocale(localeStr) .setLocale(mLocale) .setClassName(fragmentName) .setScreenTitle(screenTitle) .setIntentAction(intentAction) Loading Loading @@ -308,7 +289,7 @@ public class IndexDataConverter { builder = new IndexData.Builder(); builder.setTitle(title) .setLocale(localeStr) .setLocale(mLocale) .setKeywords(keywords) .setClassName(fragmentName) .setScreenTitle(screenTitle) Loading Loading @@ -339,7 +320,7 @@ public class IndexDataConverter { .setPayload(payload); // Insert rows for the child nodes of PreferenceScreen updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } else { // TODO (b/33577327) We removed summary off here. We should check if we can // merge this 'else' section with the one above. Put a break point to Loading @@ -353,13 +334,13 @@ public class IndexDataConverter { builder.setSummaryOn(summaryOn); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } } // The xml header's title does not match the title of one of the child settings. if (isHeaderUnique) { updateOneRow(headerBuilder.build(mContext)); addRowToData(headerBuilder.build(mContext)); } } catch (XmlPullParserException e) { throw new RuntimeException("Error parsing PreferenceScreen", e); Loading @@ -370,8 +351,7 @@ public class IndexDataConverter { } } @VisibleForTesting void indexFromProvider(String localeStr, Indexable.SearchIndexProvider provider, private void addIndexDataFromProvider(Indexable.SearchIndexProvider provider, SearchIndexableResource sir, List<String> nonIndexableKeys) { final String className = sir.className; Loading @@ -393,7 +373,7 @@ public class IndexDataConverter { SearchIndexableRaw raw = rawList.get(i); // Should be the same locale as the one we are processing if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { if (!raw.locale.toString().equalsIgnoreCase(mLocale)) { continue; } boolean enabled = !nonIndexableKeys.contains(raw.key); Loading @@ -401,7 +381,7 @@ public class IndexDataConverter { IndexData.Builder builder = new IndexData.Builder(); builder.setTitle(raw.title) .setSummaryOn(raw.summaryOn) .setLocale(localeStr) .setLocale(mLocale) .setEntries(raw.entries) .setKeywords(raw.keywords) .setClassName(className) Loading @@ -414,7 +394,7 @@ public class IndexDataConverter { .setKey(raw.key) .setUserId(raw.userId); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } } Loading @@ -426,7 +406,7 @@ public class IndexDataConverter { SearchIndexableResource item = resList.get(i); // Should be the same locale as the one we are processing if (!item.locale.toString().equalsIgnoreCase(localeStr)) { if (!item.locale.toString().equalsIgnoreCase(mLocale)) { continue; } Loading @@ -440,49 +420,16 @@ public class IndexDataConverter { ? intentTargetPackage : item.intentTargetPackage; indexFromResource(localeStr, item, nonIndexableKeys); addIndexDataFromResource(item, nonIndexableKeys); } } } private void updateOneRow(IndexData row) { private void addRowToData(IndexData row) { if (TextUtils.isEmpty(row.updatedTitle)) { return; } ContentValues values = new ContentValues(); values.put(IndexDatabaseHelper.IndexColumns.DOCID, row.getDocId()); values.put(LOCALE, row.locale); values.put(DATA_TITLE, row.updatedTitle); values.put(DATA_TITLE_NORMALIZED, row.normalizedTitle); values.put(DATA_SUMMARY_ON, row.updatedSummaryOn); values.put(DATA_SUMMARY_ON_NORMALIZED, row.normalizedSummaryOn); values.put(DATA_ENTRIES, row.entries); values.put(DATA_KEYWORDS, row.spaceDelimitedKeywords); values.put(CLASS_NAME, row.className); values.put(SCREEN_TITLE, row.screenTitle); values.put(INTENT_ACTION, row.intentAction); values.put(INTENT_TARGET_PACKAGE, row.intentTargetPackage); values.put(INTENT_TARGET_CLASS, row.intentTargetClass); values.put(ICON, row.iconResId); values.put(ENABLED, row.enabled); values.put(DATA_KEY_REF, row.key); values.put(USER_ID, row.userId); values.put(PAYLOAD_TYPE, row.payloadType); values.put(PAYLOAD, row.payload); mDb.replaceOrThrow(TABLE_PREFS_INDEX, null, values); if (!TextUtils.isEmpty(row.className) && !TextUtils.isEmpty(row.childClassName)) { ContentValues siteMapPair = new ContentValues(); final int pairDocId = Objects.hash(row.className, row.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, row.className); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, row.screenTitle); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, row.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, row.updatedTitle); mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null, siteMapPair); } mIndexData.add(row); } } tests/robotests/assets/grandfather_not_in_search_index_provider_registry +1 −0 Original line number Diff line number Diff line com.android.settings.development.DevelopmentSettingsDashboardFragment com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard com.android.settings.search.indexing.FakeSettingsFragment tests/robotests/res/xml-mcc999/about_legal.xml 0 → 100644 +34 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- WARNING: This resource file is used to test Settings Search indexing. If you change something in here, please run the settings robotests and make sure they still pass. --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" android:title="bears_bears_bears" settings:keywords="keywords"> <Preference android:key="pref_key_1" android:title="bears_bears_bears"/> </PreferenceScreen> No newline at end of file Loading
src/com/android/settings/search/DatabaseIndexingManager.java +81 −10 Original line number Diff line number Diff line Loading @@ -23,7 +23,24 @@ import static com.android.settings.search.DatabaseResultLoader import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; import android.content.ContentValues; Loading @@ -38,10 +55,12 @@ import android.os.Build; import android.provider.SearchIndexableResource; import android.provider.SearchIndexablesContract; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.Log; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.indexing.IndexData; import com.android.settings.search.indexing.IndexDataConverter; import com.android.settings.search.indexing.PreIndexData; import com.android.settings.search.indexing.PreIndexDataCollector; Loading @@ -49,6 +68,7 @@ import com.android.settings.search.indexing.PreIndexDataCollector; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; Loading @@ -72,6 +92,7 @@ public class DatabaseIndexingManager { final AtomicBoolean mIsIndexingComplete = new AtomicBoolean(false); private PreIndexDataCollector mCollector; private IndexDataConverter mConverter; private Context mContext; Loading Loading @@ -182,8 +203,8 @@ public class DatabaseIndexingManager { * @param localeStr the default locale for the device. */ @VisibleForTesting void updateDatabase(PreIndexData indexData, boolean needsReindexing, String localeStr) { final Map<String, Set<String>> nonIndexableKeys = indexData.nonIndexableKeys; void updateDatabase(PreIndexData preIndexData, boolean needsReindexing, String localeStr) { final Map<String, Set<String>> nonIndexableKeys = preIndexData.nonIndexableKeys; final SQLiteDatabase database = getWritableDatabase(); if (database == null) { Loading @@ -194,8 +215,9 @@ public class DatabaseIndexingManager { try { database.beginTransaction(); // Add new data from Providers at initial index time, or inserted later. addIndaxebleDataToDatabase(database, localeStr, indexData); // Convert all Pre-index data to Index data. List<IndexData> indexData = getIndexData(localeStr, preIndexData); insertIndexData(database, indexData); // Only check for non-indexable key updates after initial index. // Enabled state with non-indexable keys is checked when items are first inserted. Loading @@ -209,14 +231,64 @@ public class DatabaseIndexingManager { } } @VisibleForTesting List<IndexData> getIndexData(String locale, PreIndexData data) { if (mConverter == null) { mConverter = new IndexDataConverter(mContext); } return mConverter.convertPreIndexDataToIndexData(data, locale); } /** * Inserts all of the entries in {@param indexData} into the {@param database} * as Search Data and as part of the Information Hierarchy. */ @VisibleForTesting void addIndaxebleDataToDatabase(SQLiteDatabase database, String locale, PreIndexData data) { if (data.dataToUpdate.size() == 0) { return; void insertIndexData(SQLiteDatabase database, List<IndexData> indexData) { ContentValues values; for (IndexData dataRow : indexData) { values = new ContentValues(); values.put(IndexDatabaseHelper.IndexColumns.DOCID, dataRow.getDocId()); values.put(LOCALE, dataRow.locale); values.put(DATA_TITLE, dataRow.updatedTitle); values.put(DATA_TITLE_NORMALIZED, dataRow.normalizedTitle); values.put(DATA_SUMMARY_ON, dataRow.updatedSummaryOn); values.put(DATA_SUMMARY_ON_NORMALIZED, dataRow.normalizedSummaryOn); values.put(DATA_ENTRIES, dataRow.entries); values.put(DATA_KEYWORDS, dataRow.spaceDelimitedKeywords); values.put(CLASS_NAME, dataRow.className); values.put(SCREEN_TITLE, dataRow.screenTitle); values.put(INTENT_ACTION, dataRow.intentAction); values.put(INTENT_TARGET_PACKAGE, dataRow.intentTargetPackage); values.put(INTENT_TARGET_CLASS, dataRow.intentTargetClass); values.put(ICON, dataRow.iconResId); values.put(ENABLED, dataRow.enabled); values.put(DATA_KEY_REF, dataRow.key); values.put(USER_ID, dataRow.userId); values.put(PAYLOAD_TYPE, dataRow.payloadType); values.put(PAYLOAD, dataRow.payload); database.replaceOrThrow(TABLE_PREFS_INDEX, null, values); if (!TextUtils.isEmpty(dataRow.className) && !TextUtils.isEmpty(dataRow.childClassName)) { ContentValues siteMapPair = new ContentValues(); final int pairDocId = Objects.hash(dataRow.className, dataRow.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, dataRow.className); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, dataRow.screenTitle); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, dataRow.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, dataRow.updatedTitle); database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null /* nullColumnHack */, siteMapPair); } } IndexDataConverter manager = new IndexDataConverter(mContext, database); manager.addDataToDatabase(locale, data.dataToUpdate, data.nonIndexableKeys); } /** Loading Loading @@ -288,7 +360,6 @@ public class DatabaseIndexingManager { disabledResults.close(); } /** * TODO (b/64951285): Deprecate this method * Loading
src/com/android/settings/search/indexing/IndexDataConverter.java +47 −100 Original line number Diff line number Diff line Loading @@ -17,10 +17,8 @@ package com.android.settings.search.indexing; import android.content.ContentValues; import android.content.Context; import android.content.res.XmlResourceParser; import android.database.sqlite.SQLiteDatabase; import android.provider.SearchIndexableData; import android.provider.SearchIndexableResource; import android.support.annotation.DrawableRes; Loading @@ -32,7 +30,6 @@ import android.util.Xml; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.search.IndexDatabaseHelper; import com.android.settings.search.Indexable; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; Loading @@ -44,33 +41,10 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_RANK; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; /** * Helper class to convert {@link PreIndexData} to {@link IndexData}. * Loading @@ -86,56 +60,65 @@ public class IndexDataConverter { private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference"; private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference"; private Context mContext; private final Context mContext; private String mLocale; private SQLiteDatabase mDb; private List<IndexData> mIndexData; public IndexDataConverter(Context context, SQLiteDatabase database) { public IndexDataConverter(Context context) { mContext = context; mDb = database; mLocale = Locale.getDefault().toString(); } public List<IndexData> convertPreIndexDataToIndexData(PreIndexData preIndexData, String locale) { mLocale = locale; mIndexData = new ArrayList<>(); List<SearchIndexableData> dataToUpdate = preIndexData.dataToUpdate; Map<String, Set<String>> nonIndexableKeys = preIndexData.nonIndexableKeys; parsePreIndexData(dataToUpdate, nonIndexableKeys); return mIndexData; } /** * Inserts {@link SearchIndexableData} into the database. * * @param localeStr is the locale of the data to be inserted. * @param dataToUpdate is a {@link List} of the data to be inserted. * @param nonIndexableKeys is a {@link Map} from Package Name to a {@link Set} of keys which * identify search results which should not be surfaced. */ public void addDataToDatabase(String localeStr, List<SearchIndexableData> dataToUpdate, private void parsePreIndexData(List<SearchIndexableData> dataToUpdate, Map<String, Set<String>> nonIndexableKeys) { final long current = System.currentTimeMillis(); for (SearchIndexableData data : dataToUpdate) { try { indexOneSearchIndexableData(localeStr, data, nonIndexableKeys); addOneIndexData(data, nonIndexableKeys); } catch (Exception e) { Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data) + " for locale: " + localeStr, e); + " for locale: " + mLocale, e); } } final long now = System.currentTimeMillis(); Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " + Log.d(LOG_TAG, "Indexing locale '" + mLocale + "' took " + (now - current) + " millis"); } @VisibleForTesting void indexOneSearchIndexableData(String localeStr, SearchIndexableData data, private void addOneIndexData(SearchIndexableData data, Map<String, Set<String>> nonIndexableKeys) { if (data instanceof SearchIndexableResource) { indexOneResource(localeStr, (SearchIndexableResource) data, nonIndexableKeys); addOneResource((SearchIndexableResource) data, nonIndexableKeys); } else if (data instanceof SearchIndexableRaw) { indexOneRaw(localeStr, (SearchIndexableRaw) data, nonIndexableKeys); addOneRaw((SearchIndexableRaw) data, nonIndexableKeys); } } @VisibleForTesting void indexOneRaw(String localeStr, SearchIndexableRaw raw, Map<String, private void addOneRaw(SearchIndexableRaw raw, Map<String, Set<String>> nonIndexableKeysFromResource) { // Should be the same locale as the one we are processing if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { if (!raw.locale.toString().equalsIgnoreCase(mLocale)) { return; } Loading @@ -149,7 +132,7 @@ public class IndexDataConverter { IndexData.Builder builder = new IndexData.Builder(); builder.setTitle(raw.title) .setSummaryOn(raw.summaryOn) .setLocale(localeStr) .setLocale(mLocale) .setEntries(raw.entries) .setKeywords(raw.keywords) .setClassName(raw.className) Loading @@ -162,11 +145,10 @@ public class IndexDataConverter { .setKey(raw.key) .setUserId(raw.userId); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } @VisibleForTesting void indexOneResource(String localeStr, SearchIndexableResource sir, private void addOneResource(SearchIndexableResource sir, Map<String, Set<String>> nonIndexableKeysFromResource) { if (sir == null) { Loading @@ -182,7 +164,7 @@ public class IndexDataConverter { nonIndexableKeys.addAll(resNonIndexableKeys); } indexFromResource(localeStr, sir, nonIndexableKeys); addIndexDataFromResource(sir, nonIndexableKeys); } else { if (TextUtils.isEmpty(sir.className)) { Log.w(LOG_TAG, "Cannot index an empty Search Provider name!"); Loading @@ -202,17 +184,16 @@ public class IndexDataConverter { DatabaseIndexingUtils.getSearchIndexProvider(clazz); if (provider != null) { List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context); if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) { if (providerNonIndexableKeys != null) { nonIndexableKeys.addAll(providerNonIndexableKeys); } indexFromProvider(localeStr, provider, sir, nonIndexableKeys); addIndexDataFromProvider(provider, sir, nonIndexableKeys); } } } @VisibleForTesting void indexFromResource(String localeStr, SearchIndexableResource sir, private void addIndexDataFromResource(SearchIndexableResource sir, List<String> nonIndexableKeys) { final Context context = sir.context; XmlResourceParser parser = null; Loading Loading @@ -274,7 +255,7 @@ public class IndexDataConverter { headerBuilder.setTitle(headerTitle) .setSummaryOn(headerSummary) .setKeywords(headerKeywords) .setLocale(localeStr) .setLocale(mLocale) .setClassName(fragmentName) .setScreenTitle(screenTitle) .setIntentAction(intentAction) Loading Loading @@ -308,7 +289,7 @@ public class IndexDataConverter { builder = new IndexData.Builder(); builder.setTitle(title) .setLocale(localeStr) .setLocale(mLocale) .setKeywords(keywords) .setClassName(fragmentName) .setScreenTitle(screenTitle) Loading Loading @@ -339,7 +320,7 @@ public class IndexDataConverter { .setPayload(payload); // Insert rows for the child nodes of PreferenceScreen updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } else { // TODO (b/33577327) We removed summary off here. We should check if we can // merge this 'else' section with the one above. Put a break point to Loading @@ -353,13 +334,13 @@ public class IndexDataConverter { builder.setSummaryOn(summaryOn); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } } // The xml header's title does not match the title of one of the child settings. if (isHeaderUnique) { updateOneRow(headerBuilder.build(mContext)); addRowToData(headerBuilder.build(mContext)); } } catch (XmlPullParserException e) { throw new RuntimeException("Error parsing PreferenceScreen", e); Loading @@ -370,8 +351,7 @@ public class IndexDataConverter { } } @VisibleForTesting void indexFromProvider(String localeStr, Indexable.SearchIndexProvider provider, private void addIndexDataFromProvider(Indexable.SearchIndexProvider provider, SearchIndexableResource sir, List<String> nonIndexableKeys) { final String className = sir.className; Loading @@ -393,7 +373,7 @@ public class IndexDataConverter { SearchIndexableRaw raw = rawList.get(i); // Should be the same locale as the one we are processing if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { if (!raw.locale.toString().equalsIgnoreCase(mLocale)) { continue; } boolean enabled = !nonIndexableKeys.contains(raw.key); Loading @@ -401,7 +381,7 @@ public class IndexDataConverter { IndexData.Builder builder = new IndexData.Builder(); builder.setTitle(raw.title) .setSummaryOn(raw.summaryOn) .setLocale(localeStr) .setLocale(mLocale) .setEntries(raw.entries) .setKeywords(raw.keywords) .setClassName(className) Loading @@ -414,7 +394,7 @@ public class IndexDataConverter { .setKey(raw.key) .setUserId(raw.userId); updateOneRow(builder.build(mContext)); addRowToData(builder.build(mContext)); } } Loading @@ -426,7 +406,7 @@ public class IndexDataConverter { SearchIndexableResource item = resList.get(i); // Should be the same locale as the one we are processing if (!item.locale.toString().equalsIgnoreCase(localeStr)) { if (!item.locale.toString().equalsIgnoreCase(mLocale)) { continue; } Loading @@ -440,49 +420,16 @@ public class IndexDataConverter { ? intentTargetPackage : item.intentTargetPackage; indexFromResource(localeStr, item, nonIndexableKeys); addIndexDataFromResource(item, nonIndexableKeys); } } } private void updateOneRow(IndexData row) { private void addRowToData(IndexData row) { if (TextUtils.isEmpty(row.updatedTitle)) { return; } ContentValues values = new ContentValues(); values.put(IndexDatabaseHelper.IndexColumns.DOCID, row.getDocId()); values.put(LOCALE, row.locale); values.put(DATA_TITLE, row.updatedTitle); values.put(DATA_TITLE_NORMALIZED, row.normalizedTitle); values.put(DATA_SUMMARY_ON, row.updatedSummaryOn); values.put(DATA_SUMMARY_ON_NORMALIZED, row.normalizedSummaryOn); values.put(DATA_ENTRIES, row.entries); values.put(DATA_KEYWORDS, row.spaceDelimitedKeywords); values.put(CLASS_NAME, row.className); values.put(SCREEN_TITLE, row.screenTitle); values.put(INTENT_ACTION, row.intentAction); values.put(INTENT_TARGET_PACKAGE, row.intentTargetPackage); values.put(INTENT_TARGET_CLASS, row.intentTargetClass); values.put(ICON, row.iconResId); values.put(ENABLED, row.enabled); values.put(DATA_KEY_REF, row.key); values.put(USER_ID, row.userId); values.put(PAYLOAD_TYPE, row.payloadType); values.put(PAYLOAD, row.payload); mDb.replaceOrThrow(TABLE_PREFS_INDEX, null, values); if (!TextUtils.isEmpty(row.className) && !TextUtils.isEmpty(row.childClassName)) { ContentValues siteMapPair = new ContentValues(); final int pairDocId = Objects.hash(row.className, row.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, row.className); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, row.screenTitle); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, row.childClassName); siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, row.updatedTitle); mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null, siteMapPair); } mIndexData.add(row); } }
tests/robotests/assets/grandfather_not_in_search_index_provider_registry +1 −0 Original line number Diff line number Diff line com.android.settings.development.DevelopmentSettingsDashboardFragment com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard com.android.settings.search.indexing.FakeSettingsFragment
tests/robotests/res/xml-mcc999/about_legal.xml 0 → 100644 +34 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- WARNING: This resource file is used to test Settings Search indexing. If you change something in here, please run the settings robotests and make sure they still pass. --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" android:title="bears_bears_bears" settings:keywords="keywords"> <Preference android:key="pref_key_1" android:title="bears_bears_bears"/> </PreferenceScreen> No newline at end of file