Add external Preferences indexing

- define SettingsSearchIndexablesProvider as an internal
SearchIndexablesProvider
- protect access thru using android.permission.READ_SEARCH_INDEXABLES
- update WallpaperTypeSettings and WifiSettings for taking care of
the new model
- update the Dashboard for taking care about external Icons for the
search result
- update sqlite model/version for taking care about Intents
(enable launching external applications for showing the settings)

Change-Id: I2e38599327e6480f1754f52666becce0884cee9d
This commit is contained in:
Fabrice Di Meglio
2014-03-12 19:24:43 -07:00
parent 72c6f3f9b8
commit fa7dc240e9
11 changed files with 594 additions and 290 deletions

View File

@@ -1776,5 +1776,18 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
<provider
android:name=".search.SettingsSearchIndexablesProvider"
android:authorities="com.android.settings"
android:multiprocess="false"
android:grantUriPermissions="true"
android:permission="android.permission.READ_SEARCH_INDEXABLES"
android:exported="true">
<intent-filter>
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
</intent-filter>
</provider>
</application> </application>
</manifest> </manifest>

View File

@@ -94,14 +94,12 @@ import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.deviceinfo.Memory; import com.android.settings.deviceinfo.Memory;
import com.android.settings.deviceinfo.UsbSettings; import com.android.settings.deviceinfo.UsbSettings;
import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.indexer.Index; import com.android.settings.search.Index;
import com.android.settings.indexer.IndexableRef;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment; import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
import com.android.settings.inputmethod.SpellCheckersSettings; import com.android.settings.inputmethod.SpellCheckersSettings;
import com.android.settings.inputmethod.UserDictionaryList; import com.android.settings.inputmethod.UserDictionaryList;
import com.android.settings.location.LocationSettings; import com.android.settings.location.LocationSettings;
import com.android.settings.net.DataUsageMeteredSettings;
import com.android.settings.nfc.AndroidBeam; import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings; import com.android.settings.nfc.PaymentSettings;
import com.android.settings.print.PrintJobSettingsFragment; import com.android.settings.print.PrintJobSettingsFragment;
@@ -342,76 +340,6 @@ public class SettingsActivity extends Activity
} }
}; };
private static int NO_DATA_RES_ID = 0;
/**
* Indexable data description.
*
* Known restriction: we are only searching (for now) the first level of Settings.
*/
private static IndexableRef[] INDEXABLE_REFS = new IndexableRef[] {
new IndexableRef(1, NO_DATA_RES_ID,
WifiSettings.class.getName(),
R.drawable.ic_settings_wireless),
new IndexableRef(2, R.xml.bluetooth_settings,
BluetoothSettings.class.getName(),
R.drawable.ic_settings_bluetooth2),
new IndexableRef(3, R.xml.data_usage_metered_prefs,
DataUsageMeteredSettings.class.getName(),
R.drawable.ic_settings_data_usage),
new IndexableRef(4, R.xml.wireless_settings,
WirelessSettings.class.getName(),
R.drawable.empty_icon),
new IndexableRef(5, R.xml.home_selection,
HomeSettings.class.getName(),
R.drawable.ic_settings_home),
new IndexableRef(6, R.xml.sound_settings,
SoundSettings.class.getName(),
R.drawable.ic_settings_sound),
new IndexableRef(7, R.xml.display_settings,
DisplaySettings.class.getName(),
R.drawable.ic_settings_display),
new IndexableRef(7, NO_DATA_RES_ID,
WallpaperTypeSettings.class.getName(),
R.drawable.ic_settings_display),
new IndexableRef(8, R.xml.device_info_memory,
Memory.class.getName(),
R.drawable.ic_settings_storage),
new IndexableRef(9, R.xml.power_usage_summary,
PowerUsageSummary.class.getName(),
R.drawable.ic_settings_battery),
new IndexableRef(10, R.xml.user_settings,
UserSettings.class.getName(),
R.drawable.ic_settings_multiuser),
new IndexableRef(11, R.xml.location_settings,
LocationSettings.class.getName(),
R.drawable.ic_settings_location),
new IndexableRef(12, R.xml.security_settings,
SecuritySettings.class.getName(),
R.drawable.ic_settings_security),
new IndexableRef(13, R.xml.language_settings,
InputMethodAndLanguageSettings.class.getName(),
R.drawable.ic_settings_language),
new IndexableRef(14, R.xml.privacy_settings,
PrivacySettings.class.getName(),
R.drawable.ic_settings_backup),
new IndexableRef(15, R.xml.date_time_prefs,
DateTimeSettings.class.getName(),
R.drawable.ic_settings_date_time),
new IndexableRef(16, R.xml.accessibility_settings,
AccessibilitySettings.class.getName(),
R.drawable.ic_settings_accessibility),
new IndexableRef(17, R.xml.print_settings,
PrintSettingsFragment.class.getName(),
com.android.internal.R.drawable.ic_print),
new IndexableRef(18, R.xml.development_prefs,
DevelopmentSettings.class.getName(),
R.drawable.ic_settings_development),
new IndexableRef(19, R.xml.device_info_settings,
DeviceInfoSettings.class.getName(),
R.drawable.ic_settings_about),
};
@Override @Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
// Override the fragment title for Wallpaper settings // Override the fragment title for Wallpaper settings
@@ -552,7 +480,6 @@ public class SettingsActivity extends Activity
getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0)); getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
} }
Index.getInstance(this).addIndexableData(INDEXABLE_REFS);
Index.getInstance(this).update(); Index.getInstance(this).update();
mAuthenticatorHelper = new AuthenticatorHelper(); mAuthenticatorHelper = new AuthenticatorHelper();
@@ -913,22 +840,6 @@ public class SettingsActivity extends Activity
} }
} }
/**
* Switch the fragment pane to show the given preference fragment.
*
* (used for initial fragment)
*
* @param fragmentName The name of the fragment to display.
* @param args Optional arguments to supply to the fragment.
* @param validate true means that the fragment's Header needs to be validated.
* @param title The title of the fragment to display.
*/
private void switchToHeader(String fragmentName, Bundle args, boolean validate,
CharSequence title) {
setSelectedHeader(null);
switchToHeaderInner(fragmentName, args, validate, false, title);
}
/** /**
* Switch to a specific Header with taking care of validation, Title and BackStack * Switch to a specific Header with taking care of validation, Title and BackStack
*/ */

View File

@@ -24,9 +24,9 @@ import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import com.android.settings.indexer.Indexable; import android.provider.SearchIndexableResource;
import com.android.settings.indexer.IndexableData; import com.android.settings.search.Indexable;
import com.android.settings.indexer.IndexableRef; import com.android.settings.search.SearchIndexableRaw;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -64,16 +64,16 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
} }
} }
public static final IndexDataProvider INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new IndexDataProvider() { new SearchIndexProvider() {
@Override @Override
public List<IndexableRef> getRefsToIndex(Context context) { public List<SearchIndexableResource> getXmlResourcesToIndex(Context context) {
return null; return null;
} }
@Override @Override
public List<IndexableData> getRawDataToIndex(Context context) { public List<SearchIndexableRaw> getRawDataToIndex(Context context) {
final List<IndexableData> result = new ArrayList<IndexableData>(); 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);
final PackageManager pm = context.getPackageManager(); final PackageManager pm = context.getPackageManager();
@@ -82,17 +82,14 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
// Add indexable data for each of the matching activities // Add indexable data for each of the matching activities
for (ResolveInfo info : rList) { for (ResolveInfo info : rList) {
Intent prefIntent = new Intent(intent);
prefIntent.setComponent(new ComponentName(
info.activityInfo.packageName, info.activityInfo.name));
CharSequence label = info.loadLabel(pm); CharSequence label = info.loadLabel(pm);
if (label == null) label = info.activityInfo.packageName; if (label == null) label = info.activityInfo.packageName;
IndexableData data = new IndexableData(); SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = label.toString(); data.title = label.toString();
data.fragmentTitle = context.getResources().getString( data.screenTitle = context.getResources().getString(
R.string.wallpaper_settings_fragment_title); R.string.wallpaper_settings_fragment_title);
data.intentAction = intent.getAction(); data.intentAction = Intent.ACTION_SET_WALLPAPER;
data.intentTargetPackage = info.activityInfo.packageName; data.intentTargetPackage = info.activityInfo.packageName;
data.intentTargetClass = info.activityInfo.name; data.intentTargetClass = info.activityInfo.name;
result.add(data); result.add(data);

View File

@@ -17,13 +17,19 @@
package com.android.settings.dashboard; package com.android.settings.dashboard;
import android.app.Fragment; import android.app.Fragment;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -36,10 +42,14 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.indexer.Index; import com.android.settings.search.Index;
import java.util.HashMap;
public class DashboardSummary extends Fragment { public class DashboardSummary extends Fragment {
private static final String LOG_TAG = "DashboardSummary";
private EditText mEditText; private EditText mEditText;
private ListView mListView; private ListView mListView;
@@ -124,13 +134,33 @@ public class DashboardSummary extends Fragment {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
closeSoftKeyboard(); closeSoftKeyboard();
final Cursor cursor = mAdapter.mCursor; final Cursor cursor = mAdapter.mCursor;
cursor.moveToPosition(position); cursor.moveToPosition(position);
final String fragmentName = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_NAME);
final String fragmentTitle = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_TITLE);
((SettingsActivity) getActivity()).startPreferencePanel(fragmentName, null, 0, final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
fragmentTitle, null, 0); final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
if (TextUtils.isEmpty(action)) {
((SettingsActivity) getActivity()).startPreferencePanel(className, null, 0,
screenTitle, null, 0);
} else {
final Intent intent = new Intent(action);
final String targetPackage = cursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
final String targetClass = cursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
final ComponentName component =
new ComponentName(targetPackage, targetClass);
intent.setComponent(component);
}
getActivity().startActivity(intent);
}
} }
}); });
@@ -190,8 +220,10 @@ public class DashboardSummary extends Fragment {
public String title; public String title;
public String summary; public String summary;
public int iconResId; public int iconResId;
public Context context;
public SearchResult(String title, String summary, int iconResId) { public SearchResult(Context context, String title, String summary, int iconResId) {
this.context = context;
this.title = title; this.title = title;
this.summary = summary; this.summary = summary;
this.iconResId = iconResId; this.iconResId = iconResId;
@@ -203,9 +235,12 @@ public class DashboardSummary extends Fragment {
private Cursor mCursor; private Cursor mCursor;
private LayoutInflater mInflater; private LayoutInflater mInflater;
private boolean mDataValid; private boolean mDataValid;
private Context mContext;
private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
public SearchResultsAdapter(Context context) { public SearchResultsAdapter(Context context) {
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mContext = context;
mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDataValid = false; mDataValid = false;
} }
@@ -237,9 +272,29 @@ public class DashboardSummary extends Fragment {
final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE); final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY); final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON); final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
final int iconResId = final String className = mCursor.getString(
TextUtils.isEmpty(iconResStr) ? 0 : Integer.parseInt(iconResStr); Index.COLUMN_INDEX_CLASS_NAME);
return new SearchResult(title, summary, iconResId); final String packageName = mCursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
Context packageContext;
if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
packageContext = mContextMap.get(packageName);
if (packageContext == null) {
try {
packageContext = mContext.createPackageContext(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
return null;
}
mContextMap.put(packageName, packageContext);
}
} else {
packageContext = mContext;
}
final int iconResId = TextUtils.isEmpty(iconResStr) ?
R.drawable.empty_icon : Integer.parseInt(iconResStr);
return new SearchResult(packageContext, title, summary, iconResId);
} }
return null; return null;
} }
@@ -278,7 +333,15 @@ public class DashboardSummary extends Fragment {
textTitle.setText(result.title); textTitle.setText(result.title);
textSummary.setText(result.summary); textSummary.setText(result.summary);
if (result.iconResId != R.drawable.empty_icon) { if (result.iconResId != R.drawable.empty_icon) {
imageView.setImageResource(result.iconResId); final Context packageContext = result.context;
final Drawable drawable;
try {
drawable = packageContext.getDrawable(result.iconResId);
imageView.setImageDrawable(drawable);
} catch (Resources.NotFoundException nfe) {
// Not much we can do except logging
Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
}
imageView.setBackgroundResource(R.color.background_search_result_icon); imageView.setBackgroundResource(R.color.background_search_result_icon);
} else { } else {
imageView.setImageDrawable(null); imageView.setImageDrawable(null);

View File

@@ -1,46 +0,0 @@
/*
* 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.indexer;
/**
* Indexable Reference.
*
* This class wraps a set of information representing data that can be indexed for a high
* level (see {@link android.preference.PreferenceScreen}).
*
* rank: is the rank of the data (basically its order in the list of Settings)
* xmlResId: is the resource Id of a PreferenceScreen xml file
* fragmentName: is the fragment class name associated with the data
* iconRedId: is the resource Id of an icon that represents the data
*
* See {@link Indexable} and {@link IndexableData}.
*
*/
public class IndexableRef {
public int rank;
public int xmlResId;
public String fragmentName;
public int iconResId;
public IndexableRef(int rank, int dataResId, String name, int iconResId) {
this.rank = rank;
this.xmlResId = dataResId;
this.fragmentName = name;
this.iconResId = iconResId;
}
}

View File

@@ -14,16 +14,24 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.indexer; package com.android.settings.search;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.database.Cursor; import android.database.Cursor;
import android.database.DatabaseUtils; import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.provider.SearchIndexableData;
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesContract;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@@ -41,8 +49,8 @@ import java.util.Locale;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import static com.android.settings.indexer.IndexDatabaseHelper.Tables; import static com.android.settings.search.IndexDatabaseHelper.Tables;
import static com.android.settings.indexer.IndexDatabaseHelper.IndexColumns; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns;
public class Index { public class Index {
@@ -51,9 +59,12 @@ public class Index {
// Those indices should match the indices of SELECT_COLUMNS ! // Those indices should match the indices of SELECT_COLUMNS !
public static final int COLUMN_INDEX_TITLE = 1; public static final int COLUMN_INDEX_TITLE = 1;
public static final int COLUMN_INDEX_SUMMARY = 2; public static final int COLUMN_INDEX_SUMMARY = 2;
public static final int COLUMN_INDEX_FRAGMENT_NAME = 4; public static final int COLUMN_INDEX_CLASS_NAME = 4;
public static final int COLUMN_INDEX_FRAGMENT_TITLE = 5; public static final int COLUMN_INDEX_SCREEN_TITLE = 5;
public static final int COLUMN_INDEX_ICON = 7; public static final int COLUMN_INDEX_ICON = 6;
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_CLASS = 9;
// 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[] {
@@ -61,10 +72,12 @@ public class Index {
IndexColumns.DATA_TITLE, IndexColumns.DATA_TITLE,
IndexColumns.DATA_SUMMARY, IndexColumns.DATA_SUMMARY,
IndexColumns.DATA_KEYWORDS, IndexColumns.DATA_KEYWORDS,
IndexColumns.FRAGMENT_NAME, IndexColumns.CLASS_NAME,
IndexColumns.FRAGMENT_TITLE, IndexColumns.SCREEN_TITLE,
IndexColumns.INTENT, IndexColumns.ICON,
IndexColumns.ICON IndexColumns.INTENT_ACTION,
IndexColumns.INTENT_TARGET_PACKAGE,
IndexColumns.INTENT_TARGET_CLASS
}; };
private static final String[] MATCH_COLUMNS = { private static final String[] MATCH_COLUMNS = {
@@ -105,7 +118,13 @@ public class Index {
return mIsAvailable.get(); return mIsAvailable.get();
} }
public void addIndexableData(IndexableRef[] array) { public void addIndexableData(SearchIndexableData data) {
synchronized (mUpdateData) {
mUpdateData.dataToAdd.add(data);
}
}
public void addIndexableData(SearchIndexableResource[] array) {
synchronized (mUpdateData) { synchronized (mUpdateData) {
final int count = array.length; final int count = array.length;
for (int n = 0; n < count; n++) { for (int n = 0; n < count; n++) {
@@ -124,6 +143,142 @@ public class Index {
} }
public boolean update() { public boolean update() {
final Intent intent = new Intent(SearchIndexablesContract.PROVIDER_INTERFACE);
List<ResolveInfo> list =
mContext.getPackageManager().queryIntentContentProviders(intent, 0);
final int size = list.size();
for (int n = 0; n < size; n++) {
final ResolveInfo info = list.get(n);
final String authority = info.providerInfo.authority;
final String packageName = info.providerInfo.packageName;
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);
} catch (PackageManager.NameNotFoundException e) {
Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
+ Log.getStackTraceString(e));
continue;
}
}
return updateInternal();
}
private static Uri buildUriForXmlResources(String authority) {
return Uri.parse("content://" + authority + "/" +
SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
}
private static Uri buildUriForRawData(String authority) {
return Uri.parse("content://" + authority + "/" +
SearchIndexablesContract.INDEXABLES_RAW_PATH);
}
private void addIndexablesForXmlResourceUri(Context context, String packageName, Uri uri,
String[] projection) {
final ContentResolver resolver = context.getContentResolver();
final Cursor cursor = resolver.query(uri, projection,
null, null, null);
if (cursor == null) {
Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
return;
}
try {
final int count = cursor.getCount();
if (count > 0) {
while (cursor.moveToNext()) {
final int rank = cursor.getInt(0);
final int xmlResId = cursor.getInt(1);
final String className = cursor.getString(2);
final int iconResId = cursor.getInt(3);
final String action = cursor.getString(4);
final String targetPackage = cursor.getString(5);
final String targetClass = cursor.getString(6);
SearchIndexableResource sir = new SearchIndexableResource(context);
sir.rank = rank;
sir.xmlResId = xmlResId;
sir.className = className;
sir.packageName = packageName;
sir.iconResId = iconResId;
sir.intentAction = action;
sir.intentTargetPackage = targetPackage;
sir.intentTargetClass = targetClass;
addIndexableData(sir);
}
}
} finally {
cursor.close();
}
}
private void addIndexablesForRawDataUri(Context context, String packageName, Uri uri,
String[] projection) {
final ContentResolver resolver = context.getContentResolver();
final Cursor cursor = resolver.query(uri, projection,
null, null, null);
if (cursor == null) {
Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
return;
}
try {
final int count = cursor.getCount();
if (count > 0) {
while (cursor.moveToNext()) {
final int rank = cursor.getInt(0);
final String title = cursor.getString(1);
final String summary = cursor.getString(2);
final String keywords = cursor.getString(3);
final String screenTitle = cursor.getString(4);
final String className = cursor.getString(5);
final int iconResId = cursor.getInt(6);
final String action = cursor.getString(7);
final String targetPackage = cursor.getString(8);
final String targetClass = cursor.getString(9);
SearchIndexableRaw data = new SearchIndexableRaw(context);
data.rank = rank;
data.title = title;
data.summary = summary;
data.keywords = keywords;
data.screenTitle = screenTitle;
data.className = className;
data.packageName = packageName;
data.iconResId = iconResId;
data.intentAction = action;
data.intentTargetPackage = targetPackage;
data.intentTargetClass = targetClass;
addIndexableData(data);
}
}
} finally {
cursor.close();
}
}
private boolean updateInternal() {
synchronized (mUpdateData) { synchronized (mUpdateData) {
final UpdateIndexTask task = new UpdateIndexTask(); final UpdateIndexTask task = new UpdateIndexTask();
task.execute(mUpdateData); task.execute(mUpdateData);
@@ -210,11 +365,11 @@ public class Index {
* A private class to describe the update data for the Index database * A private class to describe the update data for the Index database
*/ */
private class UpdateData { private class UpdateData {
public List<IndexableRef> dataToAdd; public List<SearchIndexableData> dataToAdd;
public List<String> dataToDelete; public List<String> dataToDelete;
public UpdateData() { public UpdateData() {
dataToAdd = new ArrayList<IndexableRef>(); dataToAdd = new ArrayList<SearchIndexableData>();
dataToDelete = new ArrayList<String>(); dataToDelete = new ArrayList<String>();
} }
@@ -245,7 +400,7 @@ public class Index {
protected Boolean doInBackground(UpdateData... params) { protected Boolean doInBackground(UpdateData... params) {
boolean result = false; boolean result = false;
final List<IndexableRef> dataToAdd = params[0].dataToAdd; final List<SearchIndexableData> dataToAdd = params[0].dataToAdd;
final List<String> dataToDelete = params[0].dataToDelete; final List<String> dataToDelete = params[0].dataToDelete;
final SQLiteDatabase database = getWritableDatabase(); final SQLiteDatabase database = getWritableDatabase();
final String localeStr = Locale.getDefault().toString(); final String localeStr = Locale.getDefault().toString();
@@ -285,7 +440,7 @@ public class Index {
} }
private boolean processDataToAdd(SQLiteDatabase database, String localeStr, private boolean processDataToAdd(SQLiteDatabase database, String localeStr,
List<IndexableRef> dataToAdd) { List<SearchIndexableData> dataToAdd) {
if (isLocaleAlreadyIndexed(database, localeStr)) { if (isLocaleAlreadyIndexed(database, localeStr)) {
Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed"); Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed");
return true; return true;
@@ -296,8 +451,12 @@ public class Index {
final int count = dataToAdd.size(); final int count = dataToAdd.size();
for (int n = 0; n < count; n++) { for (int n = 0; n < count; n++) {
final IndexableRef ref = dataToAdd.get(n); final SearchIndexableData data = dataToAdd.get(n);
indexOneRef(database, localeStr, ref); if (data instanceof SearchIndexableResource) {
indexOneResource(database, localeStr, (SearchIndexableResource) data);
} else if (data instanceof SearchIndexableRaw) {
indexOneRaw(database, localeStr, (SearchIndexableRaw) data);
}
} }
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
@@ -306,53 +465,102 @@ public class Index {
return result; return result;
} }
private void indexOneRef(SQLiteDatabase database, String localeStr, IndexableRef ref) { private void indexOneResource(SQLiteDatabase database, String localeStr,
if (ref.xmlResId > 0) { SearchIndexableResource sir) {
indexFromResource(database, localeStr, ref.xmlResId, ref.fragmentName, if (sir.xmlResId > 0) {
ref.iconResId, ref.rank); indexFromResource(sir.context, database, localeStr,
} else if (!TextUtils.isEmpty(ref.fragmentName)) { sir.xmlResId, sir.className, sir.iconResId, sir.rank,
indexRawData(database, localeStr, ref); sir.intentAction, sir.intentTargetPackage, sir.intentTargetClass);
} else if (!TextUtils.isEmpty(sir.className)) {
indexFromLocalProvider(database, localeStr, sir);
} }
} }
private void indexRawData(SQLiteDatabase database, String localeStr, IndexableRef ref) { private void indexFromLocalProvider(SQLiteDatabase database, String localeStr,
SearchIndexableResource sir) {
try { try {
final Class<?> clazz = Class.forName(ref.fragmentName); final Class<?> clazz = Class.forName(sir.className);
if (Indexable.class.isAssignableFrom(clazz)) { if (Indexable.class.isAssignableFrom(clazz)) {
final Field f = clazz.getField("INDEX_DATA_PROVIDER"); final Field f = clazz.getField("SEARCH_INDEX_DATA_PROVIDER");
final Indexable.IndexDataProvider provider = final Indexable.SearchIndexProvider provider =
(Indexable.IndexDataProvider) f.get(null); (Indexable.SearchIndexProvider) f.get(null);
final List<IndexableData> data = provider.getRawDataToIndex(mContext); 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);
final int size = data.size(); // Should be the same locale as the one we are processing
for (int i = 0; i < size; i++) { if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
IndexableData raw = data.get(i); continue;
}
// Should be the same locale as the one we are processing insertOneRowWithFilteredData(database, localeStr,
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) { raw.title,
continue; raw.summary,
sir.className,
raw.screenTitle,
sir.iconResId,
sir.rank,
raw.keywords,
raw.intentAction,
raw.intentTargetPackage,
raw.intentTargetClass
);
} }
}
inserOneRowWithFilteredData(database, localeStr, final List<SearchIndexableResource> resList =
raw.title, provider.getXmlResourcesToIndex(sir.context);
raw.summary, if (resList != null) {
ref.fragmentName, final int resSize = resList.size();
raw.fragmentTitle, for (int i = 0; i < resSize; i++) {
ref.iconResId, SearchIndexableResource item = resList.get(i);
ref.rank,
raw.keywords); // 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) { } catch (ClassNotFoundException e) {
Log.e(LOG_TAG, "Cannot find class: " + ref.fragmentName, e); Log.e(LOG_TAG, "Cannot find class: " + sir.className, e);
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
Log.e(LOG_TAG, "Cannot find field 'INDEX_DATA_PROVIDER'", e); Log.e(LOG_TAG, "Cannot find field 'SEARCH_INDEX_DATA_PROVIDER'", e);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Log.e(LOG_TAG, "Illegal access to field 'INDEX_DATA_PROVIDER'", 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) {
Cursor cursor = null; Cursor cursor = null;
boolean result = false; boolean result = false;
@@ -373,11 +581,13 @@ public class Index {
return result; return result;
} }
private void indexFromResource(SQLiteDatabase database, String localeStr, int xmlResId, private void indexFromResource(Context context, SQLiteDatabase database, String localeStr,
String fragmentName, int iconResId, int rank) { int xmlResId, String fragmentName, int iconResId, int rank,
String intentAction, String intentTargetPackage, String intentTargetClass) {
XmlResourceParser parser = null; XmlResourceParser parser = null;
try { try {
parser = mContext.getResources().getXml(xmlResId); parser = context.getResources().getXml(xmlResId);
int type; int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -394,16 +604,17 @@ public class Index {
final int outerDepth = parser.getDepth(); final int outerDepth = parser.getDepth();
final AttributeSet attrs = Xml.asAttributeSet(parser); final AttributeSet attrs = Xml.asAttributeSet(parser);
final String fragmentTitle = getDataTitle(attrs); final String screenTitle = getDataTitle(context, attrs);
String title = getDataTitle(attrs); String title = getDataTitle(context, attrs);
String summary = getDataSummary(attrs); String summary = getDataSummary(context, attrs);
String keywords = getDataKeywords(attrs); String keywords = getDataKeywords(context, attrs);
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing // Insert rows for the main PreferenceScreen node. Rewrite the data for removing
// hyphens. // hyphens.
inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName, insertOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
fragmentTitle, iconResId, rank, keywords); screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -411,13 +622,14 @@ public class Index {
continue; continue;
} }
title = getDataTitle(attrs); title = getDataTitle(context, attrs);
summary = getDataSummary(attrs); summary = getDataSummary(context, attrs);
keywords = getDataKeywords(attrs); keywords = getDataKeywords(context, attrs);
// Insert rows for the child nodes of PreferenceScreen // Insert rows for the child nodes of PreferenceScreen
inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName, insertOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
fragmentTitle, iconResId, rank, keywords); screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
} }
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {
@@ -429,9 +641,10 @@ public class Index {
} }
} }
private void inserOneRowWithFilteredData(SQLiteDatabase database, String locale, private void insertOneRowWithFilteredData(SQLiteDatabase database, String locale,
String title, String summary, String fragmentName, String fragmentTitle, String title, String summary, String className, String screenTitle,
int iconResId, int rank, String keywords) { int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass) {
String updatedTitle; String updatedTitle;
if (title != null) { if (title != null) {
@@ -453,14 +666,16 @@ public class Index {
insertOneRow(database, locale, insertOneRow(database, locale,
updatedTitle, normalizedTitle, updatedSummary, normalizedSummary, updatedTitle, normalizedTitle, updatedSummary, normalizedSummary,
fragmentName, fragmentTitle, iconResId, rank, keywords); className, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass);
} }
private void insertOneRow(SQLiteDatabase database, String locale, private void insertOneRow(SQLiteDatabase database, String locale,
String updatedTitle, String normalizedTitle, String updatedTitle, String normalizedTitle,
String updatedSummary, String normalizedSummary, String updatedSummary, String normalizedSummary,
String fragmentName, String fragmentTitle, String className, String screenTitle,
int iconResId, int rank, String keywords) { int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass) {
if (TextUtils.isEmpty(updatedTitle)) { if (TextUtils.isEmpty(updatedTitle)) {
return; return;
@@ -473,9 +688,11 @@ public class Index {
values.put(IndexColumns.DATA_SUMMARY, updatedSummary); values.put(IndexColumns.DATA_SUMMARY, updatedSummary);
values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary); values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary);
values.put(IndexColumns.DATA_KEYWORDS, keywords); values.put(IndexColumns.DATA_KEYWORDS, keywords);
values.put(IndexColumns.FRAGMENT_NAME, fragmentName); values.put(IndexColumns.CLASS_NAME, className);
values.put(IndexColumns.FRAGMENT_TITLE, fragmentTitle); values.put(IndexColumns.SCREEN_TITLE, screenTitle);
values.put(IndexColumns.INTENT, ""); 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.ICON, iconResId);
database.insertOrThrow(Tables.TABLE_PREFS_INDEX, null, values); database.insertOrThrow(Tables.TABLE_PREFS_INDEX, null, values);
@@ -488,32 +705,32 @@ public class Index {
return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs); return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs);
} }
private String getDataTitle(AttributeSet attrs) { private String getDataTitle(Context context, AttributeSet attrs) {
return getData(attrs, return getData(context, attrs,
com.android.internal.R.styleable.Preference, com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_title); com.android.internal.R.styleable.Preference_title);
} }
private String getDataSummary(AttributeSet attrs) { private String getDataSummary(Context context, AttributeSet attrs) {
return getData(attrs, return getData(context, attrs,
com.android.internal.R.styleable.Preference, com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_summary); com.android.internal.R.styleable.Preference_summary);
} }
private String getDataKeywords(AttributeSet attrs) { private String getDataKeywords(Context context, AttributeSet attrs) {
return getData(attrs, return getData(context, attrs,
R.styleable.Preference, R.styleable.Preference,
R.styleable.Preference_keywords); R.styleable.Preference_keywords);
} }
private String getData(AttributeSet set, int[] attrs, int resId) { private String getData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = mContext.obtainStyledAttributes(set, attrs); final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId); final TypedValue tv = sa.peekValue(resId);
CharSequence data = null; CharSequence data = null;
if (tv != null && tv.type == TypedValue.TYPE_STRING) { if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) { if (tv.resourceId != 0) {
data = mContext.getText(tv.resourceId); data = context.getText(tv.resourceId);
} else { } else {
data = tv.string; data = tv.string;
} }

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.indexer; package com.android.settings.search;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
@@ -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 = 101; private static final int DATABASE_VERSION = 102;
public interface Tables { public interface Tables {
public static final String TABLE_PREFS_INDEX = "prefs_index"; public static final String TABLE_PREFS_INDEX = "prefs_index";
@@ -43,9 +43,11 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
public static final String DATA_SUMMARY = "data_summary"; public static final String DATA_SUMMARY = "data_summary";
public static final String DATA_SUMMARY_NORMALIZED = "data_summary_normalized"; public static final String DATA_SUMMARY_NORMALIZED = "data_summary_normalized";
public static final String DATA_KEYWORDS = "data_keywords"; public static final String DATA_KEYWORDS = "data_keywords";
public static final String FRAGMENT_NAME = "fragment_name"; public static final String CLASS_NAME = "class_name";
public static final String FRAGMENT_TITLE = "fragment_title"; public static final String SCREEN_TITLE = "screen_title";
public static final String INTENT = "intent"; public static final String INTENT_ACTION = "intent_action";
public static final String INTENT_TARGET_PACKAGE = "intent_target_package";
public static final String INTENT_TARGET_CLASS = "intent_target_class";
public static final String ICON = "icon"; public static final String ICON = "icon";
} }
@@ -70,13 +72,17 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
", " + ", " +
IndexColumns.DATA_KEYWORDS + IndexColumns.DATA_KEYWORDS +
", " + ", " +
IndexColumns.FRAGMENT_NAME + IndexColumns.SCREEN_TITLE +
", " + ", " +
IndexColumns.FRAGMENT_TITLE + IndexColumns.CLASS_NAME +
", " +
IndexColumns.INTENT +
", " + ", " +
IndexColumns.ICON + IndexColumns.ICON +
", " +
IndexColumns.INTENT_ACTION +
", " +
IndexColumns.INTENT_TARGET_PACKAGE +
", " +
IndexColumns.INTENT_TARGET_CLASS +
");"; ");";
private static final String CREATE_META_TABLE = private static final String CREATE_META_TABLE =
@@ -119,9 +125,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 (newVersion > 100) { if (oldVersion == 100 || oldVersion == 101) {
Log.w(TAG, "Detected schema version 100. " + Log.w(TAG, "Detected schema version 100 or 101. " +
"Index needs to be rebuilt for schema version 101"); "Index needs to be rebuilt for schema version 102");
// 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

@@ -14,9 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.indexer; package com.android.settings.search;
import android.content.Context; import android.content.Context;
import android.provider.SearchIndexableResource;
import java.util.List; import java.util.List;
@@ -24,29 +25,32 @@ import java.util.List;
* Interface for classes whose instances can provide data for indexing. * Interface for classes whose instances can provide data for indexing.
* *
* Classes implementing the Indexable interface must have a static field called * Classes implementing the Indexable interface must have a static field called
* <code>INDEX_DATA_PROVIDER</code>, which is an object implementing the * <code>SEARCH_INDEX_DATA_PROVIDER</code>, which is an object implementing the
* {@link Indexable.IndexDataProvider Indexable.IndexDataProvider} interface. * {@link Indexable.SearchIndexProvider} interface.
* *
* See {@link IndexableRef} and {@link IndexableData}. * See {@link android.provider.SearchIndexableResource} and {@link SearchIndexableRaw}.
* *
*/ */
public interface Indexable { public interface Indexable {
public interface IndexDataProvider { public interface SearchIndexProvider {
/** /**
* Return a list of references for indexing. See {@link IndexableRef} * Return a list of references for indexing.
*
* See {@link android.provider.SearchIndexableResource}
* *
* @param context the context * @param context the context
* @return a list of {@link IndexableRef} references. Can be null. * @return a list of {@link android.provider.SearchIndexableResource} references.
* Can be null.
*/ */
List<IndexableRef> getRefsToIndex(Context context); List<SearchIndexableResource> getXmlResourcesToIndex(Context context);
/** /**
* Return a list of raw data for indexing. See {@link IndexableData} * Return a list of raw data for indexing. See {@link SearchIndexableRaw}
* *
* @param context the context * @param context the context
* @return a list of {@link IndexableData} references. Can be null. * @return a list of {@link SearchIndexableRaw} references. Can be null.
*/ */
List<IndexableData> getRawDataToIndex(Context context); List<SearchIndexableRaw> getRawDataToIndex(Context context);
} }
} }

View File

@@ -14,32 +14,27 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.indexer; package com.android.settings.search;
import java.util.Locale; import android.content.Context;
import android.provider.SearchIndexableData;
/** /**
* Indexable Data. * Indexable raw data for Search.
* *
* This is the raw data used by the Indexer and should match its data model. * This is the raw data used by the Indexer and should match its data model.
* *
* See {@link Indexable} and {@link IndexableRef}. * See {@link Indexable} and {@link android.provider.SearchIndexableResource}.
*/ */
public class IndexableData { public class SearchIndexableRaw extends SearchIndexableData {
public Locale locale;
public String title; public String title;
public String summary; public String summary;
public String keywords; public String keywords;
public String intentAction; public String screenTitle;
public String intentTargetPackage;
public String intentTargetClass;
public String fragmentTitle; public SearchIndexableRaw(Context context) {
super(context);
public IndexableData() {
locale = Locale.getDefault();
} }
} }

View File

@@ -0,0 +1,144 @@
/*
* 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.database.Cursor;
import android.database.MatrixCursor;
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesProvider;
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 static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
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, R.xml.bluetooth_settings,
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
public boolean onCreate() {
return true;
}
@Override
public Cursor queryXmlResources(String[] projection) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
final int count = INDEXABLE_REFS.length;
for (int n = 0; n < count; n++) {
Object[] ref = new Object[7];
ref[0] = INDEXABLE_REFS[n].rank;
ref[1] = INDEXABLE_REFS[n].xmlResId;
ref[2] = INDEXABLE_REFS[n].className;
ref[3] = INDEXABLE_REFS[n].iconResId;
ref[4] = null; // intent action
ref[5] = null; // intent target package
ref[6] = null; // intent target class
cursor.addRow(ref);
}
return cursor;
}
@Override
public Cursor queryRawData(String[] projection) {
Cursor result = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
return result;
}
}

View File

@@ -20,12 +20,12 @@ import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
import static android.os.UserManager.DISALLOW_CONFIG_WIFI; import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.provider.SearchIndexableResource;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment; import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.indexer.Indexable; import com.android.settings.search.Indexable;
import com.android.settings.indexer.IndexableData; import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.indexer.IndexableRef;
import com.android.settings.wifi.p2p.WifiP2pSettings; import com.android.settings.wifi.p2p.WifiP2pSettings;
import android.app.ActionBar; import android.app.ActionBar;
@@ -1165,22 +1165,22 @@ public class WifiSettings extends RestrictedSettingsFragment
} }
} }
public static final Indexable.IndexDataProvider INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new Indexable.IndexDataProvider() { new SearchIndexProvider() {
@Override @Override
public List<IndexableRef> getRefsToIndex(Context context) { public List<SearchIndexableResource> getXmlResourcesToIndex(Context context) {
return null; return null;
} }
@Override @Override
public List<IndexableData> getRawDataToIndex(Context context) { public List<SearchIndexableRaw> getRawDataToIndex(Context context) {
final List<IndexableData> result = new ArrayList<IndexableData>(); final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
final Resources res = context.getResources(); final Resources res = context.getResources();
// Add fragment title // Add fragment title
IndexableData data = new IndexableData(); SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = res.getString(R.string.wifi_settings); data.title = res.getString(R.string.wifi_settings);
data.fragmentTitle = res.getString(R.string.wifi_settings); data.screenTitle = res.getString(R.string.wifi_settings);
result.add(data); result.add(data);
// Add available Wi-Fi access points // Add available Wi-Fi access points
@@ -1191,9 +1191,9 @@ public class WifiSettings extends RestrictedSettingsFragment
for (AccessPoint accessPoint : accessPoints) { for (AccessPoint accessPoint : accessPoints) {
// We are indexing only the saved Wi-Fi networks. // We are indexing only the saved Wi-Fi networks.
if (accessPoint.getConfig() == null) continue; if (accessPoint.getConfig() == null) continue;
data = new IndexableData(); data = new SearchIndexableRaw(context);
data.title = accessPoint.getTitle().toString(); data.title = accessPoint.getTitle().toString();
data.fragmentTitle = res.getString(R.string.wifi_settings); data.screenTitle = res.getString(R.string.wifi_settings);
result.add(data); result.add(data);
} }