Add dynamic Preferences indexing (part 2)

- change the Index SQL model. Add a new "enabled" column.
- use that column for issuing a more restrictive search query
- change the SearchIndexProvider API to pass the "enable" state
- apply it to Bluetooth settings
- refactor the list of indexable resources (SearchIndexableResources)

Change-Id: Ic900fb27cb12a285a80d953aa1aa88f0070cd986
This commit is contained in:
Fabrice Di Meglio
2014-03-20 19:52:29 -07:00
parent 30eb2d3dd1
commit 51bfee595c
9 changed files with 641 additions and 464 deletions

View File

@@ -67,12 +67,13 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new SearchIndexProvider() { new SearchIndexProvider() {
@Override @Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context) { public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
return null; return null;
} }
@Override @Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context) { public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER); final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);

View File

@@ -28,6 +28,7 @@ import android.widget.Toast;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.WirelessSettings; import com.android.settings.WirelessSettings;
import com.android.settings.search.Index;
/** /**
* BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox * BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox
@@ -132,6 +133,7 @@ public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeLis
case BluetoothAdapter.STATE_ON: case BluetoothAdapter.STATE_ON:
setChecked(true); setChecked(true);
mSwitch.setEnabled(true); mSwitch.setEnabled(true);
updateSearchIndex(true);
break; break;
case BluetoothAdapter.STATE_TURNING_OFF: case BluetoothAdapter.STATE_TURNING_OFF:
mSwitch.setEnabled(false); mSwitch.setEnabled(false);
@@ -139,10 +141,12 @@ public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeLis
case BluetoothAdapter.STATE_OFF: case BluetoothAdapter.STATE_OFF:
setChecked(false); setChecked(false);
mSwitch.setEnabled(true); mSwitch.setEnabled(true);
updateSearchIndex(false);
break; break;
default: default:
setChecked(false); setChecked(false);
mSwitch.setEnabled(true); mSwitch.setEnabled(true);
updateSearchIndex(false);
} }
} }
@@ -159,4 +163,9 @@ public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeLis
} }
} }
} }
private void updateSearchIndex(boolean isBluetoothOn) {
Index.getInstance(mContext).updateFromClassNameResource(
BluetoothSettings.class.getName(), isBluetoothOn);
}
} }

View File

@@ -48,7 +48,6 @@ import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw; import com.android.settings.search.SearchIndexableRaw;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -421,40 +420,42 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
} }
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new SearchIndexProvider() { new SearchIndexProvider() {
@Override @Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context) { public List<SearchIndexableResource> getXmlResourcesToIndex(
return null; Context context, boolean enabled) {
} return null;
}
@Override @Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context) { public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
final Resources res = context.getResources(); final Resources res = context.getResources();
// Add fragment title // Add fragment title
SearchIndexableRaw data = new SearchIndexableRaw(context); SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = res.getString(R.string.bluetooth_settings); data.title = res.getString(R.string.bluetooth_settings);
data.screenTitle = res.getString(R.string.bluetooth_settings);
result.add(data);
// Add cached paired BT devices
LocalBluetoothManager lbtm = LocalBluetoothManager.getInstance(context);
Set<BluetoothDevice> bondedDevices =
lbtm.getBluetoothAdapter().getBondedDevices();
for (BluetoothDevice device : bondedDevices) {
data = new SearchIndexableRaw(context);
data.title = device.getName();
data.screenTitle = res.getString(R.string.bluetooth_settings); data.screenTitle = res.getString(R.string.bluetooth_settings);
data.enabled = enabled;
result.add(data); result.add(data);
// Add cached paired BT devices
LocalBluetoothManager lbtm = LocalBluetoothManager.getInstance(context);
Set<BluetoothDevice> bondedDevices =
lbtm.getBluetoothAdapter().getBondedDevices();
for (BluetoothDevice device : bondedDevices) {
data = new SearchIndexableRaw(context);
data.title = device.getName();
data.screenTitle = res.getString(R.string.bluetooth_settings);
result.add(data);
}
return result;
} }
};
return result;
}
};
} }

View File

@@ -65,6 +65,7 @@ public class Index {
public static final int COLUMN_INDEX_INTENT_ACTION = 7; public static final int COLUMN_INDEX_INTENT_ACTION = 7;
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 8; public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 8;
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 9; public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 9;
public static final int COLUMN_INDEX_ENABLED = 10;
// If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
private static final String[] SELECT_COLUMNS = new String[] { private static final String[] SELECT_COLUMNS = new String[] {
@@ -93,13 +94,30 @@ public class Index {
private static final String HYPHEN = "-"; private static final String HYPHEN = "-";
private static Index sInstance; private static Index sInstance;
private final AtomicBoolean mIsAvailable = new AtomicBoolean(false); private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
private final UpdateData mDataToProcess = new UpdateData();
private final UpdateData mUpdateData = new UpdateData();
private final Context mContext; private final Context mContext;
/**
* A private class to describe the update data for the Index database
*/
private class UpdateData {
public List<SearchIndexableData> dataToUpdate;
public List<String> dataToDelete;
public boolean forceUpdate = false;
public UpdateData() {
dataToUpdate = new ArrayList<SearchIndexableData>();
dataToDelete = new ArrayList<String>();
}
public void clear() {
dataToUpdate.clear();
dataToDelete.clear();
forceUpdate = false;
}
}
/** /**
* A basic singleton * A basic singleton
*/ */
@@ -118,26 +136,32 @@ public class Index {
return mIsAvailable.get(); return mIsAvailable.get();
} }
public Cursor search(String query) {
final String sql = buildSQL(query);
Log.d(LOG_TAG, "Query: " + sql);
return getReadableDatabase().rawQuery(sql, null);
}
public void addIndexableData(SearchIndexableData data) { public void addIndexableData(SearchIndexableData data) {
synchronized (mUpdateData) { synchronized (mDataToProcess) {
mUpdateData.dataToAdd.add(data); mDataToProcess.dataToUpdate.add(data);
} }
} }
public void addIndexableData(SearchIndexableResource[] array) { public void addIndexableData(SearchIndexableResource[] array) {
synchronized (mUpdateData) { synchronized (mDataToProcess) {
final int count = array.length; final int count = array.length;
for (int n = 0; n < count; n++) { for (int n = 0; n < count; n++) {
mUpdateData.dataToAdd.add(array[n]); mDataToProcess.dataToUpdate.add(array[n]);
} }
} }
} }
public void deleteIndexableData(String[] array) { public void deleteIndexableData(String[] array) {
synchronized (mUpdateData) { synchronized (mDataToProcess) {
final int count = array.length; final int count = array.length;
for (int n = 0; n < count; n++) { for (int n = 0; n < count; n++) {
mUpdateData.dataToDelete.add(array[n]); mDataToProcess.dataToDelete.add(array[n]);
} }
} }
} }
@@ -152,27 +176,69 @@ public class Index {
final ResolveInfo info = list.get(n); final ResolveInfo info = list.get(n);
final String authority = info.providerInfo.authority; final String authority = info.providerInfo.authority;
final String packageName = info.providerInfo.packageName; final String packageName = info.providerInfo.packageName;
final Context packageContext; addIndexablesFromRemoteProvider(packageName, authority);
try {
packageContext = mContext.createPackageContext(packageName, 0);
final Uri uriForResources = buildUriForXmlResources(authority);
addIndexablesForXmlResourceUri(packageContext, packageName, uriForResources,
SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS);
final Uri uriForRawData = buildUriForRawData(authority);
addIndexablesForRawDataUri(packageContext, packageName, uriForRawData,
SearchIndexablesContract.INDEXABLES_RAW_COLUMNS);
} catch (PackageManager.NameNotFoundException e) {
Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
+ Log.getStackTraceString(e));
continue;
}
} }
return updateInternal(); return updateInternal();
} }
public boolean updateFromRemoteProvider(String packageName, String authority) {
if (!addIndexablesFromRemoteProvider(packageName, authority)) {
return false;
}
return updateInternal();
}
public boolean updateFromClassNameResource(String className, boolean includeInSearchResults) {
if (className == null) {
throw new IllegalArgumentException("class name cannot be null!");
}
final SearchIndexableResource res = SearchIndexableResources.getResourceByName(className);
if (res == null ) {
Log.e(LOG_TAG, "Cannot find SearchIndexableResources for class name: " + className);
return false;
}
res.enabled = includeInSearchResults;
addIndexableData(res);
mDataToProcess.forceUpdate = true;
boolean result = updateInternal();
res.enabled = false;
return result;
}
private boolean updateFromSearchIndexableData(SearchIndexableData data) {
addIndexableData(data);
return updateInternal();
}
private SQLiteDatabase getReadableDatabase() {
return IndexDatabaseHelper.getInstance(mContext).getReadableDatabase();
}
private SQLiteDatabase getWritableDatabase() {
return IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
}
private boolean addIndexablesFromRemoteProvider(String packageName, String authority) {
final Context packageContext;
try {
packageContext = mContext.createPackageContext(packageName, 0);
final Uri uriForResources = buildUriForXmlResources(authority);
addIndexablesForXmlResourceUri(packageContext, packageName, uriForResources,
SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS);
final Uri uriForRawData = buildUriForRawData(authority);
addIndexablesForRawDataUri(packageContext, packageName, uriForRawData,
SearchIndexablesContract.INDEXABLES_RAW_COLUMNS);
return true;
} catch (PackageManager.NameNotFoundException e) {
Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
+ Log.getStackTraceString(e));
return false;
}
}
private static Uri buildUriForXmlResources(String authority) { private static Uri buildUriForXmlResources(String authority) {
return Uri.parse("content://" + authority + "/" + return Uri.parse("content://" + authority + "/" +
SearchIndexablesContract.INDEXABLES_XML_RES_PATH); SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
@@ -183,10 +249,28 @@ public class Index {
SearchIndexablesContract.INDEXABLES_RAW_PATH); SearchIndexablesContract.INDEXABLES_RAW_PATH);
} }
private void addIndexablesForXmlResourceUri(Context packageContext, String packageName, Uri uri, private boolean updateInternal() {
String[] projection) { synchronized (mDataToProcess) {
final ContentResolver resolver = packageContext.getContentResolver(); final UpdateIndexTask task = new UpdateIndexTask();
task.execute(mDataToProcess);
try {
final boolean result = task.get();
mDataToProcess.clear();
return result;
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
return false;
} catch (ExecutionException e) {
Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
return false;
}
}
}
private void addIndexablesForXmlResourceUri(Context packageContext, String packageName,
Uri uri, String[] projection) {
final ContentResolver resolver = packageContext.getContentResolver();
final Cursor cursor = resolver.query(uri, projection, final Cursor cursor = resolver.query(uri, projection,
null, null, null); null, null, null);
@@ -227,10 +311,10 @@ public class Index {
} }
} }
private void addIndexablesForRawDataUri(Context packageContext, String packageName, Uri uri, private void addIndexablesForRawDataUri(Context packageContext, String packageName,
String[] projection) { Uri uri, String[] projection) {
final ContentResolver resolver = packageContext.getContentResolver();
final ContentResolver resolver = packageContext.getContentResolver();
final Cursor cursor = resolver.query(uri, projection, final Cursor cursor = resolver.query(uri, projection,
null, null, null); null, null, null);
@@ -278,30 +362,6 @@ public class Index {
} }
} }
private boolean updateInternal() {
synchronized (mUpdateData) {
final UpdateIndexTask task = new UpdateIndexTask();
task.execute(mUpdateData);
try {
final boolean result = task.get();
mUpdateData.clear();
return result;
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
return false;
} catch (ExecutionException e) {
Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
return false;
}
}
}
public Cursor search(String query) {
final String sql = buildSQL(query);
Log.d(LOG_TAG, "Query: " + sql);
return getReadableDatabase().rawQuery(sql, null);
}
private String buildSQL(String query) { private String buildSQL(String query) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(buildSQLForColumn(query, MATCH_COLUMNS)); sb.append(buildSQLForColumn(query, MATCH_COLUMNS));
@@ -335,6 +395,9 @@ public class Index {
sb.append(IndexColumns.LOCALE); sb.append(IndexColumns.LOCALE);
sb.append(" = "); sb.append(" = ");
DatabaseUtils.appendEscapedSQLString(sb, Locale.getDefault().toString()); DatabaseUtils.appendEscapedSQLString(sb, Locale.getDefault().toString());
sb.append(" AND ");
sb.append(IndexColumns.ENABLED);
sb.append(" = 1");
return sb.toString(); return sb.toString();
} }
@@ -353,32 +416,265 @@ public class Index {
return sb.toString(); return sb.toString();
} }
private SQLiteDatabase getReadableDatabase() { private void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
return IndexDatabaseHelper.getInstance(mContext).getReadableDatabase(); SearchIndexableData data) {
if (data instanceof SearchIndexableResource) {
indexOneResource(database, localeStr, (SearchIndexableResource) data);
} else if (data instanceof SearchIndexableRaw) {
indexOneRaw(database, localeStr, (SearchIndexableRaw) data);
}
} }
private SQLiteDatabase getWritableDatabase() { private void indexOneResource(SQLiteDatabase database, String localeStr,
return IndexDatabaseHelper.getInstance(mContext).getWritableDatabase(); SearchIndexableResource sir) {
if (sir.xmlResId > 0) {
indexFromResource(sir.context, database, localeStr,
sir.xmlResId, sir.className, sir.iconResId, sir.rank,
sir.intentAction, sir.intentTargetPackage, sir.intentTargetClass);
} else if (!TextUtils.isEmpty(sir.className)) {
sir.context = mContext;
indexFromLocalProvider(database, localeStr, sir);
}
} }
/** private void indexFromResource(Context context, SQLiteDatabase database, String localeStr,
* A private class to describe the update data for the Index database int xmlResId, String fragmentName, int iconResId, int rank,
*/ String intentAction, String intentTargetPackage, String intentTargetClass) {
private class UpdateData {
public List<SearchIndexableData> dataToAdd;
public List<String> dataToDelete;
public UpdateData() { XmlResourceParser parser = null;
dataToAdd = new ArrayList<SearchIndexableData>(); try {
dataToDelete = new ArrayList<String>(); parser = context.getResources().getXml(xmlResId);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
// Parse next until start tag is found
}
String nodeName = parser.getName();
if (!"PreferenceScreen".equals(nodeName)) {
throw new RuntimeException(
"XML document must start with <PreferenceScreen> tag; found"
+ nodeName + " at " + parser.getPositionDescription());
}
final int outerDepth = parser.getDepth();
final AttributeSet attrs = Xml.asAttributeSet(parser);
final String screenTitle = getDataTitle(context, attrs);
String title = getDataTitle(context, attrs);
String summary = getDataSummary(context, attrs);
String keywords = getDataKeywords(context, attrs);
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
// hyphens.
updateOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, true);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
title = getDataTitle(context, attrs);
summary = getDataSummary(context, attrs);
keywords = getDataKeywords(context, attrs);
// Insert rows for the child nodes of PreferenceScreen
updateOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, true);
}
} catch (XmlPullParserException e) {
throw new RuntimeException("Error parsing PreferenceScreen", e);
} catch (IOException e) {
throw new RuntimeException("Error parsing PreferenceScreen", e);
} finally {
if (parser != null) parser.close();
}
}
private void indexOneRaw(SQLiteDatabase database, String localeStr,
SearchIndexableRaw raw) {
// Should be the same locale as the one we are processing
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
return;
} }
public void clear() { updateOneRowWithFilteredData(database, localeStr,
dataToAdd.clear(); raw.title,
dataToDelete.clear(); raw.summary,
raw.className,
raw.screenTitle,
raw.iconResId,
raw.rank,
raw.keywords,
raw.intentAction,
raw.intentTargetPackage,
raw.intentTargetClass,
raw.enabled);
}
private void indexFromLocalProvider(SQLiteDatabase database, String localeStr,
SearchIndexableResource sir) {
try {
final Class<?> clazz = Class.forName(sir.className);
if (Indexable.class.isAssignableFrom(clazz)) {
final Field f = clazz.getField("SEARCH_INDEX_DATA_PROVIDER");
final Indexable.SearchIndexProvider provider =
(Indexable.SearchIndexProvider) f.get(null);
final List<SearchIndexableRaw> rawList =
provider.getRawDataToIndex(sir.context, sir.enabled);
if (rawList != null) {
final int rawSize = rawList.size();
for (int i = 0; i < rawSize; i++) {
SearchIndexableRaw raw = rawList.get(i);
// Should be the same locale as the one we are processing
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
continue;
}
updateOneRowWithFilteredData(database, localeStr,
raw.title,
raw.summary,
sir.className,
raw.screenTitle,
sir.iconResId,
sir.rank,
raw.keywords,
raw.intentAction,
raw.intentTargetPackage,
raw.intentTargetClass,
raw.enabled);
}
}
final List<SearchIndexableResource> resList =
provider.getXmlResourcesToIndex(sir.context, sir.enabled);
if (resList != null) {
final int resSize = resList.size();
for (int i = 0; i < resSize; i++) {
SearchIndexableResource item = resList.get(i);
// Should be the same locale as the one we are processing
if (!item.locale.toString().equalsIgnoreCase(localeStr)) {
continue;
}
indexFromResource(sir.context, database, localeStr,
item.xmlResId, item.className, item.iconResId, item.rank,
item.intentAction, item.intentTargetPackage,
item.intentTargetClass);
}
}
}
} catch (ClassNotFoundException e) {
Log.e(LOG_TAG, "Cannot find class: " + sir.className, e);
} catch (NoSuchFieldException e) {
Log.e(LOG_TAG, "Cannot find field 'SEARCH_INDEX_DATA_PROVIDER'", e);
} catch (IllegalAccessException e) {
Log.e(LOG_TAG, "Illegal access to field 'SEARCH_INDEX_DATA_PROVIDER'", e);
} }
} }
private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale,
String title, String summary, String className, String screenTitle,
int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass,
boolean enabled) {
String updatedTitle;
if (title != null) {
updatedTitle = title.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
}
else {
updatedTitle = EMPTY;
}
String updatedSummary;
if (summary != null) {
updatedSummary = summary.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
} else {
updatedSummary = EMPTY;
}
String normalizedTitle = updatedTitle.replaceAll(HYPHEN, EMPTY);
String normalizedSummary = updatedSummary.replaceAll(HYPHEN, EMPTY);
updateOneRow(database, locale,
updatedTitle, normalizedTitle, updatedSummary, normalizedSummary,
className, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, enabled);
}
private void updateOneRow(SQLiteDatabase database, String locale,
String updatedTitle, String normalizedTitle,
String updatedSummary, String normalizedSummary,
String className, String screenTitle,
int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass,
boolean enabled) {
if (TextUtils.isEmpty(updatedTitle)) {
return;
}
ContentValues values = new ContentValues();
values.put(IndexColumns.DOCID, updatedTitle.hashCode());
values.put(IndexColumns.LOCALE, locale);
values.put(IndexColumns.DATA_RANK, rank);
values.put(IndexColumns.DATA_TITLE, updatedTitle);
values.put(IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
values.put(IndexColumns.DATA_SUMMARY, updatedSummary);
values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary);
values.put(IndexColumns.DATA_KEYWORDS, keywords);
values.put(IndexColumns.CLASS_NAME, className);
values.put(IndexColumns.SCREEN_TITLE, screenTitle);
values.put(IndexColumns.INTENT_ACTION, intentAction);
values.put(IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage);
values.put(IndexColumns.INTENT_TARGET_CLASS, intentTargetClass);
values.put(IndexColumns.ICON, iconResId);
values.put(IndexColumns.ENABLED, enabled);
database.replaceOrThrow(Tables.TABLE_PREFS_INDEX, null, values);
}
private String getDataTitle(Context context, AttributeSet attrs) {
return getData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_title);
}
private String getDataSummary(Context context, AttributeSet attrs) {
return getData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_summary);
}
private String getDataKeywords(Context context, AttributeSet attrs) {
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
}
private String getData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId);
CharSequence data = null;
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
data = context.getText(tv.resourceId);
} else {
data = tv.string;
}
}
return (data != null) ? data.toString() : null;
}
/** /**
* A private class for updating the Index database * A private class for updating the Index database
*/ */
@@ -400,15 +696,16 @@ public class Index {
protected Boolean doInBackground(UpdateData... params) { protected Boolean doInBackground(UpdateData... params) {
boolean result = false; boolean result = false;
final List<SearchIndexableData> dataToAdd = params[0].dataToAdd; final List<SearchIndexableData> dataToUpdate = params[0].dataToUpdate;
final List<String> dataToDelete = params[0].dataToDelete; final List<String> dataToDelete = params[0].dataToDelete;
final boolean forceUpdate = params[0].forceUpdate;
final SQLiteDatabase database = getWritableDatabase(); final SQLiteDatabase database = getWritableDatabase();
final String localeStr = Locale.getDefault().toString(); final String localeStr = Locale.getDefault().toString();
try { try {
database.beginTransaction(); database.beginTransaction();
if (dataToAdd.size() > 0) { if (dataToUpdate.size() > 0) {
processDataToAdd(database, localeStr, dataToAdd); processDataToUpdate(database, localeStr, dataToUpdate, forceUpdate);
} }
if (dataToDelete.size() > 0) { if (dataToDelete.size() > 0) {
processDataToDelete(database, localeStr, dataToDelete); processDataToDelete(database, localeStr, dataToDelete);
@@ -421,8 +718,31 @@ public class Index {
return result; return result;
} }
private boolean processDataToUpdate(SQLiteDatabase database, String localeStr,
List<SearchIndexableData> dataToUpdate, boolean forceUpdate) {
if (!forceUpdate && isLocaleAlreadyIndexed(database, localeStr)) {
Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed");
return true;
}
boolean result = false;
final long current = System.currentTimeMillis();
final int count = dataToUpdate.size();
for (int n = 0; n < count; n++) {
final SearchIndexableData data = dataToUpdate.get(n);
indexOneSearchIndexableData(database, localeStr, data);
}
final long now = System.currentTimeMillis();
Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
(now - current) + " millis");
return result;
}
private boolean processDataToDelete(SQLiteDatabase database, String localeStr, private boolean processDataToDelete(SQLiteDatabase database, String localeStr,
List<String> dataToDelete) { List<String> dataToDelete) {
boolean result = false; boolean result = false;
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
@@ -439,127 +759,11 @@ public class Index {
return result; return result;
} }
private boolean processDataToAdd(SQLiteDatabase database, String localeStr, private int delete(SQLiteDatabase database, String title) {
List<SearchIndexableData> dataToAdd) { final String whereClause = IndexColumns.DATA_TITLE + "=?";
if (isLocaleAlreadyIndexed(database, localeStr)) { final String[] whereArgs = new String[] { title };
Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed");
return true;
}
boolean result = false; return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs);
final long current = System.currentTimeMillis();
final int count = dataToAdd.size();
for (int n = 0; n < count; n++) {
final SearchIndexableData data = dataToAdd.get(n);
if (data instanceof SearchIndexableResource) {
indexOneResource(database, localeStr, (SearchIndexableResource) data);
} else if (data instanceof SearchIndexableRaw) {
indexOneRaw(database, localeStr, (SearchIndexableRaw) data);
}
}
final long now = System.currentTimeMillis();
Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
(now - current) + " millis");
return result;
}
private void indexOneResource(SQLiteDatabase database, String localeStr,
SearchIndexableResource sir) {
if (sir.xmlResId > 0) {
indexFromResource(sir.context, database, localeStr,
sir.xmlResId, sir.className, sir.iconResId, sir.rank,
sir.intentAction, sir.intentTargetPackage, sir.intentTargetClass);
} else if (!TextUtils.isEmpty(sir.className)) {
sir.context = mContext;
indexFromLocalProvider(database, localeStr, sir);
}
}
private void indexFromLocalProvider(SQLiteDatabase database, String localeStr,
SearchIndexableResource sir) {
try {
final Class<?> clazz = Class.forName(sir.className);
if (Indexable.class.isAssignableFrom(clazz)) {
final Field f = clazz.getField("SEARCH_INDEX_DATA_PROVIDER");
final Indexable.SearchIndexProvider provider =
(Indexable.SearchIndexProvider) f.get(null);
final List<SearchIndexableRaw> rawList =
provider.getRawDataToIndex(sir.context);
if (rawList != null) {
final int rawSize = rawList.size();
for (int i = 0; i < rawSize; i++) {
SearchIndexableRaw raw = rawList.get(i);
// Should be the same locale as the one we are processing
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
continue;
}
insertOneRowWithFilteredData(database, localeStr,
raw.title,
raw.summary,
sir.className,
raw.screenTitle,
sir.iconResId,
sir.rank,
raw.keywords,
raw.intentAction,
raw.intentTargetPackage,
raw.intentTargetClass
);
}
}
final List<SearchIndexableResource> resList =
provider.getXmlResourcesToIndex(sir.context);
if (resList != null) {
final int resSize = resList.size();
for (int i = 0; i < resSize; i++) {
SearchIndexableResource item = resList.get(i);
// Should be the same locale as the one we are processing
if (!item.locale.toString().equalsIgnoreCase(localeStr)) {
continue;
}
indexFromResource(sir.context, database, localeStr,
item.xmlResId, item.className, item.iconResId, item.rank,
item.intentAction, item.intentTargetPackage,
item.intentTargetClass);
}
}
}
} catch (ClassNotFoundException e) {
Log.e(LOG_TAG, "Cannot find class: " + sir.className, e);
} catch (NoSuchFieldException e) {
Log.e(LOG_TAG, "Cannot find field 'SEARCH_INDEX_DATA_PROVIDER'", e);
} catch (IllegalAccessException e) {
Log.e(LOG_TAG, "Illegal access to field 'SEARCH_INDEX_DATA_PROVIDER'", e);
}
}
private void indexOneRaw(SQLiteDatabase database, String localeStr,
SearchIndexableRaw raw) {
// Should be the same locale as the one we are processing
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
return;
}
insertOneRowWithFilteredData(database, localeStr,
raw.title,
raw.summary,
raw.className,
raw.screenTitle,
raw.iconResId,
raw.rank,
raw.keywords,
raw.intentAction,
raw.intentTargetPackage,
raw.intentTargetClass
);
} }
private boolean isLocaleAlreadyIndexed(SQLiteDatabase database, String locale) { private boolean isLocaleAlreadyIndexed(SQLiteDatabase database, String locale) {
@@ -581,162 +785,5 @@ public class Index {
} }
return result; return result;
} }
private void indexFromResource(Context context, SQLiteDatabase database, String localeStr,
int xmlResId, String fragmentName, int iconResId, int rank,
String intentAction, String intentTargetPackage, String intentTargetClass) {
XmlResourceParser parser = null;
try {
parser = context.getResources().getXml(xmlResId);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
// Parse next until start tag is found
}
String nodeName = parser.getName();
if (!"PreferenceScreen".equals(nodeName)) {
throw new RuntimeException(
"XML document must start with <PreferenceScreen> tag; found"
+ nodeName + " at " + parser.getPositionDescription());
}
final int outerDepth = parser.getDepth();
final AttributeSet attrs = Xml.asAttributeSet(parser);
final String screenTitle = getDataTitle(context, attrs);
String title = getDataTitle(context, attrs);
String summary = getDataSummary(context, attrs);
String keywords = getDataKeywords(context, attrs);
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
// hyphens.
insertOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
title = getDataTitle(context, attrs);
summary = getDataSummary(context, attrs);
keywords = getDataKeywords(context, attrs);
// Insert rows for the child nodes of PreferenceScreen
insertOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
}
} catch (XmlPullParserException e) {
throw new RuntimeException("Error parsing PreferenceScreen", e);
} catch (IOException e) {
throw new RuntimeException("Error parsing PreferenceScreen", e);
} finally {
if (parser != null) parser.close();
}
}
private void insertOneRowWithFilteredData(SQLiteDatabase database, String locale,
String title, String summary, String className, String screenTitle,
int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass) {
String updatedTitle;
if (title != null) {
updatedTitle = title.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
}
else {
updatedTitle = EMPTY;
}
String updatedSummary;
if (summary != null) {
updatedSummary = summary.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
} else {
updatedSummary = EMPTY;
}
String normalizedTitle = updatedTitle.replaceAll(HYPHEN, EMPTY);
String normalizedSummary = updatedSummary.replaceAll(HYPHEN, EMPTY);
insertOneRow(database, locale,
updatedTitle, normalizedTitle, updatedSummary, normalizedSummary,
className, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
}
private void insertOneRow(SQLiteDatabase database, String locale,
String updatedTitle, String normalizedTitle,
String updatedSummary, String normalizedSummary,
String className, String screenTitle,
int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass) {
if (TextUtils.isEmpty(updatedTitle)) {
return;
}
ContentValues values = new ContentValues();
values.put(IndexColumns.LOCALE, locale);
values.put(IndexColumns.DATA_RANK, rank);
values.put(IndexColumns.DATA_TITLE, updatedTitle);
values.put(IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
values.put(IndexColumns.DATA_SUMMARY, updatedSummary);
values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary);
values.put(IndexColumns.DATA_KEYWORDS, keywords);
values.put(IndexColumns.CLASS_NAME, className);
values.put(IndexColumns.SCREEN_TITLE, screenTitle);
values.put(IndexColumns.INTENT_ACTION, intentAction);
values.put(IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage);
values.put(IndexColumns.INTENT_TARGET_CLASS, intentTargetClass);
values.put(IndexColumns.ICON, iconResId);
database.insertOrThrow(Tables.TABLE_PREFS_INDEX, null, values);
}
private int delete(SQLiteDatabase database, String title) {
final String whereClause = IndexColumns.DATA_TITLE + "=?";
final String[] whereArgs = new String[] { title };
return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs);
}
private String getDataTitle(Context context, AttributeSet attrs) {
return getData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_title);
}
private String getDataSummary(Context context, AttributeSet attrs) {
return getData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_summary);
}
private String getDataKeywords(Context context, AttributeSet attrs) {
return getData(context, attrs,
R.styleable.Preference,
R.styleable.Preference_keywords);
}
private String getData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId);
CharSequence data = null;
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
data = context.getText(tv.resourceId);
} else {
data = tv.string;
}
}
return (data != null) ? data.toString() : null;
}
} }
} }

View File

@@ -28,7 +28,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "IndexDatabaseHelper"; private static final String TAG = "IndexDatabaseHelper";
private static final String DATABASE_NAME = "search_index.db"; private static final String DATABASE_NAME = "search_index.db";
private static final int DATABASE_VERSION = 102; private static final int DATABASE_VERSION = 103;
public interface Tables { public interface Tables {
public static final String TABLE_PREFS_INDEX = "prefs_index"; public static final String TABLE_PREFS_INDEX = "prefs_index";
@@ -36,6 +36,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
} }
public interface IndexColumns { public interface IndexColumns {
public static final String DOCID = "docid";
public static final String LOCALE = "locale"; public static final String LOCALE = "locale";
public static final String DATA_RANK = "data_rank"; public static final String DATA_RANK = "data_rank";
public static final String DATA_TITLE = "data_title"; public static final String DATA_TITLE = "data_title";
@@ -49,6 +50,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
public static final String INTENT_TARGET_PACKAGE = "intent_target_package"; public static final String INTENT_TARGET_PACKAGE = "intent_target_package";
public static final String INTENT_TARGET_CLASS = "intent_target_class"; public static final String INTENT_TARGET_CLASS = "intent_target_class";
public static final String ICON = "icon"; public static final String ICON = "icon";
public static final String ENABLED = "enabled";
} }
public interface MetaColumns { public interface MetaColumns {
@@ -83,6 +85,8 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
IndexColumns.INTENT_TARGET_PACKAGE + IndexColumns.INTENT_TARGET_PACKAGE +
", " + ", " +
IndexColumns.INTENT_TARGET_CLASS + IndexColumns.INTENT_TARGET_CLASS +
", " +
IndexColumns.ENABLED +
");"; ");";
private static final String CREATE_META_TABLE = private static final String CREATE_META_TABLE =
@@ -125,9 +129,9 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 100 || oldVersion == 101) { if (oldVersion == 100 || oldVersion == 101 || oldVersion == 102) {
Log.w(TAG, "Detected schema version 100 or 101. " + Log.w(TAG, "Detected schema version 100, 101 or 102. " +
"Index needs to be rebuilt for schema version 102"); "Index needs to be rebuilt for schema version 103");
// We need to drop the tables and recreate them // We need to drop the tables and recreate them
dropTables(db); dropTables(db);
bootstrapDB(db); bootstrapDB(db);

View File

@@ -39,18 +39,23 @@ public interface Indexable {
* *
* See {@link android.provider.SearchIndexableResource} * See {@link android.provider.SearchIndexableResource}
* *
* @param context the context *
* @param context the context.
* @param enabled hint telling if the data needs to be considered into the search results
* or not.
* @return a list of {@link android.provider.SearchIndexableResource} references. * @return a list of {@link android.provider.SearchIndexableResource} references.
* Can be null. * Can be null.
*/ */
List<SearchIndexableResource> getXmlResourcesToIndex(Context context); List<SearchIndexableResource> getXmlResourcesToIndex(Context context, boolean enabled);
/** /**
* Return a list of raw data for indexing. See {@link SearchIndexableRaw} * Return a list of raw data for indexing. See {@link SearchIndexableRaw}
* *
* @param context the context * @param context the context.
* @param enabled hint telling if the data needs to be considered into the search results
* or not.
* @return a list of {@link SearchIndexableRaw} references. Can be null. * @return a list of {@link SearchIndexableRaw} references. Can be null.
*/ */
List<SearchIndexableRaw> getRawDataToIndex(Context context); List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled);
} }
} }

View File

@@ -0,0 +1,172 @@
/*
* 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 android.provider.SearchIndexableResource;
import com.android.settings.DateTimeSettings;
import com.android.settings.DevelopmentSettings;
import com.android.settings.DeviceInfoSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.HomeSettings;
import com.android.settings.PrivacySettings;
import com.android.settings.R;
import com.android.settings.SecuritySettings;
import com.android.settings.SoundSettings;
import com.android.settings.WallpaperTypeSettings;
import com.android.settings.WirelessSettings;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.deviceinfo.Memory;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.location.LocationSettings;
import com.android.settings.net.DataUsageMeteredSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.users.UserSettings;
import com.android.settings.wifi.WifiSettings;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
public final class SearchIndexableResources {
private static int NO_DATA_RES_ID = 0;
private static HashMap<String, SearchIndexableResource> sResMap =
new HashMap<String, SearchIndexableResource>();
static {
sResMap.put(WifiSettings.class.getName(),
new SearchIndexableResource(1,
NO_DATA_RES_ID,
WifiSettings.class.getName(),
R.drawable.ic_settings_wireless));
sResMap.put(BluetoothSettings.class.getName(),
new SearchIndexableResource(2,
NO_DATA_RES_ID,
BluetoothSettings.class.getName(),
R.drawable.ic_settings_bluetooth2));
sResMap.put(DataUsageMeteredSettings.class.getName(),
new SearchIndexableResource(3, R.xml.data_usage_metered_prefs,
DataUsageMeteredSettings.class.getName(),
R.drawable.ic_settings_data_usage));
sResMap.put(WirelessSettings.class.getName(),
new SearchIndexableResource(4, R.xml.wireless_settings,
WirelessSettings.class.getName(),
R.drawable.empty_icon));
sResMap.put(HomeSettings.class.getName(),
new SearchIndexableResource(5, R.xml.home_selection,
HomeSettings.class.getName(),
R.drawable.ic_settings_home));
sResMap.put(SoundSettings.class.getName(),
new SearchIndexableResource(6, R.xml.sound_settings,
SoundSettings.class.getName(),
R.drawable.ic_settings_sound));
sResMap.put(DisplaySettings.class.getName(),
new SearchIndexableResource(7, R.xml.display_settings,
DisplaySettings.class.getName(),
R.drawable.ic_settings_display));
sResMap.put(WallpaperTypeSettings.class.getName(),
new SearchIndexableResource(7, NO_DATA_RES_ID,
WallpaperTypeSettings.class.getName(),
R.drawable.ic_settings_display));
sResMap.put(Memory.class.getName(),
new SearchIndexableResource(8, R.xml.device_info_memory,
Memory.class.getName(),
R.drawable.ic_settings_storage));
sResMap.put(PowerUsageSummary.class.getName(),
new SearchIndexableResource(9, R.xml.power_usage_summary,
PowerUsageSummary.class.getName(),
R.drawable.ic_settings_battery));
sResMap.put(UserSettings.class.getName(),
new SearchIndexableResource(10, R.xml.user_settings,
UserSettings.class.getName(),
R.drawable.ic_settings_multiuser));
sResMap.put(LocationSettings.class.getName(),
new SearchIndexableResource(11, R.xml.location_settings,
LocationSettings.class.getName(),
R.drawable.ic_settings_location));
sResMap.put(SecuritySettings.class.getName(),
new SearchIndexableResource(12, R.xml.security_settings,
SecuritySettings.class.getName(),
R.drawable.ic_settings_security));
sResMap.put(InputMethodAndLanguageSettings.class.getName(),
new SearchIndexableResource(13, R.xml.language_settings,
InputMethodAndLanguageSettings.class.getName(),
R.drawable.ic_settings_language));
sResMap.put(PrivacySettings.class.getName(),
new SearchIndexableResource(14, R.xml.privacy_settings,
PrivacySettings.class.getName(),
R.drawable.ic_settings_backup));
sResMap.put(DateTimeSettings.class.getName(),
new SearchIndexableResource(15, R.xml.date_time_prefs,
DateTimeSettings.class.getName(),
R.drawable.ic_settings_date_time));
sResMap.put(AccessibilitySettings.class.getName(),
new SearchIndexableResource(16, R.xml.accessibility_settings,
AccessibilitySettings.class.getName(),
R.drawable.ic_settings_accessibility));
sResMap.put(PrintSettingsFragment.class.getName(),
new SearchIndexableResource(17, R.xml.print_settings,
PrintSettingsFragment.class.getName(),
com.android.internal.R.drawable.ic_print));
sResMap.put(DevelopmentSettings.class.getName(),
new SearchIndexableResource(18, R.xml.development_prefs,
DevelopmentSettings.class.getName(),
R.drawable.ic_settings_development));
sResMap.put(DeviceInfoSettings.class.getName(),
new SearchIndexableResource(19, R.xml.device_info_settings,
DeviceInfoSettings.class.getName(),
R.drawable.ic_settings_about));
}
private SearchIndexableResources() {
}
public static int size() {
return sResMap.size();
}
public static SearchIndexableResource getResourceByName(String className) {
return sResMap.get(className);
}
public static Collection<SearchIndexableResource> values() {
return sResMap.values();
}
}

View File

@@ -42,77 +42,14 @@ import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.users.UserSettings; import com.android.settings.users.UserSettings;
import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.WifiSettings;
import java.util.Collection;
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS; import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
private static final String TAG = "SettingsSearchIndexablesProvider"; private static final String TAG = "SettingsSearchIndexablesProvider";
private static int NO_DATA_RES_ID = 0;
private static SearchIndexableResource[] INDEXABLE_REFS = new SearchIndexableResource[] {
new SearchIndexableResource(1, NO_DATA_RES_ID,
WifiSettings.class.getName(),
R.drawable.ic_settings_wireless),
new SearchIndexableResource(2, NO_DATA_RES_ID,
BluetoothSettings.class.getName(),
R.drawable.ic_settings_bluetooth2),
new SearchIndexableResource(3, R.xml.data_usage_metered_prefs,
DataUsageMeteredSettings.class.getName(),
R.drawable.ic_settings_data_usage),
new SearchIndexableResource(4, R.xml.wireless_settings,
WirelessSettings.class.getName(),
R.drawable.empty_icon),
new SearchIndexableResource(5, R.xml.home_selection,
HomeSettings.class.getName(),
R.drawable.ic_settings_home),
new SearchIndexableResource(6, R.xml.sound_settings,
SoundSettings.class.getName(),
R.drawable.ic_settings_sound),
new SearchIndexableResource(7, R.xml.display_settings,
DisplaySettings.class.getName(),
R.drawable.ic_settings_display),
new SearchIndexableResource(7, NO_DATA_RES_ID,
WallpaperTypeSettings.class.getName(),
R.drawable.ic_settings_display),
new SearchIndexableResource(8, R.xml.device_info_memory,
Memory.class.getName(),
R.drawable.ic_settings_storage),
new SearchIndexableResource(9, R.xml.power_usage_summary,
PowerUsageSummary.class.getName(),
R.drawable.ic_settings_battery),
new SearchIndexableResource(10, R.xml.user_settings,
UserSettings.class.getName(),
R.drawable.ic_settings_multiuser),
new SearchIndexableResource(11, R.xml.location_settings,
LocationSettings.class.getName(),
R.drawable.ic_settings_location),
new SearchIndexableResource(12, R.xml.security_settings,
SecuritySettings.class.getName(),
R.drawable.ic_settings_security),
new SearchIndexableResource(13, R.xml.language_settings,
InputMethodAndLanguageSettings.class.getName(),
R.drawable.ic_settings_language),
new SearchIndexableResource(14, R.xml.privacy_settings,
PrivacySettings.class.getName(),
R.drawable.ic_settings_backup),
new SearchIndexableResource(15, R.xml.date_time_prefs,
DateTimeSettings.class.getName(),
R.drawable.ic_settings_date_time),
new SearchIndexableResource(16, R.xml.accessibility_settings,
AccessibilitySettings.class.getName(),
R.drawable.ic_settings_accessibility),
new SearchIndexableResource(17, R.xml.print_settings,
PrintSettingsFragment.class.getName(),
com.android.internal.R.drawable.ic_print),
new SearchIndexableResource(18, R.xml.development_prefs,
DevelopmentSettings.class.getName(),
R.drawable.ic_settings_development),
new SearchIndexableResource(19, R.xml.device_info_settings,
DeviceInfoSettings.class.getName(),
R.drawable.ic_settings_about),
};
@Override @Override
public boolean onCreate() { public boolean onCreate() {
return true; return true;
@@ -121,13 +58,13 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
@Override @Override
public Cursor queryXmlResources(String[] projection) { public Cursor queryXmlResources(String[] projection) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS); MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
final int count = INDEXABLE_REFS.length; Collection<SearchIndexableResource> values = SearchIndexableResources.values();
for (int n = 0; n < count; n++) { for (SearchIndexableResource val : values) {
Object[] ref = new Object[7]; Object[] ref = new Object[7];
ref[0] = INDEXABLE_REFS[n].rank; ref[0] = val.rank;
ref[1] = INDEXABLE_REFS[n].xmlResId; ref[1] = val.xmlResId;
ref[2] = INDEXABLE_REFS[n].className; ref[2] = val.className;
ref[3] = INDEXABLE_REFS[n].iconResId; ref[3] = val.iconResId;
ref[4] = null; // intent action ref[4] = null; // intent action
ref[5] = null; // intent target package ref[5] = null; // intent target package
ref[6] = null; // intent target class ref[6] = null; // intent target class

View File

@@ -1168,12 +1168,13 @@ public class WifiSettings extends RestrictedSettingsFragment
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new SearchIndexProvider() { new SearchIndexProvider() {
@Override @Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context) { public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
return null; return null;
} }
@Override @Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context) { public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
final Resources res = context.getResources(); final Resources res = context.getResources();