Move search indexing into a separate class
Step 2 in refactoring DatabaseIndexingManager. This step moves the insertion of data into the database into a new class. This removes the remaining bulk of the code outside of DIM, but it does not fix the actual issue with the indexing code. The indexing code still chains functions together to insert data into the database at the end of the functions. It is exceedingly hard to read, and hard to track down bugs. I would like the converter to eventually return a list of IndexData objects, which lets us dissociate the database from the data collection. I.e. we can store the database in the Search app, and just pass IndexData objects via IPC.Fixing this requires more of a refactor, and will be done in a subsquent CL. Bug: 33577327 Test: make RunSettingsRoboTests Test: Took a database dump before and after change, and they were the same. Cool. Change-Id: Ia9bb815657b76f6cb9163014e746ec5eb6db8c5e
This commit is contained in:
@@ -22,68 +22,33 @@ import static com.android.settings.search.DatabaseResultLoader
|
||||
.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE;
|
||||
import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY;
|
||||
import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_RANK;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns
|
||||
.DATA_SUMMARY_OFF_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns
|
||||
.DATA_SUMMARY_ON_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.provider.SearchIndexableData;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.SearchIndexablesContract;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
import com.android.settings.search.indexing.IndexableDataCollector;
|
||||
import com.android.settings.search.indexing.IndexDataConverter;
|
||||
import com.android.settings.search.indexing.PreIndexData;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import com.android.settings.search.indexing.PreIndexDataCollector;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -91,7 +56,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* Consumes the SearchIndexableProvider content providers.
|
||||
* Updates the Resource, Raw Data and non-indexable data for Search.
|
||||
*
|
||||
* TODO this class needs to be refactored by moving most of its methods into controllers
|
||||
* TODO(b/33577327) this class needs to be refactored by moving most of its methods into controllers
|
||||
*/
|
||||
public class DatabaseIndexingManager {
|
||||
|
||||
@@ -103,14 +68,10 @@ public class DatabaseIndexingManager {
|
||||
public static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
|
||||
"SEARCH_INDEX_DATA_PROVIDER";
|
||||
|
||||
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
|
||||
private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
|
||||
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
|
||||
|
||||
@VisibleForTesting
|
||||
final AtomicBoolean mIsIndexingComplete = new AtomicBoolean(false);
|
||||
|
||||
private IndexableDataCollector mCollector;
|
||||
private PreIndexDataCollector mCollector;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@@ -143,8 +104,8 @@ public class DatabaseIndexingManager {
|
||||
final String providerVersionedNames =
|
||||
IndexDatabaseHelper.buildProviderVersionedNames(providers);
|
||||
|
||||
final boolean isFullIndex = isFullIndex(mContext, localeStr,
|
||||
fingerprint, providerVersionedNames);
|
||||
final boolean isFullIndex = isFullIndex(mContext, localeStr, fingerprint,
|
||||
providerVersionedNames);
|
||||
|
||||
if (isFullIndex) {
|
||||
rebuildDatabase();
|
||||
@@ -174,7 +135,7 @@ public class DatabaseIndexingManager {
|
||||
@VisibleForTesting
|
||||
PreIndexData getIndexDataFromProviders(List<ResolveInfo> providers, boolean isFullIndex) {
|
||||
if (mCollector == null) {
|
||||
mCollector = new IndexableDataCollector(mContext);
|
||||
mCollector = new PreIndexDataCollector(mContext);
|
||||
}
|
||||
return mCollector.collectIndexableData(providers, isFullIndex);
|
||||
}
|
||||
@@ -191,7 +152,7 @@ public class DatabaseIndexingManager {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isFullIndex(Context context, String locale, String fingerprint,
|
||||
String providerVersionedNames) {
|
||||
String providerVersionedNames) {
|
||||
final boolean isLocaleIndexed = IndexDatabaseHelper.isLocaleAlreadyIndexed(context, locale);
|
||||
final boolean isBuildIndexed = IndexDatabaseHelper.isBuildIndexed(context, fingerprint);
|
||||
final boolean areProvidersIndexed = IndexDatabaseHelper
|
||||
@@ -222,7 +183,6 @@ public class DatabaseIndexingManager {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void updateDatabase(PreIndexData indexData, boolean needsReindexing, String localeStr) {
|
||||
final List<SearchIndexableData> dataToUpdate = indexData.dataToUpdate;
|
||||
final Map<String, Set<String>> nonIndexableKeys = indexData.nonIndexableKeys;
|
||||
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
@@ -235,9 +195,7 @@ public class DatabaseIndexingManager {
|
||||
database.beginTransaction();
|
||||
|
||||
// Add new data from Providers at initial index time, or inserted later.
|
||||
if (dataToUpdate.size() > 0) {
|
||||
addDataToDatabase(database, localeStr, dataToUpdate, nonIndexableKeys);
|
||||
}
|
||||
addIndaxebleDataToDatabase(database, localeStr, indexData);
|
||||
|
||||
// Only check for non-indexable key updates after initial index.
|
||||
// Enabled state with non-indexable keys is checked when items are first inserted.
|
||||
@@ -251,32 +209,14 @@ public class DatabaseIndexingManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts {@link SearchIndexableData} into the database.
|
||||
*
|
||||
* @param database where the data will be inserted.
|
||||
* @param localeStr is the locale of the data to be inserted.
|
||||
* @param dataToUpdate is a {@link List} of the data to be inserted.
|
||||
* @param nonIndexableKeys is a {@link Map} from Package Name to a {@link Set} of keys which
|
||||
* identify search results which should not be surfaced.
|
||||
*/
|
||||
|
||||
@VisibleForTesting
|
||||
void addDataToDatabase(SQLiteDatabase database, String localeStr,
|
||||
List<SearchIndexableData> dataToUpdate, Map<String, Set<String>> nonIndexableKeys) {
|
||||
final long current = System.currentTimeMillis();
|
||||
|
||||
for (SearchIndexableData data : dataToUpdate) {
|
||||
try {
|
||||
indexOneSearchIndexableData(database, localeStr, data, nonIndexableKeys);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data)
|
||||
+ " for locale: " + localeStr, e);
|
||||
}
|
||||
void addIndaxebleDataToDatabase(SQLiteDatabase database, String locale, PreIndexData data) {
|
||||
if (data.dataToUpdate.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
|
||||
(now - current) + " millis");
|
||||
IndexDataConverter manager = new IndexDataConverter(mContext, database);
|
||||
manager.addDataToDatabase(locale, data.dataToUpdate, data.nonIndexableKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,646 +328,6 @@ public class DatabaseIndexingManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
|
||||
SearchIndexableData data, Map<String, Set<String>> nonIndexableKeys) {
|
||||
if (data instanceof SearchIndexableResource) {
|
||||
indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
|
||||
} else if (data instanceof SearchIndexableRaw) {
|
||||
indexOneRaw(database, localeStr, (SearchIndexableRaw) data, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
|
||||
private void indexOneRaw(SQLiteDatabase database, String localeStr,
|
||||
SearchIndexableRaw raw, Map<String, Set<String>> nonIndexableKeysFromResource) {
|
||||
// Should be the same locale as the one we are processing
|
||||
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> packageKeys = nonIndexableKeysFromResource.get(raw.intentTargetPackage);
|
||||
boolean enabled = raw.enabled;
|
||||
|
||||
if (packageKeys != null && packageKeys.contains(raw.key)) {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setEntries(raw.entries)
|
||||
.setClassName(raw.className)
|
||||
.setScreenTitle(raw.screenTitle)
|
||||
.setIconResId(raw.iconResId)
|
||||
.setRank(raw.rank)
|
||||
.setIntentAction(raw.intentAction)
|
||||
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||
.setIntentTargetClass(raw.intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(raw.key)
|
||||
.setUserId(raw.userId);
|
||||
|
||||
updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn, raw.summaryOff,
|
||||
raw.keywords);
|
||||
}
|
||||
|
||||
private void indexOneResource(SQLiteDatabase database, String localeStr,
|
||||
SearchIndexableResource sir, Map<String, Set<String>> nonIndexableKeysFromResource) {
|
||||
|
||||
if (sir == null) {
|
||||
Log.e(LOG_TAG, "Cannot index a null resource!");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> nonIndexableKeys = new ArrayList<String>();
|
||||
|
||||
if (sir.xmlResId > SearchIndexableResources.NO_DATA_RES_ID) {
|
||||
Set<String> resNonIndexableKeys = nonIndexableKeysFromResource.get(sir.packageName);
|
||||
if (resNonIndexableKeys != null && resNonIndexableKeys.size() > 0) {
|
||||
nonIndexableKeys.addAll(resNonIndexableKeys);
|
||||
}
|
||||
|
||||
indexFromResource(database, localeStr, sir, nonIndexableKeys);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(sir.className)) {
|
||||
Log.w(LOG_TAG, "Cannot index an empty Search Provider name!");
|
||||
return;
|
||||
}
|
||||
|
||||
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className);
|
||||
if (clazz == null) {
|
||||
Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className +
|
||||
"' should implement the " + Indexable.class.getName() + " interface!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Will be non null only for a Local provider implementing a
|
||||
// SEARCH_INDEX_DATA_PROVIDER field
|
||||
final Indexable.SearchIndexProvider provider =
|
||||
DatabaseIndexingUtils.getSearchIndexProvider(clazz);
|
||||
if (provider != null) {
|
||||
List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context);
|
||||
if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) {
|
||||
nonIndexableKeys.addAll(providerNonIndexableKeys);
|
||||
}
|
||||
|
||||
indexFromProvider(database, localeStr, provider, sir, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexFromResource(SQLiteDatabase database, String localeStr,
|
||||
SearchIndexableResource sir, List<String> nonIndexableKeys) {
|
||||
final Context context = sir.context;
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = context.getResources().getXml(sir.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 (!NODE_NAME_PREFERENCE_SCREEN.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 = XmlParserUtils.getDataTitle(context, attrs);
|
||||
String key = XmlParserUtils.getDataKey(context, attrs);
|
||||
|
||||
String title;
|
||||
String headerTitle;
|
||||
String summary;
|
||||
String headerSummary;
|
||||
String keywords;
|
||||
String headerKeywords;
|
||||
String childFragment;
|
||||
@DrawableRes
|
||||
int iconResId;
|
||||
ResultPayload payload;
|
||||
boolean enabled;
|
||||
final String fragmentName = sir.className;
|
||||
final int rank = sir.rank;
|
||||
final String intentAction = sir.intentAction;
|
||||
final String intentTargetPackage = sir.intentTargetPackage;
|
||||
final String intentTargetClass = sir.intentTargetClass;
|
||||
|
||||
Map<String, PreferenceControllerMixin> controllerUriMap = null;
|
||||
|
||||
if (fragmentName != null) {
|
||||
controllerUriMap = DatabaseIndexingUtils
|
||||
.getPreferenceControllerUriMap(fragmentName, context);
|
||||
}
|
||||
|
||||
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
||||
// hyphens.
|
||||
|
||||
headerTitle = XmlParserUtils.getDataTitle(context, attrs);
|
||||
headerSummary = XmlParserUtils.getDataSummary(context, attrs);
|
||||
headerKeywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||
enabled = !nonIndexableKeys.contains(key);
|
||||
|
||||
// TODO: Set payload type for header results
|
||||
DatabaseRow.Builder headerBuilder = new DatabaseRow.Builder();
|
||||
headerBuilder.setLocale(localeStr)
|
||||
.setEntries(null)
|
||||
.setClassName(fragmentName)
|
||||
.setScreenTitle(screenTitle)
|
||||
.setRank(rank)
|
||||
.setIntentAction(intentAction)
|
||||
.setIntentTargetPackage(intentTargetPackage)
|
||||
.setIntentTargetClass(intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(key)
|
||||
.setUserId(-1 /* default user id */);
|
||||
|
||||
// Flag for XML headers which a child element's title.
|
||||
boolean isHeaderUnique = true;
|
||||
DatabaseRow.Builder builder;
|
||||
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeName = parser.getName();
|
||||
|
||||
title = XmlParserUtils.getDataTitle(context, attrs);
|
||||
key = XmlParserUtils.getDataKey(context, attrs);
|
||||
enabled = !nonIndexableKeys.contains(key);
|
||||
keywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||
iconResId = XmlParserUtils.getDataIcon(context, attrs);
|
||||
|
||||
if (isHeaderUnique && TextUtils.equals(headerTitle, title)) {
|
||||
isHeaderUnique = false;
|
||||
}
|
||||
|
||||
builder = new DatabaseRow.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setClassName(fragmentName)
|
||||
.setScreenTitle(screenTitle)
|
||||
.setIconResId(iconResId)
|
||||
.setRank(rank)
|
||||
.setIntentAction(intentAction)
|
||||
.setIntentTargetPackage(intentTargetPackage)
|
||||
.setIntentTargetClass(intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(key)
|
||||
.setUserId(-1 /* default user id */);
|
||||
|
||||
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
|
||||
summary = XmlParserUtils.getDataSummary(context, attrs);
|
||||
|
||||
String entries = null;
|
||||
|
||||
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
|
||||
entries = XmlParserUtils.getDataEntries(context, attrs);
|
||||
}
|
||||
|
||||
// TODO (b/62254931) index primitives instead of payload
|
||||
payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
|
||||
childFragment = XmlParserUtils.getDataChildFragment(context, attrs);
|
||||
|
||||
builder.setEntries(entries)
|
||||
.setChildClassName(childFragment)
|
||||
.setPayload(payload);
|
||||
|
||||
// Insert rows for the child nodes of PreferenceScreen
|
||||
updateOneRowWithFilteredData(database, builder, title, summary,
|
||||
null /* summary off */, keywords);
|
||||
} else {
|
||||
String summaryOn = XmlParserUtils.getDataSummaryOn(context, attrs);
|
||||
String summaryOff = XmlParserUtils.getDataSummaryOff(context, attrs);
|
||||
|
||||
if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
|
||||
summaryOn = XmlParserUtils.getDataSummary(context, attrs);
|
||||
}
|
||||
|
||||
updateOneRowWithFilteredData(database, builder, title, summaryOn, summaryOff,
|
||||
keywords);
|
||||
}
|
||||
}
|
||||
|
||||
// The xml header's title does not match the title of one of the child settings.
|
||||
if (isHeaderUnique) {
|
||||
updateOneRowWithFilteredData(database, headerBuilder, headerTitle, headerSummary,
|
||||
null /* summary off */, headerKeywords);
|
||||
}
|
||||
} 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 indexFromProvider(SQLiteDatabase database, String localeStr,
|
||||
Indexable.SearchIndexProvider provider, SearchIndexableResource sir,
|
||||
List<String> nonIndexableKeys) {
|
||||
|
||||
final String className = sir.className;
|
||||
final String intentAction = sir.intentAction;
|
||||
final String intentTargetPackage = sir.intentTargetPackage;
|
||||
|
||||
if (provider == null) {
|
||||
Log.w(LOG_TAG, "Cannot find provider: " + className);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(mContext,
|
||||
true /* 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;
|
||||
}
|
||||
boolean enabled = !nonIndexableKeys.contains(raw.key);
|
||||
|
||||
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setEntries(raw.entries)
|
||||
.setClassName(className)
|
||||
.setScreenTitle(raw.screenTitle)
|
||||
.setIconResId(raw.iconResId)
|
||||
.setIntentAction(raw.intentAction)
|
||||
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||
.setIntentTargetClass(raw.intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(raw.key)
|
||||
.setUserId(raw.userId);
|
||||
|
||||
updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn,
|
||||
raw.summaryOff, raw.keywords);
|
||||
}
|
||||
}
|
||||
|
||||
final List<SearchIndexableResource> resList =
|
||||
provider.getXmlResourcesToIndex(mContext, true);
|
||||
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;
|
||||
}
|
||||
|
||||
item.className = TextUtils.isEmpty(item.className)
|
||||
? className
|
||||
: item.className;
|
||||
item.intentAction = TextUtils.isEmpty(item.intentAction)
|
||||
? intentAction
|
||||
: item.intentAction;
|
||||
item.intentTargetPackage = TextUtils.isEmpty(item.intentTargetPackage)
|
||||
? intentTargetPackage
|
||||
: item.intentTargetPackage;
|
||||
|
||||
indexFromResource(database, localeStr, item, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOneRowWithFilteredData(SQLiteDatabase database, DatabaseRow.Builder builder,
|
||||
String title, String summaryOn, String summaryOff, String keywords) {
|
||||
|
||||
final String updatedTitle = DatabaseIndexingUtils.normalizeHyphen(title);
|
||||
final String updatedSummaryOn = DatabaseIndexingUtils.normalizeHyphen(summaryOn);
|
||||
final String updatedSummaryOff = DatabaseIndexingUtils.normalizeHyphen(summaryOff);
|
||||
|
||||
final String normalizedTitle = DatabaseIndexingUtils.normalizeString(updatedTitle);
|
||||
final String normalizedSummaryOn = DatabaseIndexingUtils.normalizeString(updatedSummaryOn);
|
||||
final String normalizedSummaryOff = DatabaseIndexingUtils
|
||||
.normalizeString(updatedSummaryOff);
|
||||
|
||||
final String spaceDelimitedKeywords = DatabaseIndexingUtils.normalizeKeywords(keywords);
|
||||
|
||||
builder.setUpdatedTitle(updatedTitle)
|
||||
.setUpdatedSummaryOn(updatedSummaryOn)
|
||||
.setUpdatedSummaryOff(updatedSummaryOff)
|
||||
.setNormalizedTitle(normalizedTitle)
|
||||
.setNormalizedSummaryOn(normalizedSummaryOn)
|
||||
.setNormalizedSummaryOff(normalizedSummaryOff)
|
||||
.setSpaceDelimitedKeywords(spaceDelimitedKeywords);
|
||||
|
||||
updateOneRow(database, builder.build(mContext));
|
||||
}
|
||||
|
||||
private void updateOneRow(SQLiteDatabase database, DatabaseRow row) {
|
||||
|
||||
if (TextUtils.isEmpty(row.updatedTitle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, row.getDocId());
|
||||
values.put(LOCALE, row.locale);
|
||||
values.put(DATA_RANK, row.rank);
|
||||
values.put(DATA_TITLE, row.updatedTitle);
|
||||
values.put(DATA_TITLE_NORMALIZED, row.normalizedTitle);
|
||||
values.put(DATA_SUMMARY_ON, row.updatedSummaryOn);
|
||||
values.put(DATA_SUMMARY_ON_NORMALIZED, row.normalizedSummaryOn);
|
||||
values.put(DATA_SUMMARY_OFF, row.updatedSummaryOff);
|
||||
values.put(DATA_SUMMARY_OFF_NORMALIZED, row.normalizedSummaryOff);
|
||||
values.put(DATA_ENTRIES, row.entries);
|
||||
values.put(DATA_KEYWORDS, row.spaceDelimitedKeywords);
|
||||
values.put(CLASS_NAME, row.className);
|
||||
values.put(SCREEN_TITLE, row.screenTitle);
|
||||
values.put(INTENT_ACTION, row.intentAction);
|
||||
values.put(INTENT_TARGET_PACKAGE, row.intentTargetPackage);
|
||||
values.put(INTENT_TARGET_CLASS, row.intentTargetClass);
|
||||
values.put(ICON, row.iconResId);
|
||||
values.put(ENABLED, row.enabled);
|
||||
values.put(DATA_KEY_REF, row.key);
|
||||
values.put(USER_ID, row.userId);
|
||||
values.put(PAYLOAD_TYPE, row.payloadType);
|
||||
values.put(PAYLOAD, row.payload);
|
||||
|
||||
database.replaceOrThrow(TABLE_PREFS_INDEX, null, values);
|
||||
|
||||
if (!TextUtils.isEmpty(row.className) && !TextUtils.isEmpty(row.childClassName)) {
|
||||
ContentValues siteMapPair = new ContentValues();
|
||||
final int pairDocId = Objects.hash(row.className, row.childClassName);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, row.className);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, row.screenTitle);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, row.childClassName);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, row.updatedTitle);
|
||||
|
||||
database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null, siteMapPair);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DatabaseRow {
|
||||
public final String locale;
|
||||
public final String updatedTitle;
|
||||
public final String normalizedTitle;
|
||||
public final String updatedSummaryOn;
|
||||
public final String normalizedSummaryOn;
|
||||
public final String updatedSummaryOff;
|
||||
public final String normalizedSummaryOff;
|
||||
public final String entries;
|
||||
public final String className;
|
||||
public final String childClassName;
|
||||
public final String screenTitle;
|
||||
public final int iconResId;
|
||||
public final int rank;
|
||||
public final String spaceDelimitedKeywords;
|
||||
public final String intentAction;
|
||||
public final String intentTargetPackage;
|
||||
public final String intentTargetClass;
|
||||
public final boolean enabled;
|
||||
public final String key;
|
||||
public final int userId;
|
||||
public final int payloadType;
|
||||
public final byte[] payload;
|
||||
|
||||
private DatabaseRow(Builder builder) {
|
||||
locale = builder.mLocale;
|
||||
updatedTitle = builder.mUpdatedTitle;
|
||||
normalizedTitle = builder.mNormalizedTitle;
|
||||
updatedSummaryOn = builder.mUpdatedSummaryOn;
|
||||
normalizedSummaryOn = builder.mNormalizedSummaryOn;
|
||||
updatedSummaryOff = builder.mUpdatedSummaryOff;
|
||||
normalizedSummaryOff = builder.mNormalizedSummaryOff;
|
||||
entries = builder.mEntries;
|
||||
className = builder.mClassName;
|
||||
childClassName = builder.mChildClassName;
|
||||
screenTitle = builder.mScreenTitle;
|
||||
iconResId = builder.mIconResId;
|
||||
rank = builder.mRank;
|
||||
spaceDelimitedKeywords = builder.mSpaceDelimitedKeywords;
|
||||
intentAction = builder.mIntentAction;
|
||||
intentTargetPackage = builder.mIntentTargetPackage;
|
||||
intentTargetClass = builder.mIntentTargetClass;
|
||||
enabled = builder.mEnabled;
|
||||
key = builder.mKey;
|
||||
userId = builder.mUserId;
|
||||
payloadType = builder.mPayloadType;
|
||||
payload = builder.mPayload != null ? ResultPayloadUtils.marshall(builder.mPayload)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the doc id for this row.
|
||||
*/
|
||||
public int getDocId() {
|
||||
// Eventually we want all DocIds to be the data_reference key. For settings values,
|
||||
// this will be preference keys, and for non-settings they should be unique.
|
||||
return TextUtils.isEmpty(key)
|
||||
? Objects.hash(updatedTitle, className, screenTitle, intentTargetClass)
|
||||
: key.hashCode();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String mLocale;
|
||||
private String mUpdatedTitle;
|
||||
private String mNormalizedTitle;
|
||||
private String mUpdatedSummaryOn;
|
||||
private String mNormalizedSummaryOn;
|
||||
private String mUpdatedSummaryOff;
|
||||
private String mNormalizedSummaryOff;
|
||||
private String mEntries;
|
||||
private String mClassName;
|
||||
private String mChildClassName;
|
||||
private String mScreenTitle;
|
||||
private int mIconResId;
|
||||
private int mRank;
|
||||
private String mSpaceDelimitedKeywords;
|
||||
private String mIntentAction;
|
||||
private String mIntentTargetPackage;
|
||||
private String mIntentTargetClass;
|
||||
private boolean mEnabled;
|
||||
private String mKey;
|
||||
private int mUserId;
|
||||
@ResultPayload.PayloadType
|
||||
private int mPayloadType;
|
||||
private ResultPayload mPayload;
|
||||
|
||||
public Builder setLocale(String locale) {
|
||||
mLocale = locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedTitle(String updatedTitle) {
|
||||
mUpdatedTitle = updatedTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedTitle(String normalizedTitle) {
|
||||
mNormalizedTitle = normalizedTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedSummaryOn(String updatedSummaryOn) {
|
||||
mUpdatedSummaryOn = updatedSummaryOn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedSummaryOn(String normalizedSummaryOn) {
|
||||
mNormalizedSummaryOn = normalizedSummaryOn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedSummaryOff(String updatedSummaryOff) {
|
||||
mUpdatedSummaryOff = updatedSummaryOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedSummaryOff(String normalizedSummaryOff) {
|
||||
this.mNormalizedSummaryOff = normalizedSummaryOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEntries(String entries) {
|
||||
mEntries = entries;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setClassName(String className) {
|
||||
mClassName = className;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setChildClassName(String childClassName) {
|
||||
mChildClassName = childClassName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setScreenTitle(String screenTitle) {
|
||||
mScreenTitle = screenTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIconResId(int iconResId) {
|
||||
mIconResId = iconResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRank(int rank) {
|
||||
mRank = rank;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSpaceDelimitedKeywords(String spaceDelimitedKeywords) {
|
||||
mSpaceDelimitedKeywords = spaceDelimitedKeywords;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentAction(String intentAction) {
|
||||
mIntentAction = intentAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentTargetPackage(String intentTargetPackage) {
|
||||
mIntentTargetPackage = intentTargetPackage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentTargetClass(String intentTargetClass) {
|
||||
mIntentTargetClass = intentTargetClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKey(String key) {
|
||||
mKey = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUserId(int userId) {
|
||||
mUserId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPayload(ResultPayload payload) {
|
||||
mPayload = payload;
|
||||
|
||||
if (mPayload != null) {
|
||||
setPayloadType(mPayload.getType());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload type is added when a Payload is added to the Builder in {setPayload}
|
||||
*
|
||||
* @param payloadType PayloadType
|
||||
* @return The Builder
|
||||
*/
|
||||
private Builder setPayloadType(@ResultPayload.PayloadType int payloadType) {
|
||||
mPayloadType = payloadType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds intent to inline payloads, or creates an Intent Payload as a fallback if the
|
||||
* payload is null.
|
||||
*/
|
||||
private void setIntent(Context context) {
|
||||
if (mPayload != null) {
|
||||
return;
|
||||
}
|
||||
final Intent intent = buildIntent(context);
|
||||
mPayload = new ResultPayload(intent);
|
||||
mPayloadType = ResultPayload.PayloadType.INTENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Intent payload to builder.
|
||||
*/
|
||||
private Intent buildIntent(Context context) {
|
||||
final Intent intent;
|
||||
|
||||
boolean isEmptyIntentAction = TextUtils.isEmpty(mIntentAction);
|
||||
// No intent action is set, or the intent action is for a subsetting.
|
||||
if (isEmptyIntentAction
|
||||
|| (!isEmptyIntentAction && TextUtils.equals(mIntentTargetPackage,
|
||||
SearchIndexableResources.SUBSETTING_TARGET_PACKAGE))) {
|
||||
// Action is null, we will launch it as a sub-setting
|
||||
intent = DatabaseIndexingUtils.buildSubsettingIntent(context, mClassName, mKey,
|
||||
mScreenTitle);
|
||||
} else {
|
||||
intent = new Intent(mIntentAction);
|
||||
final String targetClass = mIntentTargetClass;
|
||||
if (!TextUtils.isEmpty(mIntentTargetPackage)
|
||||
&& !TextUtils.isEmpty(targetClass)) {
|
||||
final ComponentName component = new ComponentName(mIntentTargetPackage,
|
||||
targetClass);
|
||||
intent.setComponent(component);
|
||||
}
|
||||
intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, mKey);
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
public DatabaseRow build(Context context) {
|
||||
setIntent(context);
|
||||
return new DatabaseRow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IndexingTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
@VisibleForTesting
|
||||
|
@@ -174,18 +174,18 @@ public class DatabaseIndexingUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
static String normalizeHyphen(String input) {
|
||||
public static String normalizeHyphen(String input) {
|
||||
return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
|
||||
}
|
||||
|
||||
static String normalizeString(String input) {
|
||||
public static String normalizeString(String input) {
|
||||
final String nohyphen = (input != null) ? input.replaceAll(HYPHEN, EMPTY) : EMPTY;
|
||||
final String normalized = Normalizer.normalize(nohyphen, Normalizer.Form.NFD);
|
||||
|
||||
return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase();
|
||||
}
|
||||
|
||||
static String normalizeKeywords(String input) {
|
||||
public static String normalizeKeywords(String input) {
|
||||
return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
|
||||
}
|
||||
}
|
||||
|
@@ -35,8 +35,7 @@ public abstract class InlinePayload extends ResultPayload {
|
||||
/**
|
||||
* Defines the key to access and store the Setting the inline result represents.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
final String mSettingKey;
|
||||
private final String mSettingKey;
|
||||
|
||||
/**
|
||||
* Defines where the Setting is stored.
|
||||
@@ -154,4 +153,8 @@ public abstract class InlinePayload extends ResultPayload {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return mSettingKey;
|
||||
}
|
||||
}
|
287
src/com/android/settings/search/indexing/IndexData.java
Normal file
287
src/com/android/settings/search/indexing/IndexData.java
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search.indexing;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.search.DatabaseIndexingUtils;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.ResultPayloadUtils;
|
||||
import com.android.settings.search.SearchIndexableResources;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Data class representing a single row in the Setting Search results database.
|
||||
*/
|
||||
public class IndexData {
|
||||
public final String locale;
|
||||
public final String updatedTitle;
|
||||
public final String normalizedTitle;
|
||||
public final String updatedSummaryOn;
|
||||
public final String normalizedSummaryOn;
|
||||
public final String updatedSummaryOff;
|
||||
public final String normalizedSummaryOff;
|
||||
public final String entries;
|
||||
public final String className;
|
||||
public final String childClassName;
|
||||
public final String screenTitle;
|
||||
public final int iconResId;
|
||||
public final int rank;
|
||||
public final String spaceDelimitedKeywords;
|
||||
public final String intentAction;
|
||||
public final String intentTargetPackage;
|
||||
public final String intentTargetClass;
|
||||
public final boolean enabled;
|
||||
public final String key;
|
||||
public final int userId;
|
||||
public final int payloadType;
|
||||
public final byte[] payload;
|
||||
|
||||
private IndexData(Builder builder) {
|
||||
locale = builder.mLocale;
|
||||
updatedTitle = builder.mUpdatedTitle;
|
||||
normalizedTitle = builder.mNormalizedTitle;
|
||||
updatedSummaryOn = builder.mUpdatedSummaryOn;
|
||||
normalizedSummaryOn = builder.mNormalizedSummaryOn;
|
||||
updatedSummaryOff = builder.mUpdatedSummaryOff;
|
||||
normalizedSummaryOff = builder.mNormalizedSummaryOff;
|
||||
entries = builder.mEntries;
|
||||
className = builder.mClassName;
|
||||
childClassName = builder.mChildClassName;
|
||||
screenTitle = builder.mScreenTitle;
|
||||
iconResId = builder.mIconResId;
|
||||
rank = builder.mRank;
|
||||
spaceDelimitedKeywords = builder.mSpaceDelimitedKeywords;
|
||||
intentAction = builder.mIntentAction;
|
||||
intentTargetPackage = builder.mIntentTargetPackage;
|
||||
intentTargetClass = builder.mIntentTargetClass;
|
||||
enabled = builder.mEnabled;
|
||||
key = builder.mKey;
|
||||
userId = builder.mUserId;
|
||||
payloadType = builder.mPayloadType;
|
||||
payload = builder.mPayload != null ? ResultPayloadUtils.marshall(builder.mPayload)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the doc id for this row.
|
||||
*/
|
||||
public int getDocId() {
|
||||
// Eventually we want all DocIds to be the data_reference key. For settings values,
|
||||
// this will be preference keys, and for non-settings they should be unique.
|
||||
return TextUtils.isEmpty(key)
|
||||
? Objects.hash(updatedTitle, className, screenTitle, intentTargetClass)
|
||||
: key.hashCode();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String mLocale;
|
||||
private String mUpdatedTitle;
|
||||
private String mNormalizedTitle;
|
||||
private String mUpdatedSummaryOn;
|
||||
private String mNormalizedSummaryOn;
|
||||
private String mUpdatedSummaryOff;
|
||||
private String mNormalizedSummaryOff;
|
||||
private String mEntries;
|
||||
private String mClassName;
|
||||
private String mChildClassName;
|
||||
private String mScreenTitle;
|
||||
private int mIconResId;
|
||||
private int mRank;
|
||||
private String mSpaceDelimitedKeywords;
|
||||
private String mIntentAction;
|
||||
private String mIntentTargetPackage;
|
||||
private String mIntentTargetClass;
|
||||
private boolean mEnabled;
|
||||
private String mKey;
|
||||
private int mUserId;
|
||||
@ResultPayload.PayloadType
|
||||
private int mPayloadType;
|
||||
private ResultPayload mPayload;
|
||||
|
||||
public Builder setLocale(String locale) {
|
||||
mLocale = locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedTitle(String updatedTitle) {
|
||||
mUpdatedTitle = updatedTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedTitle(String normalizedTitle) {
|
||||
mNormalizedTitle = normalizedTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedSummaryOn(String updatedSummaryOn) {
|
||||
mUpdatedSummaryOn = updatedSummaryOn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedSummaryOn(String normalizedSummaryOn) {
|
||||
mNormalizedSummaryOn = normalizedSummaryOn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUpdatedSummaryOff(String updatedSummaryOff) {
|
||||
mUpdatedSummaryOff = updatedSummaryOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNormalizedSummaryOff(String normalizedSummaryOff) {
|
||||
this.mNormalizedSummaryOff = normalizedSummaryOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEntries(String entries) {
|
||||
mEntries = entries;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setClassName(String className) {
|
||||
mClassName = className;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setChildClassName(String childClassName) {
|
||||
mChildClassName = childClassName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setScreenTitle(String screenTitle) {
|
||||
mScreenTitle = screenTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIconResId(int iconResId) {
|
||||
mIconResId = iconResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRank(int rank) {
|
||||
mRank = rank;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSpaceDelimitedKeywords(String spaceDelimitedKeywords) {
|
||||
mSpaceDelimitedKeywords = spaceDelimitedKeywords;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentAction(String intentAction) {
|
||||
mIntentAction = intentAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentTargetPackage(String intentTargetPackage) {
|
||||
mIntentTargetPackage = intentTargetPackage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setIntentTargetClass(String intentTargetClass) {
|
||||
mIntentTargetClass = intentTargetClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKey(String key) {
|
||||
mKey = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUserId(int userId) {
|
||||
mUserId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPayload(ResultPayload payload) {
|
||||
mPayload = payload;
|
||||
|
||||
if (mPayload != null) {
|
||||
setPayloadType(mPayload.getType());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload type is added when a Payload is added to the Builder in {setPayload}
|
||||
*
|
||||
* @param payloadType PayloadType
|
||||
* @return The Builder
|
||||
*/
|
||||
private Builder setPayloadType(@ResultPayload.PayloadType int payloadType) {
|
||||
mPayloadType = payloadType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds intent to inline payloads, or creates an Intent Payload as a fallback if the
|
||||
* payload is null.
|
||||
*/
|
||||
private void setIntent(Context context) {
|
||||
if (mPayload != null) {
|
||||
return;
|
||||
}
|
||||
final Intent intent = buildIntent(context);
|
||||
mPayload = new ResultPayload(intent);
|
||||
mPayloadType = ResultPayload.PayloadType.INTENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Intent payload to builder.
|
||||
*/
|
||||
private Intent buildIntent(Context context) {
|
||||
final Intent intent;
|
||||
|
||||
boolean isEmptyIntentAction = TextUtils.isEmpty(mIntentAction);
|
||||
// No intent action is set, or the intent action is for a subsetting.
|
||||
if (isEmptyIntentAction
|
||||
|| (!isEmptyIntentAction && TextUtils.equals(mIntentTargetPackage,
|
||||
SearchIndexableResources.SUBSETTING_TARGET_PACKAGE))) {
|
||||
// Action is null, we will launch it as a sub-setting
|
||||
intent = DatabaseIndexingUtils.buildSubsettingIntent(context, mClassName, mKey,
|
||||
mScreenTitle);
|
||||
} else {
|
||||
intent = new Intent(mIntentAction);
|
||||
final String targetClass = mIntentTargetClass;
|
||||
if (!TextUtils.isEmpty(mIntentTargetPackage)
|
||||
&& !TextUtils.isEmpty(targetClass)) {
|
||||
final ComponentName component = new ComponentName(mIntentTargetPackage,
|
||||
targetClass);
|
||||
intent.setComponent(component);
|
||||
}
|
||||
intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, mKey);
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
public IndexData build(Context context) {
|
||||
setIntent(context);
|
||||
return new IndexData(this);
|
||||
}
|
||||
}
|
||||
}
|
510
src/com/android/settings/search/indexing/IndexDataConverter.java
Normal file
510
src/com/android/settings/search/indexing/IndexDataConverter.java
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search.indexing;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.provider.SearchIndexableData;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
import com.android.settings.search.DatabaseIndexingUtils;
|
||||
import com.android.settings.search.IndexDatabaseHelper;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settings.search.SearchIndexableResources;
|
||||
import com.android.settings.search.XmlParserUtils;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEY_REF;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_RANK;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.LOCALE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.SCREEN_TITLE;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_ID;
|
||||
import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX;
|
||||
|
||||
/**
|
||||
* Helper class to convert {@link PreIndexData} to {@link IndexData}.
|
||||
*
|
||||
* TODO (b/33577327) This is just copied straight from DatabaseIndexingManager. But it's still ugly.
|
||||
* TODO This is currently a long chain of method calls. It needs to be broken up.
|
||||
* TODO but for the sake of easy code reviews, that will happen later.
|
||||
*/
|
||||
public class IndexDataConverter {
|
||||
|
||||
private static final String LOG_TAG = "IndexDataConverter";
|
||||
|
||||
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
|
||||
private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
|
||||
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
public IndexDataConverter(Context context, SQLiteDatabase database) {
|
||||
mContext = context;
|
||||
mDb = database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts {@link SearchIndexableData} into the database.
|
||||
*
|
||||
* @param localeStr is the locale of the data to be inserted.
|
||||
* @param dataToUpdate is a {@link List} of the data to be inserted.
|
||||
* @param nonIndexableKeys is a {@link Map} from Package Name to a {@link Set} of keys which
|
||||
* identify search results which should not be surfaced.
|
||||
*/
|
||||
public void addDataToDatabase(String localeStr, List<SearchIndexableData> dataToUpdate,
|
||||
Map<String, Set<String>> nonIndexableKeys) {
|
||||
final long current = System.currentTimeMillis();
|
||||
|
||||
for (SearchIndexableData data : dataToUpdate) {
|
||||
try {
|
||||
indexOneSearchIndexableData(localeStr, data, nonIndexableKeys);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data)
|
||||
+ " for locale: " + localeStr, e);
|
||||
}
|
||||
}
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
|
||||
(now - current) + " millis");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexOneSearchIndexableData(String localeStr, SearchIndexableData data,
|
||||
Map<String, Set<String>> nonIndexableKeys) {
|
||||
if (data instanceof SearchIndexableResource) {
|
||||
indexOneResource(localeStr, (SearchIndexableResource) data, nonIndexableKeys);
|
||||
} else if (data instanceof SearchIndexableRaw) {
|
||||
indexOneRaw(localeStr, (SearchIndexableRaw) data, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexOneRaw(String localeStr, SearchIndexableRaw raw, Map<String,
|
||||
Set<String>> nonIndexableKeysFromResource) {
|
||||
// Should be the same locale as the one we are processing
|
||||
if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> packageKeys = nonIndexableKeysFromResource.get(raw.intentTargetPackage);
|
||||
boolean enabled = raw.enabled;
|
||||
|
||||
if (packageKeys != null && packageKeys.contains(raw.key)) {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
IndexData.Builder builder = new IndexData.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setEntries(raw.entries)
|
||||
.setClassName(raw.className)
|
||||
.setScreenTitle(raw.screenTitle)
|
||||
.setIconResId(raw.iconResId)
|
||||
.setRank(raw.rank)
|
||||
.setIntentAction(raw.intentAction)
|
||||
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||
.setIntentTargetClass(raw.intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(raw.key)
|
||||
.setUserId(raw.userId);
|
||||
|
||||
updateOneRowWithFilteredData(builder, raw.title, raw.summaryOn, raw.summaryOff,
|
||||
raw.keywords);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexOneResource(String localeStr, SearchIndexableResource sir,
|
||||
Map<String, Set<String>> nonIndexableKeysFromResource) {
|
||||
|
||||
if (sir == null) {
|
||||
Log.e(LOG_TAG, "Cannot index a null resource!");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> nonIndexableKeys = new ArrayList<>();
|
||||
|
||||
if (sir.xmlResId > SearchIndexableResources.NO_DATA_RES_ID) {
|
||||
Set<String> resNonIndexableKeys = nonIndexableKeysFromResource.get(sir.packageName);
|
||||
if (resNonIndexableKeys != null && resNonIndexableKeys.size() > 0) {
|
||||
nonIndexableKeys.addAll(resNonIndexableKeys);
|
||||
}
|
||||
|
||||
indexFromResource(localeStr, sir, nonIndexableKeys);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(sir.className)) {
|
||||
Log.w(LOG_TAG, "Cannot index an empty Search Provider name!");
|
||||
return;
|
||||
}
|
||||
|
||||
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className);
|
||||
if (clazz == null) {
|
||||
Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className +
|
||||
"' should implement the " + Indexable.class.getName() + " interface!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Will be non null only for a Local provider implementing a
|
||||
// SEARCH_INDEX_DATA_PROVIDER field
|
||||
final Indexable.SearchIndexProvider provider =
|
||||
DatabaseIndexingUtils.getSearchIndexProvider(clazz);
|
||||
if (provider != null) {
|
||||
List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context);
|
||||
if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) {
|
||||
nonIndexableKeys.addAll(providerNonIndexableKeys);
|
||||
}
|
||||
|
||||
indexFromProvider(localeStr, provider, sir, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexFromResource(String localeStr, SearchIndexableResource sir,
|
||||
List<String> nonIndexableKeys) {
|
||||
final Context context = sir.context;
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = context.getResources().getXml(sir.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 (!NODE_NAME_PREFERENCE_SCREEN.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 = XmlParserUtils.getDataTitle(context, attrs);
|
||||
String key = XmlParserUtils.getDataKey(context, attrs);
|
||||
|
||||
String title;
|
||||
String headerTitle;
|
||||
String summary;
|
||||
String headerSummary;
|
||||
String keywords;
|
||||
String headerKeywords;
|
||||
String childFragment;
|
||||
@DrawableRes
|
||||
int iconResId;
|
||||
ResultPayload payload;
|
||||
boolean enabled;
|
||||
final String fragmentName = sir.className;
|
||||
final int rank = sir.rank;
|
||||
final String intentAction = sir.intentAction;
|
||||
final String intentTargetPackage = sir.intentTargetPackage;
|
||||
final String intentTargetClass = sir.intentTargetClass;
|
||||
|
||||
Map<String, PreferenceControllerMixin> controllerUriMap = null;
|
||||
|
||||
if (fragmentName != null) {
|
||||
controllerUriMap = DatabaseIndexingUtils
|
||||
.getPreferenceControllerUriMap(fragmentName, context);
|
||||
}
|
||||
|
||||
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
||||
// hyphens.
|
||||
|
||||
headerTitle = XmlParserUtils.getDataTitle(context, attrs);
|
||||
headerSummary = XmlParserUtils.getDataSummary(context, attrs);
|
||||
headerKeywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||
enabled = !nonIndexableKeys.contains(key);
|
||||
|
||||
// TODO: Set payload type for header results
|
||||
IndexData.Builder headerBuilder = new IndexData.Builder();
|
||||
headerBuilder.setLocale(localeStr)
|
||||
.setEntries(null)
|
||||
.setClassName(fragmentName)
|
||||
.setScreenTitle(screenTitle)
|
||||
.setRank(rank)
|
||||
.setIntentAction(intentAction)
|
||||
.setIntentTargetPackage(intentTargetPackage)
|
||||
.setIntentTargetClass(intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(key)
|
||||
.setUserId(-1 /* default user id */);
|
||||
|
||||
// Flag for XML headers which a child element's title.
|
||||
boolean isHeaderUnique = true;
|
||||
IndexData.Builder builder;
|
||||
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeName = parser.getName();
|
||||
|
||||
title = XmlParserUtils.getDataTitle(context, attrs);
|
||||
key = XmlParserUtils.getDataKey(context, attrs);
|
||||
enabled = !nonIndexableKeys.contains(key);
|
||||
keywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||
iconResId = XmlParserUtils.getDataIcon(context, attrs);
|
||||
|
||||
if (isHeaderUnique && TextUtils.equals(headerTitle, title)) {
|
||||
isHeaderUnique = false;
|
||||
}
|
||||
|
||||
builder = new IndexData.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setClassName(fragmentName)
|
||||
.setScreenTitle(screenTitle)
|
||||
.setIconResId(iconResId)
|
||||
.setRank(rank)
|
||||
.setIntentAction(intentAction)
|
||||
.setIntentTargetPackage(intentTargetPackage)
|
||||
.setIntentTargetClass(intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(key)
|
||||
.setUserId(-1 /* default user id */);
|
||||
|
||||
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
|
||||
summary = XmlParserUtils.getDataSummary(context, attrs);
|
||||
|
||||
String entries = null;
|
||||
|
||||
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
|
||||
entries = XmlParserUtils.getDataEntries(context, attrs);
|
||||
}
|
||||
|
||||
// TODO (b/62254931) index primitives instead of payload
|
||||
payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
|
||||
childFragment = XmlParserUtils.getDataChildFragment(context, attrs);
|
||||
|
||||
builder.setEntries(entries)
|
||||
.setChildClassName(childFragment)
|
||||
.setPayload(payload);
|
||||
|
||||
// Insert rows for the child nodes of PreferenceScreen
|
||||
updateOneRowWithFilteredData(builder, title, summary,
|
||||
null /* summary off */, keywords);
|
||||
} else {
|
||||
String summaryOn = XmlParserUtils.getDataSummaryOn(context, attrs);
|
||||
String summaryOff = XmlParserUtils.getDataSummaryOff(context, attrs);
|
||||
|
||||
if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
|
||||
summaryOn = XmlParserUtils.getDataSummary(context, attrs);
|
||||
}
|
||||
|
||||
updateOneRowWithFilteredData(builder, title, summaryOn, summaryOff,
|
||||
keywords);
|
||||
}
|
||||
}
|
||||
|
||||
// The xml header's title does not match the title of one of the child settings.
|
||||
if (isHeaderUnique) {
|
||||
updateOneRowWithFilteredData(headerBuilder, headerTitle, headerSummary,
|
||||
null /* summary off */, headerKeywords);
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void indexFromProvider(String localeStr, Indexable.SearchIndexProvider provider,
|
||||
SearchIndexableResource sir, List<String> nonIndexableKeys) {
|
||||
|
||||
final String className = sir.className;
|
||||
final String intentAction = sir.intentAction;
|
||||
final String intentTargetPackage = sir.intentTargetPackage;
|
||||
|
||||
if (provider == null) {
|
||||
Log.w(LOG_TAG, "Cannot find provider: " + className);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(mContext,
|
||||
true /* 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;
|
||||
}
|
||||
boolean enabled = !nonIndexableKeys.contains(raw.key);
|
||||
|
||||
IndexData.Builder builder = new IndexData.Builder();
|
||||
builder.setLocale(localeStr)
|
||||
.setEntries(raw.entries)
|
||||
.setClassName(className)
|
||||
.setScreenTitle(raw.screenTitle)
|
||||
.setIconResId(raw.iconResId)
|
||||
.setIntentAction(raw.intentAction)
|
||||
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||
.setIntentTargetClass(raw.intentTargetClass)
|
||||
.setEnabled(enabled)
|
||||
.setKey(raw.key)
|
||||
.setUserId(raw.userId);
|
||||
|
||||
updateOneRowWithFilteredData(builder, raw.title, raw.summaryOn, raw.summaryOff,
|
||||
raw.keywords);
|
||||
}
|
||||
}
|
||||
|
||||
final List<SearchIndexableResource> resList =
|
||||
provider.getXmlResourcesToIndex(mContext, true);
|
||||
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;
|
||||
}
|
||||
|
||||
item.className = TextUtils.isEmpty(item.className)
|
||||
? className
|
||||
: item.className;
|
||||
item.intentAction = TextUtils.isEmpty(item.intentAction)
|
||||
? intentAction
|
||||
: item.intentAction;
|
||||
item.intentTargetPackage = TextUtils.isEmpty(item.intentTargetPackage)
|
||||
? intentTargetPackage
|
||||
: item.intentTargetPackage;
|
||||
|
||||
indexFromResource(localeStr, item, nonIndexableKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateOneRowWithFilteredData(IndexData.Builder builder,
|
||||
String title, String summaryOn, String summaryOff, String keywords) {
|
||||
|
||||
final String updatedTitle = DatabaseIndexingUtils.normalizeHyphen(title);
|
||||
final String updatedSummaryOn = DatabaseIndexingUtils.normalizeHyphen(summaryOn);
|
||||
final String updatedSummaryOff = DatabaseIndexingUtils.normalizeHyphen(summaryOff);
|
||||
|
||||
final String normalizedTitle = DatabaseIndexingUtils.normalizeString(updatedTitle);
|
||||
final String normalizedSummaryOn = DatabaseIndexingUtils.normalizeString(updatedSummaryOn);
|
||||
final String normalizedSummaryOff = DatabaseIndexingUtils
|
||||
.normalizeString(updatedSummaryOff);
|
||||
|
||||
final String spaceDelimitedKeywords = DatabaseIndexingUtils.normalizeKeywords(keywords);
|
||||
|
||||
builder.setUpdatedTitle(updatedTitle)
|
||||
.setUpdatedSummaryOn(updatedSummaryOn)
|
||||
.setUpdatedSummaryOff(updatedSummaryOff)
|
||||
.setNormalizedTitle(normalizedTitle)
|
||||
.setNormalizedSummaryOn(normalizedSummaryOn)
|
||||
.setNormalizedSummaryOff(normalizedSummaryOff)
|
||||
.setSpaceDelimitedKeywords(spaceDelimitedKeywords);
|
||||
|
||||
updateOneRow(builder.build(mContext));
|
||||
}
|
||||
|
||||
private void updateOneRow(IndexData row) {
|
||||
if (TextUtils.isEmpty(row.updatedTitle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, row.getDocId());
|
||||
values.put(LOCALE, row.locale);
|
||||
values.put(DATA_RANK, row.rank);
|
||||
values.put(DATA_TITLE, row.updatedTitle);
|
||||
values.put(DATA_TITLE_NORMALIZED, row.normalizedTitle);
|
||||
values.put(DATA_SUMMARY_ON, row.updatedSummaryOn);
|
||||
values.put(DATA_SUMMARY_ON_NORMALIZED, row.normalizedSummaryOn);
|
||||
values.put(DATA_SUMMARY_OFF, row.updatedSummaryOff);
|
||||
values.put(DATA_SUMMARY_OFF_NORMALIZED, row.normalizedSummaryOff);
|
||||
values.put(DATA_ENTRIES, row.entries);
|
||||
values.put(DATA_KEYWORDS, row.spaceDelimitedKeywords);
|
||||
values.put(CLASS_NAME, row.className);
|
||||
values.put(SCREEN_TITLE, row.screenTitle);
|
||||
values.put(INTENT_ACTION, row.intentAction);
|
||||
values.put(INTENT_TARGET_PACKAGE, row.intentTargetPackage);
|
||||
values.put(INTENT_TARGET_CLASS, row.intentTargetClass);
|
||||
values.put(ICON, row.iconResId);
|
||||
values.put(ENABLED, row.enabled);
|
||||
values.put(DATA_KEY_REF, row.key);
|
||||
values.put(USER_ID, row.userId);
|
||||
values.put(PAYLOAD_TYPE, row.payloadType);
|
||||
values.put(PAYLOAD, row.payload);
|
||||
|
||||
mDb.replaceOrThrow(TABLE_PREFS_INDEX, null, values);
|
||||
|
||||
if (!TextUtils.isEmpty(row.className) && !TextUtils.isEmpty(row.childClassName)) {
|
||||
ContentValues siteMapPair = new ContentValues();
|
||||
final int pairDocId = Objects.hash(row.className, row.childClassName);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, row.className);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, row.screenTitle);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, row.childClassName);
|
||||
siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, row.updatedTitle);
|
||||
|
||||
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null, siteMapPair);
|
||||
}
|
||||
}
|
||||
}
|
@@ -65,7 +65,7 @@ import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INT
|
||||
/**
|
||||
* Collects all data from {@link android.provider.SearchIndexablesProvider} to be indexed.
|
||||
*/
|
||||
public class IndexableDataCollector {
|
||||
public class PreIndexDataCollector {
|
||||
|
||||
private static final String TAG = "IndexableDataCollector";
|
||||
|
||||
@@ -78,7 +78,7 @@ public class IndexableDataCollector {
|
||||
|
||||
private PreIndexData mIndexData;
|
||||
|
||||
public IndexableDataCollector(Context context) {
|
||||
public PreIndexDataCollector(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
@@ -243,7 +243,7 @@ public class CursorToSearchResultConverterTest {
|
||||
for (SearchResult result : results) {
|
||||
final InlineSwitchPayload newPayload = (InlineSwitchPayload) result.payload;
|
||||
final Intent rebuiltIntent = newPayload.getIntent();
|
||||
assertThat(newPayload.mSettingKey).isEqualTo(uri);
|
||||
assertThat(newPayload.getKey()).isEqualTo(uri);
|
||||
assertThat(newPayload.getType()).isEqualTo(type);
|
||||
assertThat(newPayload.mSettingSource).isEqualTo(source);
|
||||
assertThat(newPayload.isStandard()).isTrue();
|
||||
|
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyList;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
@@ -42,10 +41,8 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Build;
|
||||
import android.provider.SearchIndexableData;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.indexing.PreIndexData;
|
||||
import com.android.settings.testutils.DatabaseTestUtils;
|
||||
@@ -65,7 +62,6 @@ import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -149,7 +145,7 @@ public class DatabaseIndexingManagerTest {
|
||||
Cursor dbCursor = mDb.query("prefs_index", null, null, null, null, null, null);
|
||||
List<String> columnNames = new ArrayList<>(Arrays.asList(dbCursor.getColumnNames()));
|
||||
// Note that docid is not included.
|
||||
List<String> expColumnNames = new ArrayList<>(Arrays.asList(new String[]{
|
||||
List<String> expColumnNames = Arrays.asList(
|
||||
"locale",
|
||||
"data_rank",
|
||||
"data_title",
|
||||
@@ -171,187 +167,13 @@ public class DatabaseIndexingManagerTest {
|
||||
"user_id",
|
||||
"payload_type",
|
||||
"payload"
|
||||
}));
|
||||
);
|
||||
// Prevent database schema regressions
|
||||
assertThat(columnNames).containsAllIn(expColumnNames);
|
||||
}
|
||||
|
||||
// Tests for the flow: IndexOneRaw -> UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_rowInserted() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, raw,
|
||||
new HashMap<>()/* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_nonIndexableKey_resultIsDisabled() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
Map<String, Set<String>> niks = new HashMap<>();
|
||||
Set<String> keys = new HashSet<>();
|
||||
keys.add(raw.key);
|
||||
niks.put(raw.intentTargetPackage, keys);
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, raw, niks);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_rowMatches() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, raw,
|
||||
new HashMap<>()/* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(raw.rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo(updatedTitle);
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo(normalizedTitle);
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(updatedSummaryOn);
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(normalizedSummaryOn);
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(6)).isEqualTo(updatedSummaryOff);
|
||||
// Summary off normalized
|
||||
assertThat(cursor.getString(7)).isEqualTo(normalizedSummaryOff);
|
||||
// Entries
|
||||
assertThat(cursor.getString(8)).isEqualTo(raw.entries);
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(spaceDelimittedKeywords);
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo(raw.screenTitle);
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(raw.className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(raw.iconResId);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(raw.intentAction);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(raw.intentTargetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(raw.intentTargetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(raw.enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNotNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(raw.userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_mismatchedLocale_noRowInserted() {
|
||||
SearchIndexableRaw raw = getFakeRaw("ca-fr");
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
// Tests for the flow: IndexOneResource -> IndexFromResource ->
|
||||
// UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||
|
||||
@Test
|
||||
public void testNullResource_NothingInserted() {
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, null /* searchIndexableResource */,
|
||||
new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_RowsInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.display_settings);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(17);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_withNIKs_rowsInsertedDisabled() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.display_settings);
|
||||
// Only add 2 of 16 items to be disabled.
|
||||
String[] keys = {"brightness", "wallpaper"};
|
||||
Map<String, Set<String>> niks = getNonIndexableKeys(keys);
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, niks);
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(2);
|
||||
cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResourceHeader_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(1);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("App info");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("app info");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo("Manage apps, set up quick launch shortcuts");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo("manage apps, set up quick launch shortcuts");
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(0);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("applications_settings");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_withChildFragment_shouldUpdateSiteMapDb() {
|
||||
// FIXME: This test was failing. (count = 6 at the end)
|
||||
@@ -377,376 +199,6 @@ public class DatabaseIndexingManagerTest {
|
||||
// assertThat(count).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_customSetting_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
final String prefTitle =
|
||||
mContext.getString(R.string.fingerprint_swipe_for_notifications_title);
|
||||
final String prefSummary =
|
||||
mContext.getString(R.string.fingerprint_swipe_for_notifications_summary);
|
||||
final String keywords = mContext.getString(R.string.keywords_gesture);
|
||||
Cursor cursor = mDb.rawQuery(
|
||||
"SELECT * FROM prefs_index where data_title='" + prefTitle + "'", null);
|
||||
cursor.moveToFirst();
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo(prefTitle);
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo(prefTitle.toLowerCase());
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(prefSummary);
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(prefSummary.toLowerCase());
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(keywords);
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo(
|
||||
mContext.getString(R.string.fingerprint_swipe_for_notifications_title));
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("gesture_swipe_down_fingerprint");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_checkboxPreference_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
|
||||
/* Should return 6 results, with the following titles:
|
||||
* Advanced Settings, Apps, Manage Apps, Preferred install location, Running Services
|
||||
*/
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Advanced settings");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("advanced settings");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo("Enable more settings options");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo("enable more settings options");
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(6)).isEqualTo("Enable more settings options");
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(7)).isEqualTo("enable more settings options");
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("toggle_advanced_settings");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_listPreference_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(3);
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Preferred install location");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("preferred install location");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(
|
||||
"Change the preferred installation location for new apps");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(
|
||||
"change the preferred installation location for new apps");
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isEqualTo("Internal device storage|Removable SD card|" +
|
||||
"Let the system decide|");
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("app_install_location");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_iconAddedFromXml() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.connected_devices);
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isNotEqualTo(noIcon);
|
||||
}
|
||||
|
||||
// Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
|
||||
// UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_rowInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
|
||||
resource.xmlResId = 0;
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_rowMatches() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
|
||||
resource.xmlResId = 0;
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(0);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Display size");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("display size");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEmpty();
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEmpty();
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo("display density screen zoom scale scaling");
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("Display size");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11))
|
||||
.isEqualTo("com.android.settings.display.ScreenZoomSettings");
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isNull();
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isNull();
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isNull();
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_resourceRowInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(0);
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_resourceRowMatches() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(0);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Display size");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("display size");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEmpty();
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEmpty();
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(
|
||||
"display density screen zoom scale scaling");
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("Display size");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11))
|
||||
.isEqualTo("com.android.settings.display.ScreenZoomSettings");
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isNull();
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isNull();
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isNull();
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_disabledResource_rowsInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||
new HashMap<String, Set<String>>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResource_withTitleAndSettingName_titleNotInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
|
||||
mManager.indexFromResource(mDb, localeStr, resource, new ArrayList<String>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE" +
|
||||
" enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_nonSubsettingIntent() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
String fakeAction = "fake_action";
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
resource.intentAction = fakeAction;
|
||||
resource.intentTargetPackage = SearchIndexableResources.SUBSETTING_TARGET_PACKAGE;
|
||||
|
||||
mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(fakeAction);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14))
|
||||
.isEqualTo(SearchIndexableResources.SUBSETTING_TARGET_PACKAGE);
|
||||
}
|
||||
|
||||
// Test new public indexing flow
|
||||
|
||||
@Test
|
||||
@@ -824,14 +276,6 @@ public class DatabaseIndexingManagerTest {
|
||||
assertThat(IndexDatabaseHelper.isBuildIndexed(mContext, Build.FINGERPRINT)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullUpdatedDatabase_noData_addDataToDatabaseNotCalled() {
|
||||
PreIndexData emptydata = new PreIndexData();
|
||||
mManager.updateDatabase(emptydata, true /* isFullIndex */, localeStr);
|
||||
verify(mManager, times(0)).addDataToDatabase(any(SQLiteDatabase.class), anyString(),
|
||||
anyList(), anyMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocaleUpdated_afterIndexing_localeNotAdded() {
|
||||
PreIndexData emptydata = new PreIndexData();
|
||||
@@ -1013,28 +457,6 @@ public class DatabaseIndexingManagerTest {
|
||||
return data;
|
||||
}
|
||||
|
||||
private SearchIndexableResource getFakeResource(int xml) {
|
||||
SearchIndexableResource sir = new SearchIndexableResource(mContext);
|
||||
sir.rank = rank;
|
||||
sir.xmlResId = xml;
|
||||
sir.className = className;
|
||||
sir.packageName = packageName;
|
||||
sir.iconResId = iconResId;
|
||||
sir.intentAction = action;
|
||||
sir.intentTargetPackage = targetPackage;
|
||||
sir.intentTargetClass = targetClass;
|
||||
sir.enabled = enabled;
|
||||
return sir;
|
||||
}
|
||||
|
||||
private Map<String, Set<String>> getNonIndexableKeys(String[] keys) {
|
||||
Map<String, Set<String>> niks = new HashMap<>();
|
||||
Set<String> keysList = new HashSet<>();
|
||||
keysList.addAll(Arrays.asList(keys));
|
||||
niks.put(packageName, keysList);
|
||||
return niks;
|
||||
}
|
||||
|
||||
private void insertSpecialCase(String specialCase, boolean enabled, String key) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, specialCase.hashCode());
|
||||
|
@@ -40,7 +40,7 @@ public class InlineListPayloadTest {
|
||||
intent, true /* isAvailable */, 1 /* numOptions */, 1 /* default */);
|
||||
|
||||
final Intent retainedIntent = payload.getIntent();
|
||||
assertThat(payload.mSettingKey).isEqualTo(uri);
|
||||
assertThat(payload.getKey()).isEqualTo(uri);
|
||||
assertThat(payload.getType()).isEqualTo(type);
|
||||
assertThat(payload.mSettingSource).isEqualTo(source);
|
||||
assertThat(payload.getAvailability()).isEqualTo(ResultPayload.Availability.AVAILABLE);
|
||||
@@ -69,7 +69,7 @@ public class InlineListPayloadTest {
|
||||
.CREATOR.createFromParcel(parcel);
|
||||
|
||||
final Intent builtIntent = payload.getIntent();
|
||||
assertThat(payload.mSettingKey).isEqualTo(uri);
|
||||
assertThat(payload.getKey()).isEqualTo(uri);
|
||||
assertThat(payload.getType()).isEqualTo(type);
|
||||
assertThat(payload.mSettingSource).isEqualTo(source);
|
||||
assertThat(payload.getAvailability()).isEqualTo(ResultPayload.Availability.AVAILABLE);
|
||||
|
@@ -64,7 +64,7 @@ public class InlineSwitchPayloadTest {
|
||||
InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, 1, intent, true,
|
||||
1 /* default */);
|
||||
final Intent retainedIntent = payload.getIntent();
|
||||
assertThat(payload.mSettingKey).isEqualTo(uri);
|
||||
assertThat(payload.getKey()).isEqualTo(uri);
|
||||
assertThat(payload.getType()).isEqualTo(type);
|
||||
assertThat(payload.mSettingSource).isEqualTo(source);
|
||||
assertThat(payload.isStandard()).isTrue();
|
||||
@@ -93,7 +93,7 @@ public class InlineSwitchPayloadTest {
|
||||
InlineSwitchPayload payload = InlineSwitchPayload.CREATOR.createFromParcel(parcel);
|
||||
|
||||
final Intent builtIntent = payload.getIntent();
|
||||
assertThat(payload.mSettingKey).isEqualTo(uri);
|
||||
assertThat(payload.getKey()).isEqualTo(uri);
|
||||
assertThat(payload.getType()).isEqualTo(type);
|
||||
assertThat(payload.mSettingSource).isEqualTo(source);
|
||||
assertThat(payload.isStandard()).isTrue();
|
||||
|
@@ -0,0 +1,689 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search.indexing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.IndexDatabaseHelper;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.ResultPayloadUtils;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settings.search.SearchIndexableResources;
|
||||
import com.android.settings.testutils.DatabaseTestUtils;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.android.settings.R.*;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class IndexDataConverterTest {
|
||||
|
||||
private final String localeStr = "en_US";
|
||||
|
||||
private final int rank = 8;
|
||||
private final String title = "title\u2011title";
|
||||
private final String updatedTitle = "title-title";
|
||||
private final String normalizedTitle = "titletitle";
|
||||
private final String summaryOn = "summary\u2011on";
|
||||
private final String updatedSummaryOn = "summary-on";
|
||||
private final String normalizedSummaryOn = "summaryon";
|
||||
private final String summaryOff = "summary\u2011off";
|
||||
private final String updatedSummaryOff = "summary-off";
|
||||
private final String normalizedSummaryOff = "summaryoff";
|
||||
private final String entries = "entries";
|
||||
private final String keywords = "keywords, keywordss, keywordsss";
|
||||
private final String spaceDelimittedKeywords = "keywords keywordss keywordsss";
|
||||
private final String screenTitle = "screen title";
|
||||
private final String className = "class name";
|
||||
private final int iconResId = 0xff;
|
||||
private final int noIcon = 0;
|
||||
private final String action = "action";
|
||||
private final String targetPackage = "target package";
|
||||
private final String targetClass = "target class";
|
||||
private final String packageName = "package name";
|
||||
private final String key = "key";
|
||||
private final int userId = -1;
|
||||
private final boolean enabled = true;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private IndexDataConverter mConverter;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
||||
mConverter = spy(new IndexDataConverter(mContext, mDb));
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
DatabaseTestUtils.clearDb(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_rowInserted() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
mConverter.indexOneSearchIndexableData(localeStr, raw,
|
||||
new HashMap<>()/* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_nonIndexableKey_resultIsDisabled() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
Map<String, Set<String>> niks = new HashMap<>();
|
||||
Set<String> keys = new HashSet<>();
|
||||
keys.add(raw.key);
|
||||
niks.put(raw.intentTargetPackage, keys);
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, raw, niks);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_rowMatches() {
|
||||
SearchIndexableRaw raw = getFakeRaw();
|
||||
mConverter.indexOneSearchIndexableData(localeStr, raw,
|
||||
new HashMap<>()/* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(raw.rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo(updatedTitle);
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo(normalizedTitle);
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(updatedSummaryOn);
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(normalizedSummaryOn);
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(6)).isEqualTo(updatedSummaryOff);
|
||||
// Summary off normalized
|
||||
assertThat(cursor.getString(7)).isEqualTo(normalizedSummaryOff);
|
||||
// Entries
|
||||
assertThat(cursor.getString(8)).isEqualTo(raw.entries);
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(spaceDelimittedKeywords);
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo(raw.screenTitle);
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(raw.className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(raw.iconResId);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(raw.intentAction);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(raw.intentTargetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(raw.intentTargetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(raw.enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNotNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(raw.userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertRawColumn_mismatchedLocale_noRowInserted() {
|
||||
SearchIndexableRaw raw = getFakeRaw("ca-fr");
|
||||
mConverter.indexOneSearchIndexableData(localeStr, raw, null /* Non-indexable keys */);
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
// Tests for the flow: IndexOneResource -> IndexFromResource ->
|
||||
// UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||
|
||||
@Test
|
||||
public void testNullResource_NothingInserted() {
|
||||
mConverter.indexOneSearchIndexableData(localeStr, null /* searchIndexableResource */,
|
||||
new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_RowsInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.display_settings);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(17);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_withNIKs_rowsInsertedDisabled() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.display_settings);
|
||||
// Only add 2 of 16 items to be disabled.
|
||||
String[] keys = {"brightness", "wallpaper"};
|
||||
Map<String, Set<String>> niks = getNonIndexableKeys(keys);
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, niks);
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(2);
|
||||
cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResourceHeader_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.application_settings);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(1);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("App info");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("app info");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo("Manage apps, set up quick launch shortcuts");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo("manage apps, set up quick launch shortcuts");
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(0);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("applications_settings");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_customSetting_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.swipe_to_notification_settings);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
final String prefTitle =
|
||||
mContext.getString(string.fingerprint_swipe_for_notifications_title);
|
||||
final String prefSummary =
|
||||
mContext.getString(string.fingerprint_swipe_for_notifications_summary);
|
||||
final String keywords = mContext.getString(string.keywords_gesture);
|
||||
Cursor cursor = mDb.rawQuery(
|
||||
"SELECT * FROM prefs_index where data_title='" + prefTitle + "'", null);
|
||||
cursor.moveToFirst();
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo(prefTitle);
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo(prefTitle.toLowerCase());
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(prefSummary);
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(prefSummary.toLowerCase());
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(keywords);
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo(
|
||||
mContext.getString(string.fingerprint_swipe_for_notifications_title));
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("gesture_swipe_down_fingerprint");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_checkboxPreference_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.application_settings);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
|
||||
/* Should return 6 results, with the following titles:
|
||||
* Advanced Settings, Apps, Manage Apps, Preferred install location, Running Services
|
||||
*/
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Advanced settings");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("advanced settings");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo("Enable more settings options");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo("enable more settings options");
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(6)).isEqualTo("Enable more settings options");
|
||||
// Summary Off
|
||||
assertThat(cursor.getString(7)).isEqualTo("enable more settings options");
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("toggle_advanced_settings");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_listPreference_rowsMatch() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.application_settings);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(3);
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(rank);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Preferred install location");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("preferred install location");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEqualTo(
|
||||
"Change the preferred installation location for new apps");
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEqualTo(
|
||||
"change the preferred installation location for new apps");
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isEqualTo("Internal device storage|Removable SD card|" +
|
||||
"Let the system decide|");
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEmpty();
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("App info");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(action);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isEqualTo(targetPackage);
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isEqualTo(targetClass);
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isEqualTo("app_install_location");
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResource_iconAddedFromXml() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.connected_devices);
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isNotEqualTo(noIcon);
|
||||
}
|
||||
|
||||
// Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
|
||||
// UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_rowInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.swipe_to_notification_settings);
|
||||
resource.xmlResId = 0;
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_rowMatches() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.swipe_to_notification_settings);
|
||||
resource.xmlResId = 0;
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(0);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Display size");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("display size");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEmpty();
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEmpty();
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo("display density screen zoom scale scaling");
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("Display size");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11))
|
||||
.isEqualTo("com.android.settings.display.ScreenZoomSettings");
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isNull();
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isNull();
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isNull();
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_resourceRowInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(0);
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_resourceRowMatches() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Locale
|
||||
assertThat(cursor.getString(0)).isEqualTo(localeStr);
|
||||
// Data Rank
|
||||
assertThat(cursor.getInt(1)).isEqualTo(0);
|
||||
// Data Title
|
||||
assertThat(cursor.getString(2)).isEqualTo("Display size");
|
||||
// Normalized Title
|
||||
assertThat(cursor.getString(3)).isEqualTo("display size");
|
||||
// Summary On
|
||||
assertThat(cursor.getString(4)).isEmpty();
|
||||
// Summary On Normalized
|
||||
assertThat(cursor.getString(5)).isEmpty();
|
||||
// Summary Off - only on for checkbox preferences
|
||||
assertThat(cursor.getString(6)).isEmpty();
|
||||
// Summary off normalized - only on for checkbox preferences
|
||||
assertThat(cursor.getString(7)).isEmpty();
|
||||
// Entries - only on for list preferences
|
||||
assertThat(cursor.getString(8)).isNull();
|
||||
// Keywords
|
||||
assertThat(cursor.getString(9)).isEqualTo(
|
||||
"display density screen zoom scale scaling");
|
||||
// Screen Title
|
||||
assertThat(cursor.getString(10)).isEqualTo("Display size");
|
||||
// Class Name
|
||||
assertThat(cursor.getString(11))
|
||||
.isEqualTo("com.android.settings.display.ScreenZoomSettings");
|
||||
// Icon
|
||||
assertThat(cursor.getInt(12)).isEqualTo(noIcon);
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isNull();
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14)).isNull();
|
||||
// Target Class
|
||||
assertThat(cursor.getString(15)).isNull();
|
||||
// Enabled
|
||||
assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
|
||||
// Data ref key
|
||||
assertThat(cursor.getString(17)).isNull();
|
||||
// User Id
|
||||
assertThat(cursor.getInt(18)).isEqualTo(userId);
|
||||
// Payload Type - default is 0
|
||||
assertThat(cursor.getInt(19)).isEqualTo(0);
|
||||
// Payload - should be updated to real payloads as controllers are added
|
||||
byte[] payload = cursor.getBlob(20);
|
||||
ResultPayload unmarshalledPayload = ResultPayloadUtils.unmarshall(payload,
|
||||
ResultPayload.CREATOR);
|
||||
assertThat(unmarshalledPayload).isInstanceOf(ResultPayload.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_disabledResource_rowsInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResource_withTitleAndSettingName_titleNotInserted() {
|
||||
SearchIndexableResource resource = getFakeResource(xml.swipe_to_notification_settings);
|
||||
mConverter.indexFromResource(localeStr, resource, new ArrayList<>());
|
||||
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE" +
|
||||
" enabled = 1", null);
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceProvider_nonSubsettingIntent() {
|
||||
SearchIndexableResource resource = getFakeResource(0 /* xml */);
|
||||
String fakeAction = "fake_action";
|
||||
resource.className = "com.android.settings.LegalSettings";
|
||||
resource.intentAction = fakeAction;
|
||||
resource.intentTargetPackage = SearchIndexableResources.SUBSETTING_TARGET_PACKAGE;
|
||||
|
||||
mConverter.indexOneSearchIndexableData(localeStr, resource, new HashMap<>());
|
||||
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||
cursor.moveToPosition(0);
|
||||
|
||||
// Intent Action
|
||||
assertThat(cursor.getString(13)).isEqualTo(fakeAction);
|
||||
// Target Package
|
||||
assertThat(cursor.getString(14))
|
||||
.isEqualTo(SearchIndexableResources.SUBSETTING_TARGET_PACKAGE);
|
||||
}
|
||||
|
||||
private SearchIndexableRaw getFakeRaw() {
|
||||
return getFakeRaw(localeStr);
|
||||
}
|
||||
|
||||
private SearchIndexableRaw getFakeRaw(String localeStr) {
|
||||
SearchIndexableRaw data = new SearchIndexableRaw(mContext);
|
||||
data.locale = new Locale(localeStr);
|
||||
data.rank = rank;
|
||||
data.title = title;
|
||||
data.summaryOn = summaryOn;
|
||||
data.summaryOff = summaryOff;
|
||||
data.entries = entries;
|
||||
data.keywords = keywords;
|
||||
data.screenTitle = screenTitle;
|
||||
data.className = className;
|
||||
data.packageName = packageName;
|
||||
data.iconResId = iconResId;
|
||||
data.intentAction = action;
|
||||
data.intentTargetPackage = targetPackage;
|
||||
data.intentTargetClass = targetClass;
|
||||
data.key = key;
|
||||
data.userId = userId;
|
||||
data.enabled = enabled;
|
||||
return data;
|
||||
}
|
||||
|
||||
private SearchIndexableResource getFakeResource(int xml) {
|
||||
SearchIndexableResource sir = new SearchIndexableResource(mContext);
|
||||
sir.rank = rank;
|
||||
sir.xmlResId = xml;
|
||||
sir.className = className;
|
||||
sir.packageName = packageName;
|
||||
sir.iconResId = iconResId;
|
||||
sir.intentAction = action;
|
||||
sir.intentTargetPackage = targetPackage;
|
||||
sir.intentTargetClass = targetClass;
|
||||
sir.enabled = enabled;
|
||||
return sir;
|
||||
}
|
||||
|
||||
private Map<String, Set<String>> getNonIndexableKeys(String[] keys) {
|
||||
Map<String, Set<String>> niks = new HashMap<>();
|
||||
Set<String> keysList = new HashSet<>();
|
||||
keysList.addAll(Arrays.asList(keys));
|
||||
niks.put(packageName, keysList);
|
||||
return niks;
|
||||
}
|
||||
}
|
@@ -15,16 +15,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
package com.android.settings.search.indexing;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.search.InlineSwitchPayload;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.ResultPayloadUtils;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.DatabaseIndexingManager.DatabaseRow;
|
||||
import com.android.settings.search.DatabaseIndexingManager.DatabaseRow.Builder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -36,8 +37,8 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class DatabaseRowTest {
|
||||
private Builder mBuilder;
|
||||
public class IndexDataTest {
|
||||
private IndexData.Builder mBuilder;
|
||||
|
||||
private static final String LOCALE = "locale";
|
||||
private static final String UPDATED_TITLE = "updated title";
|
||||
@@ -69,13 +70,13 @@ public class DatabaseRowTest {
|
||||
|
||||
@Test
|
||||
public void testFullRowBuild_nonNull() {
|
||||
DatabaseRow row = generateRow();
|
||||
IndexData row = generateRow();
|
||||
assertThat(row).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitivesBuild_noDataLoss() {
|
||||
DatabaseRow row = generateRow();
|
||||
IndexData row = generateRow();
|
||||
|
||||
assertThat(row.locale).isEqualTo(LOCALE);
|
||||
assertThat(row.updatedTitle).isEqualTo(UPDATED_TITLE);
|
||||
@@ -102,7 +103,7 @@ public class DatabaseRowTest {
|
||||
|
||||
@Test
|
||||
public void testGenericIntent_addedToPayload() {
|
||||
final DatabaseRow row = generateRow();
|
||||
final IndexData row = generateRow();
|
||||
final ResultPayload payload = ResultPayloadUtils.unmarshall(row.payload,
|
||||
ResultPayload.CREATOR);
|
||||
final ComponentName name = payload.getIntent().getComponent();
|
||||
@@ -116,12 +117,12 @@ public class DatabaseRowTest {
|
||||
final InlineSwitchPayload payload = new InlineSwitchPayload(URI, 0 /* mSettingSource */,
|
||||
1 /* onValue */, null /* intent */, true /* isDeviceSupported */, 1 /* default */);
|
||||
mBuilder.setPayload(payload);
|
||||
final DatabaseRow row = generateRow();
|
||||
final IndexData row = generateRow();
|
||||
final InlineSwitchPayload unmarshalledPayload = ResultPayloadUtils
|
||||
.unmarshall(row.payload, InlineSwitchPayload.CREATOR);
|
||||
|
||||
assertThat(row.payloadType).isEqualTo(ResultPayload.PayloadType.INLINE_SWITCH);
|
||||
assertThat(unmarshalledPayload.mSettingKey).isEqualTo(URI);
|
||||
assertThat(unmarshalledPayload.getKey()).isEqualTo(URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,7 +136,7 @@ public class DatabaseRowTest {
|
||||
final InlineSwitchPayload payload = new InlineSwitchPayload(URI, 0 /* mSettingSource */,
|
||||
1 /* onValue */, intent, true /* isDeviceSupported */, 1 /* default */);
|
||||
mBuilder.setPayload(payload);
|
||||
final DatabaseRow row = generateRow();
|
||||
final IndexData row = generateRow();
|
||||
final InlineSwitchPayload unmarshalledPayload = ResultPayloadUtils
|
||||
.unmarshall(row.payload, InlineSwitchPayload.CREATOR);
|
||||
final ComponentName name = unmarshalledPayload.getIntent().getComponent();
|
||||
@@ -145,12 +146,12 @@ public class DatabaseRowTest {
|
||||
}
|
||||
|
||||
|
||||
private DatabaseRow generateRow() {
|
||||
private IndexData generateRow() {
|
||||
return mBuilder.build(mContext);
|
||||
}
|
||||
|
||||
private DatabaseRow.Builder createBuilder() {
|
||||
mBuilder = new DatabaseRow.Builder();
|
||||
private IndexData.Builder createBuilder() {
|
||||
mBuilder = new IndexData.Builder();
|
||||
mBuilder.setLocale(LOCALE)
|
||||
.setUpdatedTitle(UPDATED_TITLE)
|
||||
.setNormalizedTitle(NORMALIZED_TITLE)
|
@@ -47,7 +47,7 @@ import static org.mockito.Mockito.spy;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class IndexableDataCollectorTest {
|
||||
public class PreIndexDataCollectorTest {
|
||||
|
||||
private final String AUTHORITY_ONE = "authority";
|
||||
private final String PACKAGE_ONE = "com.android.settings";
|
||||
@@ -57,7 +57,7 @@ public class IndexableDataCollectorTest {
|
||||
|
||||
Context mContext;
|
||||
|
||||
IndexableDataCollector mDataCollector;
|
||||
PreIndexDataCollector mDataCollector;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -66,7 +66,7 @@ public class IndexableDataCollectorTest {
|
||||
doReturn(mResolver).when(mContext).getContentResolver();
|
||||
//doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
|
||||
mDataCollector = spy(new IndexableDataCollector(mContext));
|
||||
mDataCollector = spy(new PreIndexDataCollector(mContext));
|
||||
}
|
||||
|
||||
@Test
|
Reference in New Issue
Block a user