Pre-patch, settings search provider would push all of its fragments into to search via SearchIndexableResources with an implicit contract of if the resource's xml == 0, then it was a settings fragment with an Index provider. One, implicit contract is bad. Two, it was messy at indexing time. So this patch moves htat conversion into the search index provider. Such that all of the indexables are either real Resources or Raw. Change-Id: I39f4351c03d123bb9b45edb4df7f924cfaff2b38 Fixes: 65376542 Fixes: 37741509 Test: robotests
224 lines
9.7 KiB
Java
224 lines
9.7 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.search;
|
|
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
|
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
|
|
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
|
|
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
|
|
import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
|
|
|
|
import android.content.Context;
|
|
import android.database.Cursor;
|
|
import android.database.MatrixCursor;
|
|
import android.provider.SearchIndexableResource;
|
|
import android.provider.SearchIndexablesProvider;
|
|
import android.text.TextUtils;
|
|
import android.util.ArraySet;
|
|
import android.util.Log;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
|
|
public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
|
|
public static final boolean DEBUG = false;
|
|
private static final String TAG = "SettingsSearchProvider";
|
|
|
|
private static final Collection<String> INVALID_KEYS;
|
|
|
|
static {
|
|
INVALID_KEYS = new ArraySet<>();
|
|
INVALID_KEYS.add(null);
|
|
INVALID_KEYS.add("");
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreate() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Cursor queryXmlResources(String[] projection) {
|
|
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
|
|
final List<SearchIndexableResource> resources =
|
|
getSearchIndexableResourcesFromProvider(getContext());
|
|
for (SearchIndexableResource val : resources) {
|
|
Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length];
|
|
ref[COLUMN_INDEX_XML_RES_RANK] = val.rank;
|
|
ref[COLUMN_INDEX_XML_RES_RESID] = val.xmlResId;
|
|
ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = val.className;
|
|
ref[COLUMN_INDEX_XML_RES_ICON_RESID] = val.iconResId;
|
|
ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = val.intentAction;
|
|
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = val.intentTargetPackage;
|
|
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = null; // intent target class
|
|
cursor.addRow(ref);
|
|
}
|
|
|
|
return cursor;
|
|
}
|
|
|
|
@Override
|
|
public Cursor queryRawData(String[] projection) {
|
|
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
|
|
final List<SearchIndexableRaw> raws = getSearchIndexableRawFromProvider(getContext());
|
|
for (SearchIndexableRaw val : raws) {
|
|
Object[] ref = new Object[INDEXABLES_RAW_COLUMNS.length];
|
|
ref[COLUMN_INDEX_RAW_TITLE] = val.title;
|
|
ref[COLUMN_INDEX_RAW_SUMMARY_ON] = val.summaryOn;
|
|
ref[COLUMN_INDEX_RAW_SUMMARY_OFF] = val.summaryOff;
|
|
ref[COLUMN_INDEX_RAW_ENTRIES] = val.entries;
|
|
ref[COLUMN_INDEX_RAW_KEYWORDS] = val.keywords;
|
|
ref[COLUMN_INDEX_RAW_SCREEN_TITLE] = val.screenTitle;
|
|
ref[COLUMN_INDEX_RAW_CLASS_NAME] = val.className;
|
|
ref[COLUMN_INDEX_RAW_ICON_RESID] = val.iconResId;
|
|
ref[COLUMN_INDEX_RAW_INTENT_ACTION] = val.intentAction;
|
|
ref[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = val.intentTargetPackage;
|
|
ref[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = val.intentTargetClass;
|
|
ref[COLUMN_INDEX_RAW_KEY] = val.key;
|
|
ref[COLUMN_INDEX_RAW_USER_ID] = val.userId;
|
|
cursor.addRow(ref);
|
|
}
|
|
|
|
return cursor;
|
|
}
|
|
|
|
/**
|
|
* Gets a combined list non-indexable keys that come from providers inside of settings.
|
|
* The non-indexable keys are used in Settings search at both index and update time to verify
|
|
* the validity of results in the database.
|
|
*/
|
|
@Override
|
|
public Cursor queryNonIndexableKeys(String[] projection) {
|
|
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
|
|
final List<String> nonIndexableKeys = getNonIndexableKeysFromProvider(getContext());
|
|
for (String nik : nonIndexableKeys) {
|
|
final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length];
|
|
ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik;
|
|
cursor.addRow(ref);
|
|
}
|
|
|
|
return cursor;
|
|
}
|
|
|
|
private List<String> getNonIndexableKeysFromProvider(Context context) {
|
|
final Collection<Class> values = SearchIndexableResources.providerValues();
|
|
final List<String> nonIndexableKeys = new ArrayList<>();
|
|
|
|
for (Class<?> clazz : values) {
|
|
final long startTime = System.currentTimeMillis();
|
|
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
|
|
clazz);
|
|
List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(context);
|
|
|
|
if (providerNonIndexableKeys == null || providerNonIndexableKeys.isEmpty()) {
|
|
if (DEBUG) {
|
|
final long totalTime = System.currentTimeMillis() - startTime;
|
|
Log.d(TAG, "No indexable, total time " + totalTime);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (providerNonIndexableKeys.removeAll(INVALID_KEYS)) {
|
|
Log.v(TAG, provider + " tried to add an empty non-indexable key");
|
|
}
|
|
|
|
if (DEBUG) {
|
|
final long totalTime = System.currentTimeMillis() - startTime;
|
|
Log.d(TAG, "Non-indexables " + providerNonIndexableKeys.size() + ", total time "
|
|
+ totalTime);
|
|
}
|
|
|
|
nonIndexableKeys.addAll(providerNonIndexableKeys);
|
|
}
|
|
|
|
return nonIndexableKeys;
|
|
}
|
|
|
|
private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) {
|
|
Collection<Class> values = SearchIndexableResources.providerValues();
|
|
List<SearchIndexableResource> resourceList = new ArrayList<>();
|
|
|
|
for (Class<?> clazz : values) {
|
|
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
|
|
clazz);
|
|
|
|
final List<SearchIndexableResource> resList =
|
|
provider.getXmlResourcesToIndex(context, true);
|
|
|
|
if (resList == null) {
|
|
continue;
|
|
}
|
|
|
|
for (SearchIndexableResource item : resList) {
|
|
item.className = TextUtils.isEmpty(item.className)
|
|
? clazz.getName()
|
|
: item.className;
|
|
}
|
|
|
|
resourceList.addAll(resList);
|
|
}
|
|
|
|
return resourceList;
|
|
}
|
|
|
|
private List<SearchIndexableRaw> getSearchIndexableRawFromProvider(Context context) {
|
|
final Collection<Class> values = SearchIndexableResources.providerValues();
|
|
final List<SearchIndexableRaw> rawList = new ArrayList<>();
|
|
|
|
for (Class<?> clazz : values) {
|
|
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
|
|
clazz);
|
|
final List<SearchIndexableRaw> providerRaws = provider.getRawDataToIndex(context,
|
|
true /* enabled */);
|
|
|
|
if (providerRaws == null) {
|
|
continue;
|
|
}
|
|
|
|
for (SearchIndexableRaw raw : providerRaws) {
|
|
// The classname and intent information comes from the PreIndexData
|
|
// This will be more clear when provider conversion is done at PreIndex time.
|
|
raw.className = clazz.getName();
|
|
|
|
}
|
|
rawList.addAll(providerRaws);
|
|
}
|
|
|
|
return rawList;
|
|
}
|
|
}
|