Merge "Update the Settings database to enable Payloads"
This commit is contained in:
committed by
Android (Google) Code Review
commit
08951ab12f
@@ -20,6 +20,7 @@ import android.support.v7.preference.Preference;
|
|||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.settings.search.SearchIndexableRaw;
|
import com.android.settings.search.SearchIndexableRaw;
|
||||||
|
import com.android.settings.search2.ResultPayload;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -104,4 +105,11 @@ public abstract class PreferenceController {
|
|||||||
screen.removePreference(pref);
|
screen.removePreference(pref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the {@link ResultPayload} corresponding to the search result type for the preference.
|
||||||
|
*/
|
||||||
|
public ResultPayload getResultPayload() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.search;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.SearchIndexableResource;
|
import android.provider.SearchIndexableResource;
|
||||||
|
import com.android.settings.core.PreferenceController;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -46,4 +47,9 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
|
|||||||
public List<String> getNonIndexableKeys(Context context) {
|
public List<String> getNonIndexableKeys(Context context) {
|
||||||
return EMPTY_LIST;
|
return EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,46 +28,48 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
|
|||||||
private static final String TAG = "IndexDatabaseHelper";
|
private static final String TAG = "IndexDatabaseHelper";
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "search_index.db";
|
private static final String DATABASE_NAME = "search_index.db";
|
||||||
private static final int DATABASE_VERSION = 115;
|
private static final int DATABASE_VERSION = 116;
|
||||||
|
|
||||||
private static final String INDEX = "index";
|
private static final String INDEX = "index";
|
||||||
|
|
||||||
public interface Tables {
|
public interface Tables {
|
||||||
public static final String TABLE_PREFS_INDEX = "prefs_index";
|
String TABLE_PREFS_INDEX = "prefs_index";
|
||||||
public static final String TABLE_META_INDEX = "meta_index";
|
String TABLE_META_INDEX = "meta_index";
|
||||||
public static final String TABLE_SAVED_QUERIES = "saved_queries";
|
String TABLE_SAVED_QUERIES = "saved_queries";
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IndexColumns {
|
public interface IndexColumns {
|
||||||
public static final String DOCID = "docid";
|
String DOCID = "docid";
|
||||||
public static final String LOCALE = "locale";
|
String LOCALE = "locale";
|
||||||
public static final String DATA_RANK = "data_rank";
|
String DATA_RANK = "data_rank";
|
||||||
public static final String DATA_TITLE = "data_title";
|
String DATA_TITLE = "data_title";
|
||||||
public static final String DATA_TITLE_NORMALIZED = "data_title_normalized";
|
String DATA_TITLE_NORMALIZED = "data_title_normalized";
|
||||||
public static final String DATA_SUMMARY_ON = "data_summary_on";
|
String DATA_SUMMARY_ON = "data_summary_on";
|
||||||
public static final String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
|
String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
|
||||||
public static final String DATA_SUMMARY_OFF = "data_summary_off";
|
String DATA_SUMMARY_OFF = "data_summary_off";
|
||||||
public static final String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
|
String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
|
||||||
public static final String DATA_ENTRIES = "data_entries";
|
String DATA_ENTRIES = "data_entries";
|
||||||
public static final String DATA_KEYWORDS = "data_keywords";
|
String DATA_KEYWORDS = "data_keywords";
|
||||||
public static final String CLASS_NAME = "class_name";
|
String CLASS_NAME = "class_name";
|
||||||
public static final String SCREEN_TITLE = "screen_title";
|
String SCREEN_TITLE = "screen_title";
|
||||||
public static final String INTENT_ACTION = "intent_action";
|
String INTENT_ACTION = "intent_action";
|
||||||
public static final String INTENT_TARGET_PACKAGE = "intent_target_package";
|
String INTENT_TARGET_PACKAGE = "intent_target_package";
|
||||||
public static final String INTENT_TARGET_CLASS = "intent_target_class";
|
String INTENT_TARGET_CLASS = "intent_target_class";
|
||||||
public static final String ICON = "icon";
|
String ICON = "icon";
|
||||||
public static final String ENABLED = "enabled";
|
String ENABLED = "enabled";
|
||||||
public static final String DATA_KEY_REF = "data_key_reference";
|
String DATA_KEY_REF = "data_key_reference";
|
||||||
public static final String USER_ID = "user_id";
|
String USER_ID = "user_id";
|
||||||
|
String PAYLOAD_TYPE = "payload_type";
|
||||||
|
String PAYLOAD = "payload";
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface MetaColumns {
|
public interface MetaColumns {
|
||||||
public static final String BUILD = "build";
|
String BUILD = "build";
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface SavedQueriesColums {
|
public interface SavedQueriesColums {
|
||||||
public static final String QUERY = "query";
|
String QUERY = "query";
|
||||||
public static final String TIME_STAMP = "timestamp";
|
String TIME_STAMP = "timestamp";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String CREATE_INDEX_TABLE =
|
private static final String CREATE_INDEX_TABLE =
|
||||||
@@ -110,6 +112,10 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
|
|||||||
IndexColumns.DATA_KEY_REF +
|
IndexColumns.DATA_KEY_REF +
|
||||||
", " +
|
", " +
|
||||||
IndexColumns.USER_ID +
|
IndexColumns.USER_ID +
|
||||||
|
", " +
|
||||||
|
IndexColumns.PAYLOAD_TYPE +
|
||||||
|
", " +
|
||||||
|
IndexColumns.PAYLOAD +
|
||||||
");";
|
");";
|
||||||
|
|
||||||
private static final String CREATE_META_TABLE =
|
private static final String CREATE_META_TABLE =
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.search;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.SearchIndexableResource;
|
import android.provider.SearchIndexableResource;
|
||||||
|
import com.android.settings.core.PreferenceController;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -65,5 +66,11 @@ public interface Indexable {
|
|||||||
* @return a list of {@link SearchIndexableRaw} references. Can be null.
|
* @return a list of {@link SearchIndexableRaw} references. Can be null.
|
||||||
*/
|
*/
|
||||||
List<String> getNonIndexableKeys(Context context);
|
List<String> getNonIndexableKeys(Context context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @return a list of {@link PreferenceController} for ResultPayload data during Indexing.
|
||||||
|
*/
|
||||||
|
List<PreferenceController> getPreferenceControllers(Context context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,10 +34,12 @@ import android.provider.SearchIndexableData;
|
|||||||
import android.provider.SearchIndexableResource;
|
import android.provider.SearchIndexableResource;
|
||||||
import android.provider.SearchIndexablesContract;
|
import android.provider.SearchIndexablesContract;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.settings.core.PreferenceController;
|
||||||
import com.android.settings.search.IndexDatabaseHelper;
|
import com.android.settings.search.IndexDatabaseHelper;
|
||||||
import com.android.settings.search.Indexable;
|
import com.android.settings.search.Indexable;
|
||||||
import com.android.settings.search.Ranking;
|
import com.android.settings.search.Ranking;
|
||||||
@@ -86,56 +88,6 @@ import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RES
|
|||||||
public class DatabaseIndexingManager {
|
public class DatabaseIndexingManager {
|
||||||
private static final String LOG_TAG = "DatabaseIndexingManager";
|
private static final String LOG_TAG = "DatabaseIndexingManager";
|
||||||
|
|
||||||
// Those indices should match the indices of SELECT_COLUMNS !
|
|
||||||
public static final int COLUMN_INDEX_RANK = 0;
|
|
||||||
public static final int COLUMN_INDEX_TITLE = 1;
|
|
||||||
public static final int COLUMN_INDEX_SUMMARY_ON = 2;
|
|
||||||
public static final int COLUMN_INDEX_SUMMARY_OFF = 3;
|
|
||||||
public static final int COLUMN_INDEX_ENTRIES = 4;
|
|
||||||
public static final int COLUMN_INDEX_KEYWORDS = 5;
|
|
||||||
public static final int COLUMN_INDEX_CLASS_NAME = 6;
|
|
||||||
public static final int COLUMN_INDEX_SCREEN_TITLE = 7;
|
|
||||||
public static final int COLUMN_INDEX_ICON = 8;
|
|
||||||
public static final int COLUMN_INDEX_INTENT_ACTION = 9;
|
|
||||||
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10;
|
|
||||||
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11;
|
|
||||||
public static final int COLUMN_INDEX_ENABLED = 12;
|
|
||||||
public static final int COLUMN_INDEX_KEY = 13;
|
|
||||||
public static final int COLUMN_INDEX_USER_ID = 14;
|
|
||||||
|
|
||||||
// If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
|
|
||||||
private static final String[] SELECT_COLUMNS = new String[] {
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_RANK, // 0
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_TITLE, // 1
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, // 2
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, // 3
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, // 4
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, // 5
|
|
||||||
IndexDatabaseHelper.IndexColumns.CLASS_NAME, // 6
|
|
||||||
IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, // 7
|
|
||||||
IndexDatabaseHelper.IndexColumns.ICON, // 8
|
|
||||||
IndexDatabaseHelper.IndexColumns.INTENT_ACTION, // 9
|
|
||||||
IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, // 10
|
|
||||||
IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, // 11
|
|
||||||
IndexDatabaseHelper.IndexColumns.ENABLED, // 12
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_KEY_REF // 13
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final String[] MATCH_COLUMNS_PRIMARY = {
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_TITLE,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final String[] MATCH_COLUMNS_SECONDARY = {
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
|
|
||||||
IndexDatabaseHelper.IndexColumns.DATA_ENTRIES
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
|
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_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
|
||||||
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
|
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
|
||||||
@@ -514,7 +466,7 @@ public class DatabaseIndexingManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
|
public void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
|
||||||
SearchIndexableData data, Map<String, List<String>> nonIndexableKeys) {
|
SearchIndexableData data, Map<String, List<String>> nonIndexableKeys) {
|
||||||
if (data instanceof SearchIndexableResource) {
|
if (data instanceof SearchIndexableResource) {
|
||||||
indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
|
indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
|
||||||
@@ -530,22 +482,22 @@ public class DatabaseIndexingManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOneRowWithFilteredData(database, localeStr,
|
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||||
raw.title,
|
builder.setLocale(localeStr)
|
||||||
raw.summaryOn,
|
.setEntries(raw.entries)
|
||||||
raw.summaryOff,
|
.setClassName(raw.className)
|
||||||
raw.entries,
|
.setScreenTitle(raw.screenTitle)
|
||||||
raw.className,
|
.setIconResId(raw.iconResId)
|
||||||
raw.screenTitle,
|
.setRank(raw.rank)
|
||||||
raw.iconResId,
|
.setIntentAction(raw.intentAction)
|
||||||
raw.rank,
|
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||||
raw.keywords,
|
.setIntentTargetClass(raw.intentTargetClass)
|
||||||
raw.intentAction,
|
.setEnabled(raw.enabled)
|
||||||
raw.intentTargetPackage,
|
.setKey(raw.key)
|
||||||
raw.intentTargetClass,
|
.setUserId(raw.userId);
|
||||||
raw.enabled,
|
|
||||||
raw.key,
|
updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn, raw.summaryOff,
|
||||||
raw.userId);
|
raw.keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexOneResource(SQLiteDatabase database, String localeStr,
|
private void indexOneResource(SQLiteDatabase database, String localeStr,
|
||||||
@@ -622,25 +574,45 @@ public class DatabaseIndexingManager {
|
|||||||
final int outerDepth = parser.getDepth();
|
final int outerDepth = parser.getDepth();
|
||||||
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
|
||||||
final String screenTitle = XMLParserUtil.getDataTitle(context, attrs);
|
final String screenTitle = XmlParserUtils.getDataTitle(context, attrs);
|
||||||
|
|
||||||
String key = XMLParserUtil.getDataKey(context, attrs);
|
String key = XmlParserUtils.getDataKey(context, attrs);
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
String summary;
|
String summary;
|
||||||
String keywords;
|
String keywords;
|
||||||
|
ResultPayload payload;
|
||||||
|
|
||||||
|
ArrayMap<String, PreferenceController> controllerUriMap = null;
|
||||||
|
|
||||||
|
if (fragmentName != null) {
|
||||||
|
controllerUriMap = (ArrayMap) DatabaseIndexingUtils
|
||||||
|
.getPreferenceControllerUriMap(fragmentName, context);
|
||||||
|
}
|
||||||
|
|
||||||
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
||||||
// hyphens.
|
// hyphens.
|
||||||
if (!nonIndexableKeys.contains(key)) {
|
if (!nonIndexableKeys.contains(key)) {
|
||||||
title = XMLParserUtil.getDataTitle(context, attrs);
|
title = XmlParserUtils.getDataTitle(context, attrs);
|
||||||
summary = XMLParserUtil.getDataSummary(context, attrs);
|
summary = XmlParserUtils.getDataSummary(context, attrs);
|
||||||
keywords = XMLParserUtil.getDataKeywords(context, attrs);
|
keywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||||
|
|
||||||
updateOneRowWithFilteredData(database, localeStr, title, summary, null, null,
|
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||||
fragmentName, screenTitle, iconResId, rank,
|
builder.setLocale(localeStr)
|
||||||
keywords, intentAction, intentTargetPackage, intentTargetClass, true,
|
.setEntries(null)
|
||||||
key, -1 /* default user id */);
|
.setClassName(fragmentName)
|
||||||
|
.setScreenTitle(screenTitle)
|
||||||
|
.setIconResId(iconResId)
|
||||||
|
.setRank(rank)
|
||||||
|
.setIntentAction(intentAction)
|
||||||
|
.setIntentTargetPackage(intentTargetPackage)
|
||||||
|
.setIntentTargetClass(intentTargetClass)
|
||||||
|
.setEnabled(true)
|
||||||
|
.setKey(key)
|
||||||
|
.setUserId(-1 /* default user id */);
|
||||||
|
|
||||||
|
updateOneRowWithFilteredData(database, builder, title, summary,
|
||||||
|
null /* summary off */, keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
@@ -651,43 +623,56 @@ public class DatabaseIndexingManager {
|
|||||||
|
|
||||||
nodeName = parser.getName();
|
nodeName = parser.getName();
|
||||||
|
|
||||||
key = XMLParserUtil.getDataKey(context, attrs);
|
key = XmlParserUtils.getDataKey(context, attrs);
|
||||||
if (nonIndexableKeys.contains(key)) {
|
if (nonIndexableKeys.contains(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
title = XMLParserUtil.getDataTitle(context, attrs);
|
title = XmlParserUtils.getDataTitle(context, attrs);
|
||||||
keywords = XMLParserUtil.getDataKeywords(context, attrs);
|
keywords = XmlParserUtils.getDataKeywords(context, attrs);
|
||||||
|
|
||||||
|
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||||
|
builder.setLocale(localeStr)
|
||||||
|
.setClassName(fragmentName)
|
||||||
|
.setScreenTitle(screenTitle)
|
||||||
|
.setIconResId(iconResId)
|
||||||
|
.setRank(rank)
|
||||||
|
.setIntentAction(intentAction)
|
||||||
|
.setIntentTargetPackage(intentTargetPackage)
|
||||||
|
.setIntentTargetClass(intentTargetClass)
|
||||||
|
.setEnabled(true)
|
||||||
|
.setKey(key)
|
||||||
|
.setUserId(-1 /* default user id */);
|
||||||
|
|
||||||
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
|
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
|
||||||
summary = XMLParserUtil.getDataSummary(context, attrs);
|
summary = XmlParserUtils.getDataSummary(context, attrs);
|
||||||
|
|
||||||
String entries = null;
|
String entries = null;
|
||||||
|
|
||||||
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
|
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
|
||||||
entries = XMLParserUtil.getDataEntries(context, attrs);
|
entries = XmlParserUtils.getDataEntries(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
|
||||||
|
|
||||||
|
builder.setEntries(entries)
|
||||||
|
.setPayload(payload);
|
||||||
|
|
||||||
// Insert rows for the child nodes of PreferenceScreen
|
// Insert rows for the child nodes of PreferenceScreen
|
||||||
updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries,
|
updateOneRowWithFilteredData(database, builder, title, summary,
|
||||||
fragmentName, screenTitle, iconResId, rank,
|
null /* summary off */, keywords);
|
||||||
keywords, intentAction, intentTargetPackage, intentTargetClass,
|
|
||||||
true, key, -1 /* default user id */);
|
|
||||||
} else {
|
} else {
|
||||||
String summaryOn = XMLParserUtil.getDataSummaryOn(context, attrs);
|
String summaryOn = XmlParserUtils.getDataSummaryOn(context, attrs);
|
||||||
String summaryOff = XMLParserUtil.getDataSummaryOff(context, attrs);
|
String summaryOff = XmlParserUtils.getDataSummaryOff(context, attrs);
|
||||||
|
|
||||||
if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
|
if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
|
||||||
summaryOn = XMLParserUtil.getDataSummary(context, attrs);
|
summaryOn = XmlParserUtils.getDataSummary(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff,
|
updateOneRowWithFilteredData(database, builder, title, summaryOn, summaryOff,
|
||||||
null, fragmentName, screenTitle, iconResId, rank,
|
keywords);
|
||||||
keywords, intentAction, intentTargetPackage, intentTargetClass,
|
|
||||||
true, key, -1 /* default user id */);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
throw new RuntimeException("Error parsing PreferenceScreen", e);
|
throw new RuntimeException("Error parsing PreferenceScreen", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -709,6 +694,7 @@ public class DatabaseIndexingManager {
|
|||||||
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(context, enabled);
|
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(context, enabled);
|
||||||
|
|
||||||
if (rawList != null) {
|
if (rawList != null) {
|
||||||
|
|
||||||
final int rawSize = rawList.size();
|
final int rawSize = rawList.size();
|
||||||
for (int i = 0; i < rawSize; i++) {
|
for (int i = 0; i < rawSize; i++) {
|
||||||
SearchIndexableRaw raw = rawList.get(i);
|
SearchIndexableRaw raw = rawList.get(i);
|
||||||
@@ -722,22 +708,22 @@ public class DatabaseIndexingManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOneRowWithFilteredData(database, localeStr,
|
DatabaseRow.Builder builder = new DatabaseRow.Builder();
|
||||||
raw.title,
|
builder.setLocale(localeStr)
|
||||||
raw.summaryOn,
|
.setEntries(raw.entries)
|
||||||
raw.summaryOff,
|
.setClassName(className)
|
||||||
raw.entries,
|
.setScreenTitle(raw.screenTitle)
|
||||||
className,
|
.setIconResId(iconResId)
|
||||||
raw.screenTitle,
|
.setRank(rank)
|
||||||
iconResId,
|
.setIntentAction(raw.intentAction)
|
||||||
rank,
|
.setIntentTargetPackage(raw.intentTargetPackage)
|
||||||
raw.keywords,
|
.setIntentTargetClass(raw.intentTargetClass)
|
||||||
raw.intentAction,
|
.setEnabled(raw.enabled)
|
||||||
raw.intentTargetPackage,
|
.setKey(raw.key)
|
||||||
raw.intentTargetClass,
|
.setUserId(raw.userId);
|
||||||
raw.enabled,
|
|
||||||
raw.key,
|
updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn,
|
||||||
raw.userId);
|
raw.summaryOff, raw.keywords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,70 +752,68 @@ public class DatabaseIndexingManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale,
|
private void updateOneRowWithFilteredData(SQLiteDatabase database, DatabaseRow.Builder builder,
|
||||||
String title, String summaryOn, String summaryOff, String entries,
|
String title, String summaryOn, String summaryOff,String keywords) {
|
||||||
String className,
|
|
||||||
String screenTitle, int iconResId, int rank, String keywords,
|
|
||||||
String intentAction, String intentTargetPackage, String intentTargetClass,
|
|
||||||
boolean enabled, String key, int userId) {
|
|
||||||
|
|
||||||
final String updatedTitle = XMLParserUtil.normalizeHyphen(title);
|
final String updatedTitle = DatabaseIndexingUtils.normalizeHyphen(title);
|
||||||
final String updatedSummaryOn = XMLParserUtil.normalizeHyphen(summaryOn);
|
final String updatedSummaryOn = DatabaseIndexingUtils.normalizeHyphen(summaryOn);
|
||||||
final String updatedSummaryOff = XMLParserUtil.normalizeHyphen(summaryOff);
|
final String updatedSummaryOff = DatabaseIndexingUtils.normalizeHyphen(summaryOff);
|
||||||
|
|
||||||
final String normalizedTitle = XMLParserUtil.normalizeString(updatedTitle);
|
final String normalizedTitle = DatabaseIndexingUtils.normalizeString(updatedTitle);
|
||||||
final String normalizedSummaryOn = XMLParserUtil.normalizeString(updatedSummaryOn);
|
final String normalizedSummaryOn = DatabaseIndexingUtils.normalizeString(updatedSummaryOn);
|
||||||
final String normalizedSummaryOff = XMLParserUtil.normalizeString(updatedSummaryOff);
|
final String normalizedSummaryOff = DatabaseIndexingUtils
|
||||||
|
.normalizeString(updatedSummaryOff);
|
||||||
|
|
||||||
final String spaceDelimitedKeywords = XMLParserUtil.normalizeKeywords(keywords);
|
final String spaceDelimitedKeywords = DatabaseIndexingUtils.normalizeKeywords(keywords);
|
||||||
|
|
||||||
updateOneRow(database, locale,
|
builder.setUpdatedTitle(updatedTitle)
|
||||||
updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
|
.setUpdatedSummaryOn(updatedSummaryOn)
|
||||||
updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId,
|
.setUpdatedSummaryOff(updatedSummaryOff)
|
||||||
rank, spaceDelimitedKeywords, intentAction, intentTargetPackage, intentTargetClass,
|
.setNormalizedTitle(normalizedTitle)
|
||||||
enabled, key, userId);
|
.setNormalizedSummaryOn(normalizedSummaryOn)
|
||||||
|
.setNormalizedSummaryOff(normalizedSummaryOff)
|
||||||
|
.setSpaceDelimitedKeywords(spaceDelimitedKeywords);
|
||||||
|
|
||||||
|
updateOneRow(database, builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOneRow(SQLiteDatabase database, String locale, String updatedTitle,
|
private void updateOneRow(SQLiteDatabase database, DatabaseRow row) {
|
||||||
String normalizedTitle, String updatedSummaryOn, String normalizedSummaryOn,
|
|
||||||
String updatedSummaryOff, String normalizedSummaryOff, String entries, String className,
|
|
||||||
String screenTitle, int iconResId, int rank, String spaceDelimitedKeywords,
|
|
||||||
String intentAction, String intentTargetPackage, String intentTargetClass,
|
|
||||||
boolean enabled, String key, int userId) {
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(updatedTitle)) {
|
if (TextUtils.isEmpty(row.updatedTitle)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The DocID should contains more than the title string itself (you may have two settings
|
// The DocID should contains more than the title string itself (you may have two settings
|
||||||
// with the same title). So we need to use a combination of the title and the screenTitle.
|
// with the same title). So we need to use a combination of the title and the screenTitle.
|
||||||
StringBuilder sb = new StringBuilder(updatedTitle);
|
StringBuilder sb = new StringBuilder(row.updatedTitle);
|
||||||
sb.append(screenTitle);
|
sb.append(row.screenTitle);
|
||||||
int docId = sb.toString().hashCode();
|
int docId = sb.toString().hashCode();
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId);
|
values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, locale);
|
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, row.locale);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, rank);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, row.rank);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, updatedTitle);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, row.updatedTitle);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, row.normalizedTitle);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, updatedSummaryOn);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, row.updatedSummaryOn);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
|
||||||
normalizedSummaryOn);
|
row.normalizedSummaryOn);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, row.updatedSummaryOff);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
|
||||||
normalizedSummaryOff);
|
row.normalizedSummaryOff);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, entries);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, row.entries);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, spaceDelimitedKeywords);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, row.spaceDelimitedKeywords);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, className);
|
values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, row.className);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, screenTitle);
|
values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, row.screenTitle);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, intentAction);
|
values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, row.intentAction);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage);
|
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, row.intentTargetPackage);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, intentTargetClass);
|
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, row.intentTargetClass);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.ICON, iconResId);
|
values.put(IndexDatabaseHelper.IndexColumns.ICON, row.iconResId);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, enabled);
|
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, row.enabled);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key);
|
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, row.key);
|
||||||
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, userId);
|
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, row.userId);
|
||||||
|
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, row.payloadType);
|
||||||
|
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, row.payload);
|
||||||
|
|
||||||
database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
|
database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
|
||||||
}
|
}
|
||||||
@@ -960,4 +944,195 @@ public class DatabaseIndexingManager {
|
|||||||
whereArgs);
|
whereArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseRow build() {
|
||||||
|
return new DatabaseRow(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,12 +23,19 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.settings.core.PreferenceController;
|
||||||
import com.android.settings.search.Indexable;
|
import com.android.settings.search.Indexable;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.Normalizer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for {@like DatabaseIndexingManager} to handle the mapping between Payloads
|
* Utility class for {@like DatabaseIndexingManager} to handle the mapping between Payloads
|
||||||
@@ -36,17 +43,82 @@ import java.lang.reflect.Field;
|
|||||||
*/
|
*/
|
||||||
public class DatabaseIndexingUtils {
|
public class DatabaseIndexingUtils {
|
||||||
|
|
||||||
private static final String LOG_TAG = "IndexingUtil";
|
private static final String TAG = "IndexingUtil";
|
||||||
|
|
||||||
private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
|
private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
|
||||||
"SEARCH_INDEX_DATA_PROVIDER";
|
"SEARCH_INDEX_DATA_PROVIDER";
|
||||||
|
|
||||||
|
private static final String NON_BREAKING_HYPHEN = "\u2011";
|
||||||
|
private static final String EMPTY = "";
|
||||||
|
private static final String LIST_DELIMITERS = "[,]\\s*";
|
||||||
|
private static final String HYPHEN = "-";
|
||||||
|
private static final String SPACE = " ";
|
||||||
|
|
||||||
|
private static final Pattern REMOVE_DIACRITICALS_PATTERN
|
||||||
|
= Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param className which wil provide the map between from {@link Uri}s to
|
||||||
|
* {@link PreferenceController}
|
||||||
|
* @param context
|
||||||
|
* @return A map between {@link Uri}s and {@link PreferenceController}s to get the payload
|
||||||
|
* types for Settings.
|
||||||
|
*/
|
||||||
|
public static Map<String, PreferenceController> getPreferenceControllerUriMap(
|
||||||
|
String className, Context context) {
|
||||||
|
final Class<?> clazz = getIndexableClass(className);
|
||||||
|
|
||||||
|
if (clazz == null) {
|
||||||
|
Log.d(TAG, "SearchIndexableResource '" + className +
|
||||||
|
"' should implement the " + Indexable.class.getName() + " interface!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will be non null only for a Local provider implementing a
|
||||||
|
// SEARCH_INDEX_DATA_PROVIDER field
|
||||||
|
final Indexable.SearchIndexProvider provider = getSearchIndexProvider(clazz);
|
||||||
|
List<PreferenceController> controllers =
|
||||||
|
provider.getPreferenceControllers(context);
|
||||||
|
|
||||||
|
if (controllers == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayMap<String, PreferenceController> map = new ArrayMap<>();
|
||||||
|
|
||||||
|
for (PreferenceController controller : controllers) {
|
||||||
|
map.put(controller.getPreferenceKey(), controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uriMap Map between the {@link PreferenceController} keys and the controllers themselves.
|
||||||
|
* @param key The look up key
|
||||||
|
* @return The Payload from the {@link PreferenceController} specified by the key, if it exists.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public static ResultPayload getPayloadFromUriMap(ArrayMap<String, PreferenceController> uriMap,
|
||||||
|
String key) {
|
||||||
|
if (uriMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferenceController controller = uriMap.get(key);
|
||||||
|
if (controller == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return controller.getResultPayload();
|
||||||
|
}
|
||||||
|
|
||||||
public static Class<?> getIndexableClass(String className) {
|
public static Class<?> getIndexableClass(String className) {
|
||||||
final Class<?> clazz;
|
final Class<?> clazz;
|
||||||
try {
|
try {
|
||||||
clazz = Class.forName(className);
|
clazz = Class.forName(className);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
Log.d(LOG_TAG, "Cannot find class: " + className);
|
Log.d(TAG, "Cannot find class: " + className);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return isIndexableClass(clazz) ? clazz : null;
|
return isIndexableClass(clazz) ? clazz : null;
|
||||||
@@ -61,15 +133,15 @@ public class DatabaseIndexingUtils {
|
|||||||
final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
|
final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
|
||||||
return (Indexable.SearchIndexProvider) f.get(null);
|
return (Indexable.SearchIndexProvider) f.get(null);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
Log.d(LOG_TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
Log.d(TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||||
} catch (SecurityException se) {
|
} catch (SecurityException se) {
|
||||||
Log.d(LOG_TAG,
|
Log.d(TAG,
|
||||||
"Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
"Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
Log.d(LOG_TAG,
|
Log.d(TAG,
|
||||||
"Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
"Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Log.d(LOG_TAG,
|
Log.d(TAG,
|
||||||
"Illegal argument when accessing field '" +
|
"Illegal argument when accessing field '" +
|
||||||
FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||||
}
|
}
|
||||||
@@ -115,4 +187,19 @@ public class DatabaseIndexingUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String normalizeHyphen(String input) {
|
||||||
|
return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String normalizeKeywords(String input) {
|
||||||
|
return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ package com.android.settings.search2;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates the standard intent based results as seen in first party apps and Settings results.
|
* Encapsulates the standard intent based results as seen in first party apps and Settings results.
|
||||||
|
56
src/com/android/settings/search2/ResultPayloadUtils.java
Normal file
56
src/com/android/settings/search2/ResultPayloadUtils.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search2;
|
||||||
|
|
||||||
|
import android.os.BadParcelableException;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.StreamCorruptedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to Marshall and Unmarshall the payloads stored in the SQLite Database
|
||||||
|
*/
|
||||||
|
public class ResultPayloadUtils {
|
||||||
|
|
||||||
|
private static final String TAG = "PayloadUtil";
|
||||||
|
|
||||||
|
public static byte[] marshall(ResultPayload payload) {
|
||||||
|
Parcel parcel = Parcel.obtain();
|
||||||
|
payload.writeToParcel(parcel, 0);
|
||||||
|
byte[] bytes = parcel.marshall();
|
||||||
|
parcel.recycle();
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T unmarshall(byte[] bytes, Parcelable.Creator<T> creator) {
|
||||||
|
T result;
|
||||||
|
Parcel parcel = unmarshall(bytes);
|
||||||
|
result = creator.createFromParcel(parcel);
|
||||||
|
parcel.recycle();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Parcel unmarshall(byte[] bytes) {
|
||||||
|
Parcel parcel = Parcel.obtain();
|
||||||
|
parcel.unmarshall(bytes, 0, bytes.length);
|
||||||
|
parcel.setDataPosition(0);
|
||||||
|
return parcel;
|
||||||
|
}
|
||||||
|
}
|
@@ -30,19 +30,10 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* Utility class to parse elements of XML preferences
|
* Utility class to parse elements of XML preferences
|
||||||
*/
|
*/
|
||||||
public class XMLParserUtil {
|
public class XmlParserUtils {
|
||||||
|
|
||||||
private static final String NON_BREAKING_HYPHEN = "\u2011";
|
|
||||||
private static final String EMPTY = "";
|
|
||||||
private static final String LIST_DELIMITERS = "[,]\\s*";
|
|
||||||
private static final String HYPHEN = "-";
|
|
||||||
private static final String SPACE = " ";
|
|
||||||
|
|
||||||
private static final String ENTRIES_SEPARATOR = "|";
|
private static final String ENTRIES_SEPARATOR = "|";
|
||||||
|
|
||||||
private static final Pattern REMOVE_DIACRITICALS_PATTERN
|
|
||||||
= Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
|
|
||||||
|
|
||||||
public static String getDataKey(Context context, AttributeSet attrs) {
|
public static String getDataKey(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getData(context, attrs,
|
||||||
com.android.internal.R.styleable.Preference,
|
com.android.internal.R.styleable.Preference,
|
||||||
@@ -83,7 +74,7 @@ public class XMLParserUtil {
|
|||||||
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
|
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
|
private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
|
||||||
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
|
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
|
||||||
final TypedValue tv = sa.peekValue(resId);
|
final TypedValue tv = sa.peekValue(resId);
|
||||||
|
|
||||||
@@ -98,7 +89,7 @@ public class XMLParserUtil {
|
|||||||
return (data != null) ? data.toString() : null;
|
return (data != null) ? data.toString() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
|
private static String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
|
||||||
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
|
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
|
||||||
final TypedValue tv = sa.peekValue(resId);
|
final TypedValue tv = sa.peekValue(resId);
|
||||||
|
|
||||||
@@ -119,19 +110,4 @@ public class XMLParserUtil {
|
|||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String normalizeHyphen(String input) {
|
|
||||||
return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String normalizeKeywords(String input) {
|
|
||||||
return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -0,0 +1,616 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.search;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.provider.SearchIndexableResource;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.DatabaseIndexingManager;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
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 DatabaseIndexingManagerTest {
|
||||||
|
private final String localeStr = "en_US";
|
||||||
|
|
||||||
|
private final int rank = 42;
|
||||||
|
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 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 DatabaseIndexingManager mManager;
|
||||||
|
private SQLiteDatabase mDb;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = ShadowApplication.getInstance().getApplicationContext();
|
||||||
|
mManager = spy(new DatabaseIndexingManager(mContext, mContext.getPackageName()));
|
||||||
|
mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanUp() {
|
||||||
|
Field instance;
|
||||||
|
Class clazz = IndexDatabaseHelper.class;
|
||||||
|
try {
|
||||||
|
instance = clazz.getDeclaredField("sSingleton");
|
||||||
|
instance.setAccessible(true);
|
||||||
|
instance.set(null, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDatabaseSchema() {
|
||||||
|
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[ ]{
|
||||||
|
"locale",
|
||||||
|
"data_rank",
|
||||||
|
"data_title",
|
||||||
|
"data_title_normalized",
|
||||||
|
"data_summary_on",
|
||||||
|
"data_summary_on_normalized",
|
||||||
|
"data_summary_off",
|
||||||
|
"data_summary_off_normalized",
|
||||||
|
"data_entries",
|
||||||
|
"data_keywords",
|
||||||
|
"class_name",
|
||||||
|
"screen_title",
|
||||||
|
"intent_action",
|
||||||
|
"intent_target_package",
|
||||||
|
"intent_target_class",
|
||||||
|
"icon",
|
||||||
|
"enabled",
|
||||||
|
"data_key_reference",
|
||||||
|
"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, null /* Non-indexable keys */);
|
||||||
|
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||||
|
assertThat(cursor.getCount()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertRawColumn_RowMatches() {
|
||||||
|
SearchIndexableRaw raw = getFakeRaw();
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertRawColumnMismatchedLocale_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<String, List<String>>());
|
||||||
|
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||||
|
assertThat(cursor.getCount()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddResource_RowsInserted() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||||
|
assertThat(cursor.getCount()).isEqualTo(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddResourceHeader_RowsMatch() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
|
||||||
|
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("Apps");
|
||||||
|
// Normalized Title
|
||||||
|
assertThat(cursor.getString(3)).isEqualTo("apps");
|
||||||
|
// 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("Apps");
|
||||||
|
// Class Name
|
||||||
|
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||||
|
// Icon
|
||||||
|
assertThat(cursor.getInt(12)).isEqualTo(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddResourceCustomSetting_RowsMatch() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
|
||||||
|
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(rank);
|
||||||
|
// Data Title
|
||||||
|
assertThat(cursor.getString(2)).isEqualTo("Swipe for notifications");
|
||||||
|
// Normalized Title
|
||||||
|
assertThat(cursor.getString(3)).isEqualTo("swipe for notifications");
|
||||||
|
// Summary On
|
||||||
|
assertThat(cursor.getString(4)).isEqualTo("To check your notifications, " +
|
||||||
|
"swipe down on the fingerprint sensor on the back of your phone.");
|
||||||
|
// Summary On Normalized
|
||||||
|
assertThat(cursor.getString(5)).isEqualTo("to check your notifications, " +
|
||||||
|
"swipe down on the fingerprint sensor on the back of your phone.");
|
||||||
|
// 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("Gestures");
|
||||||
|
// Class Name
|
||||||
|
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||||
|
// Icon
|
||||||
|
assertThat(cursor.getInt(12)).isEqualTo(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddResourceCheckboxPreference_RowsMatch() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
|
||||||
|
/* 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("Apps");
|
||||||
|
// Class Name
|
||||||
|
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||||
|
// Icon
|
||||||
|
assertThat(cursor.getInt(12)).isEqualTo(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddResourceListPreference_RowsMatch() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
|
||||||
|
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("Apps");
|
||||||
|
// Class Name
|
||||||
|
assertThat(cursor.getString(11)).isEqualTo(className);
|
||||||
|
// Icon
|
||||||
|
assertThat(cursor.getInt(12)).isEqualTo(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
|
||||||
|
// UpdateOneRowWithFilteredData -> UpdateOneRow
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceProvider_RowInserted() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
resource.xmlResId = 0;
|
||||||
|
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||||
|
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||||
|
assertThat(cursor.getCount()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceProvider_Matches() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
resource.xmlResId = 0;
|
||||||
|
resource.className = "com.android.settings.display.ScreenZoomSettings";
|
||||||
|
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
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(rank);
|
||||||
|
// 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(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceProvider_ResourceRowInserted() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
resource.xmlResId = 0;
|
||||||
|
resource.className = "com.android.settings.LegalSettings";
|
||||||
|
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
|
||||||
|
assertThat(cursor.getCount()).isEqualTo(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceProvider_ResourceRowMatches() {
|
||||||
|
SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
|
||||||
|
resource.xmlResId = 0;
|
||||||
|
resource.className = "com.android.settings.LegalSettings";
|
||||||
|
|
||||||
|
mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
|
||||||
|
new HashMap<String, List<String>>());
|
||||||
|
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("Legal information");
|
||||||
|
// Normalized Title
|
||||||
|
assertThat(cursor.getString(3)).isEqualTo("legal information");
|
||||||
|
// 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)).isEmpty();
|
||||||
|
// Screen Title
|
||||||
|
assertThat(cursor.getString(10)).isEqualTo("Legal information");
|
||||||
|
// Class Name
|
||||||
|
assertThat(cursor.getString(11))
|
||||||
|
.isEqualTo("com.android.settings.LegalSettings");
|
||||||
|
// Icon
|
||||||
|
assertThat(cursor.getInt(12)).isEqualTo(iconResId);
|
||||||
|
// 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
|
||||||
|
assertThat(cursor.getBlob(20)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Util functions
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 static for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.search;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.DatabaseIndexingManager.DatabaseRow;
|
||||||
|
import com.android.settings.search2.DatabaseIndexingManager.DatabaseRow.Builder;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.ResultPayload;
|
||||||
|
import com.android.settings.search2.ResultPayloadUtils;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
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 builder;
|
||||||
|
|
||||||
|
private static final String LOCALE = "locale";
|
||||||
|
private static final String UPDATED_TITLE = "updated title";
|
||||||
|
private static final String NORMALIZED_TITLE = "normal title";
|
||||||
|
private static final String UPDATED_SUMMARY_ON = "updated summary on";
|
||||||
|
private static final String NORMALIZED_SUMMARY_ON = "normalized summary on";
|
||||||
|
private static final String UPDATED_SUMMARY_OFF = "updated summary off";
|
||||||
|
private static final String NORMALIZED_SUMMARY_OFF = "normalized summary off";
|
||||||
|
private static final String ENTRIES = "entries";
|
||||||
|
private static final String CLASS_NAME = "class name";
|
||||||
|
private static final String SCREEN_TITLE = "sceen title";
|
||||||
|
private static final int ICON_RES_ID = 0xff;
|
||||||
|
private static final int RANK = 1;
|
||||||
|
private static final String SPACE_DELIMITED_KEYWORDS = "keywords";
|
||||||
|
private static final String INTENT_ACTION = "intent action";
|
||||||
|
private static final String INTENT_TARGET_PACKAGE = "target package";
|
||||||
|
private static final String INTENT_TARGET_CLASS = "target class";
|
||||||
|
private static final boolean ENABLED = true;
|
||||||
|
private static final String KEY = "key";
|
||||||
|
private static final int USER_ID = 1;
|
||||||
|
private static IntentPayload intentPayload;
|
||||||
|
|
||||||
|
private final String EXTRA_KEY = "key";
|
||||||
|
private final String EXTRA_VALUE = "value";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_KEY, EXTRA_VALUE);
|
||||||
|
intentPayload = new IntentPayload(intent);
|
||||||
|
|
||||||
|
builder = new DatabaseRow.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFullRowBuild_NonNull() {
|
||||||
|
DatabaseRow row = generateRow();
|
||||||
|
assertThat(row).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrimativesBuild_NoDataLoss() {
|
||||||
|
DatabaseRow row = generateRow();
|
||||||
|
|
||||||
|
assertThat(row.locale).isEqualTo(LOCALE);
|
||||||
|
assertThat(row.updatedTitle).isEqualTo(UPDATED_TITLE);
|
||||||
|
assertThat(row.normalizedTitle).isEqualTo(NORMALIZED_TITLE);
|
||||||
|
assertThat(row.updatedSummaryOn).isEqualTo(UPDATED_SUMMARY_ON);
|
||||||
|
assertThat(row.normalizedSummaryOn).isEqualTo(NORMALIZED_SUMMARY_ON);
|
||||||
|
assertThat(row.updatedSummaryOff).isEqualTo(UPDATED_SUMMARY_OFF);
|
||||||
|
assertThat(row.normalizedSummaryOff).isEqualTo(NORMALIZED_SUMMARY_OFF);
|
||||||
|
assertThat(row.entries).isEqualTo(ENTRIES);
|
||||||
|
assertThat(row.className).isEqualTo(CLASS_NAME);
|
||||||
|
assertThat(row.screenTitle).isEqualTo(SCREEN_TITLE);
|
||||||
|
assertThat(row.iconResId).isEqualTo(ICON_RES_ID);
|
||||||
|
assertThat(row.rank).isEqualTo(RANK);
|
||||||
|
assertThat(row.spaceDelimitedKeywords).isEqualTo(SPACE_DELIMITED_KEYWORDS);
|
||||||
|
assertThat(row.intentAction).isEqualTo(INTENT_ACTION);
|
||||||
|
assertThat(row.intentTargetClass).isEqualTo(INTENT_TARGET_CLASS);
|
||||||
|
assertThat(row.intentTargetPackage).isEqualTo(INTENT_TARGET_PACKAGE);
|
||||||
|
assertThat(row.enabled).isEqualTo(ENABLED);
|
||||||
|
assertThat(row.userId).isEqualTo(USER_ID);
|
||||||
|
assertThat(row.key).isEqualTo(KEY);
|
||||||
|
assertThat(row.payloadType).isEqualTo(ResultPayload.PayloadType.INTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPayload_PayloadTypeAdded() {
|
||||||
|
DatabaseRow row = generateRow();
|
||||||
|
byte[] marshalledPayload = row.payload;
|
||||||
|
IntentPayload payload = ResultPayloadUtils.unmarshall(marshalledPayload,
|
||||||
|
IntentPayload.CREATOR);
|
||||||
|
|
||||||
|
Intent intent = payload.intent;
|
||||||
|
assertThat(intent.getExtra(EXTRA_KEY)).isEqualTo(EXTRA_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestNullPayload_NoCrash() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.setPayload(null);
|
||||||
|
DatabaseRow row = builder.build();
|
||||||
|
|
||||||
|
assertThat(row.payload).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DatabaseRow generateRow() {
|
||||||
|
builder.setLocale(LOCALE)
|
||||||
|
.setUpdatedTitle(UPDATED_TITLE)
|
||||||
|
.setNormalizedTitle(NORMALIZED_TITLE)
|
||||||
|
.setUpdatedSummaryOn(UPDATED_SUMMARY_ON)
|
||||||
|
.setNormalizedSummaryOn(NORMALIZED_SUMMARY_ON)
|
||||||
|
.setUpdatedSummaryOff(UPDATED_SUMMARY_OFF)
|
||||||
|
.setNormalizedSummaryOff(NORMALIZED_SUMMARY_OFF)
|
||||||
|
.setEntries(ENTRIES)
|
||||||
|
.setClassName(CLASS_NAME)
|
||||||
|
.setScreenTitle(SCREEN_TITLE)
|
||||||
|
.setIconResId(ICON_RES_ID)
|
||||||
|
.setRank(RANK)
|
||||||
|
.setSpaceDelimitedKeywords(SPACE_DELIMITED_KEYWORDS)
|
||||||
|
.setIntentAction(INTENT_ACTION)
|
||||||
|
.setIntentTargetPackage(INTENT_TARGET_PACKAGE)
|
||||||
|
.setIntentTargetClass(INTENT_TARGET_CLASS)
|
||||||
|
.setEnabled(ENABLED)
|
||||||
|
.setKey(KEY)
|
||||||
|
.setUserId(USER_ID)
|
||||||
|
.setPayload(intentPayload);
|
||||||
|
|
||||||
|
return(builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.search;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.BadParcelableException;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.ResultPayloadUtils;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.io.StreamCorruptedException;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static junit.framework.Assert.fail;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class ResultPayloadUtilsTest {
|
||||||
|
private IntentPayload payload;
|
||||||
|
|
||||||
|
private final String EXTRA_KEY = "key";
|
||||||
|
private final String EXTRA_VALUE = "value";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_KEY, EXTRA_VALUE);
|
||||||
|
payload = new IntentPayload(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnmarshallBadData_ExceptionThrown() {
|
||||||
|
byte[] badData = "I'm going to fail :)".getBytes();
|
||||||
|
try {
|
||||||
|
ResultPayloadUtils.unmarshall(badData, IntentPayload.CREATOR);
|
||||||
|
fail("unmarshall should throw exception");
|
||||||
|
} catch ( RuntimeException e) {
|
||||||
|
assertThat(e).isNotNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMarshallIntentPayload_NonEmptyArray() {
|
||||||
|
byte[] marshalledPayload = ResultPayloadUtils.marshall(payload);
|
||||||
|
assertThat(marshalledPayload).isNotNull();
|
||||||
|
assertThat(marshalledPayload).isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnmarshall_PreservedData() {
|
||||||
|
byte[] marshalledPayload = ResultPayloadUtils.marshall(payload);
|
||||||
|
IntentPayload newPayload = ResultPayloadUtils.unmarshall(marshalledPayload,
|
||||||
|
IntentPayload.CREATOR);
|
||||||
|
|
||||||
|
String originalIntentExtra = payload.intent.getStringExtra(EXTRA_KEY);
|
||||||
|
String copiedIntentExtra = newPayload.intent.getStringExtra(EXTRA_KEY);
|
||||||
|
assertThat(originalIntentExtra).isEqualTo(copiedIntentExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.search;
|
||||||
|
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import com.android.settings.search2.XmlParserUtils;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These tests use a series of preferences that have specific attributes which are sometimes
|
||||||
|
* uncommon (such as summaryOn).
|
||||||
|
*
|
||||||
|
* If changing a preference file breaks a test in this test file, please replace its reference
|
||||||
|
* with another preference with a matchin replacement attribute.
|
||||||
|
*/
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class XmlParserUtilTest {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = ShadowApplication.getInstance().getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataTitleValid_ReturnsPreferenceTitle() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
|
||||||
|
"com.android.settings.gestures.GesturePreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String title = XmlParserUtils.getDataTitle(mContext, attrs);
|
||||||
|
String expTitle = mContext.getString(R.string.fingerprint_swipe_for_notifications_title);
|
||||||
|
assertThat(title).isEqualTo(expTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataKeywordsValid_ReturnsPreferenceKeywords() {
|
||||||
|
XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String keywords = XmlParserUtils.getDataKeywords(mContext, attrs);
|
||||||
|
String expKeywords = mContext.getString(R.string.keywords_gesture);
|
||||||
|
assertThat(keywords).isEqualTo(expKeywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataKeyValid_ReturnsPreferenceKey() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
|
||||||
|
"com.android.settings.gestures.GesturePreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String key = XmlParserUtils.getDataKey(mContext, attrs);
|
||||||
|
String expKey = "gesture_swipe_down_fingerprint";
|
||||||
|
assertThat(key).isEqualTo(expKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataSummaryValid_ReturnsPreferenceSummary() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
|
||||||
|
"com.android.settings.gestures.GesturePreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String summary = XmlParserUtils.getDataSummary(mContext, attrs);
|
||||||
|
String expSummary = mContext.getString(R.string.fingerprint_swipe_for_notifications_summary);
|
||||||
|
assertThat(summary).isEqualTo(expSummary);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataSummaryOnValid_ReturnsPreferenceSummaryOn() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.application_settings, "CheckBoxPreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String summary = XmlParserUtils.getDataSummaryOn(mContext, attrs);
|
||||||
|
String expSummary = mContext.getString(R.string.advanced_settings_summary);
|
||||||
|
assertThat(summary).isEqualTo(expSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataSummaryOffValid_ReturnsPreferenceSummaryOff() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.application_settings, "CheckBoxPreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String summary = XmlParserUtils.getDataSummaryOff(mContext, attrs);
|
||||||
|
String expSummary = mContext.getString(R.string.advanced_settings_summary);
|
||||||
|
assertThat(summary).isEqualTo(expSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataEntriesValid_ReturnsPreferenceEntries() {
|
||||||
|
XmlResourceParser parser = getChildByType(R.xml.application_settings, "ListPreference");
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String entries = XmlParserUtils.getDataEntries(mContext, attrs);
|
||||||
|
String[] expEntries = mContext.getResources()
|
||||||
|
.getStringArray(R.array.app_install_location_entries);
|
||||||
|
for (int i = 0; i < expEntries.length; i++) {
|
||||||
|
assertThat(entries).contains(expEntries[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null checks
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataKeyInvalid_ReturnsNull() {
|
||||||
|
XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String key = XmlParserUtils.getDataKey(mContext, attrs);
|
||||||
|
assertThat(key).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataSummaryInvalid_ReturnsNull() {
|
||||||
|
XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String summary = XmlParserUtils.getDataSummary(mContext, attrs);
|
||||||
|
assertThat(summary).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataSummaryOffInvalid_ReturnsNull() {
|
||||||
|
XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String summaryOff = XmlParserUtils.getDataSummaryOff(mContext, attrs);
|
||||||
|
assertThat(summaryOff).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataEntriesInvalid_ReturnsNull() {
|
||||||
|
XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String entries = XmlParserUtils.getDataEntries(mContext, attrs);
|
||||||
|
assertThat(entries).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resId the ID for the XML preference
|
||||||
|
* @return an XML resource parser that points to the start tag
|
||||||
|
*/
|
||||||
|
private XmlResourceParser getParentPrimedParser(int resId) {
|
||||||
|
XmlResourceParser parser = null;
|
||||||
|
try {
|
||||||
|
parser = mContext.getResources().getXml(resId);
|
||||||
|
|
||||||
|
int type;
|
||||||
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
|
&& type != XmlPullParser.START_TAG) {
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private XmlResourceParser getChildByType(int resId, String xmlType) {
|
||||||
|
XmlResourceParser parser = null;
|
||||||
|
try {
|
||||||
|
parser = mContext.getResources().getXml(resId);
|
||||||
|
|
||||||
|
int type;
|
||||||
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
|
&& type != XmlPullParser.START_TAG) {
|
||||||
|
}
|
||||||
|
while(parser.getName() != xmlType) {
|
||||||
|
parser.next();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user