Loading src/com/android/settings/search/SearchIndexableResources.java +6 −23 Original line number Diff line number Diff line Loading @@ -16,9 +16,7 @@ package com.android.settings.search; import android.provider.SearchIndexableResource; import android.support.annotation.VisibleForTesting; import android.support.annotation.XmlRes; import com.android.settings.DateTimeSettings; import com.android.settings.DeviceInfoSettings; Loading Loading @@ -89,22 +87,17 @@ import com.android.settings.wifi.ConfigureWifiSettings; import com.android.settings.wifi.WifiSettings; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Set; public final class SearchIndexableResources { @XmlRes public static final int NO_RES_ID = 0; @VisibleForTesting static final HashMap<String, SearchIndexableResource> sResMap = new HashMap<>(); static final Set<Class> sProviders = new HashSet<>(); @VisibleForTesting static void addIndex(Class<?> indexClass) { String className = indexClass.getName(); SearchIndexableResource resource = new SearchIndexableResource( 0 /* rank */, NO_RES_ID, className, NO_RES_ID); sResMap.put(className, resource); static void addIndex(Class indexClass) { sProviders.add(indexClass); } static { Loading Loading @@ -180,15 +173,5 @@ public final class SearchIndexableResources { private SearchIndexableResources() { } public static int size() { return sResMap.size(); } public static SearchIndexableResource getResourceByName(String className) { return sResMap.get(className); } public static Collection<SearchIndexableResource> values() { return sResMap.values(); } public static Collection<Class> providerValues() { return sProviders;} } No newline at end of file src/com/android/settings/search/SettingsSearchIndexablesProvider.java +111 −32 Original line number Diff line number Diff line Loading @@ -17,6 +17,19 @@ package com.android.settings.search; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION; Loading @@ -33,11 +46,12 @@ import android.database.Cursor; import android.database.MatrixCursor; import android.provider.SearchIndexableResource; import android.provider.SearchIndexablesProvider; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { Loading @@ -60,8 +74,9 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { @Override public Cursor queryXmlResources(String[] projection) { MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS); Collection<SearchIndexableResource> values = SearchIndexableResources.values(); for (SearchIndexableResource val : values) { final List<SearchIndexableResource> resources = getSearchIndexableResourcesFromProvider(getContext()); for (SearchIndexableResource val : resources) { Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length]; ref[COLUMN_INDEX_XML_RES_RANK] = val.rank; ref[COLUMN_INDEX_XML_RES_RESID] = val.xmlResId; Loading @@ -72,13 +87,33 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = null; // intent target class cursor.addRow(ref); } return cursor; } @Override public Cursor queryRawData(String[] projection) { MatrixCursor result = new MatrixCursor(INDEXABLES_RAW_COLUMNS); return result; MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS); final List<SearchIndexableRaw> raws = getSearchIndexableRawFromProvider(getContext()); for (SearchIndexableRaw val : raws) { Object[] ref = new Object[INDEXABLES_RAW_COLUMNS.length]; ref[COLUMN_INDEX_RAW_TITLE] = val.title; ref[COLUMN_INDEX_RAW_SUMMARY_ON] = val.summaryOn; ref[COLUMN_INDEX_RAW_SUMMARY_OFF] = val.summaryOff; ref[COLUMN_INDEX_RAW_ENTRIES] = val.entries; ref[COLUMN_INDEX_RAW_KEYWORDS] = val.keywords; ref[COLUMN_INDEX_RAW_SCREEN_TITLE] = val.screenTitle; ref[COLUMN_INDEX_RAW_CLASS_NAME] = val.className; ref[COLUMN_INDEX_RAW_ICON_RESID] = val.iconResId; ref[COLUMN_INDEX_RAW_INTENT_ACTION] = val.intentAction; ref[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = val.intentTargetPackage; ref[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = val.intentTargetClass; ref[COLUMN_INDEX_RAW_KEY] = val.key; ref[COLUMN_INDEX_RAW_USER_ID] = val.userId; cursor.addRow(ref); } return cursor; } /** Loading @@ -89,29 +124,24 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { @Override public Cursor queryNonIndexableKeys(String[] projection) { MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS); final Collection<String> values = new HashSet<>(); final Context context = getContext(); for (SearchIndexableResource sir : SearchIndexableResources.values()) { if (DEBUG) { Log.d(TAG, "Getting non-indexable from " + sir.className); } final long startTime = System.currentTimeMillis(); final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className); if (clazz == null) { Log.d(TAG, "SearchIndexableResource '" + sir.className + "' should implement the " + Indexable.class.getName() + " interface!"); continue; final List<String> nonIndexableKeys = getNonIndexableKeysFromProvider(getContext()); for (String nik : nonIndexableKeys) { final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; cursor.addRow(ref); } final Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(clazz); if (provider == null) { Log.d(TAG, "Unable to get SearchIndexableProvider from " + clazz); continue; return cursor; } private List<String> getNonIndexableKeysFromProvider(Context context) { final Collection<Class> values = SearchIndexableResources.providerValues(); final List<String> nonIndexableKeys = new ArrayList<>(); for (Class<?> clazz : values) { final long startTime = System.currentTimeMillis(); Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(context); if (providerNonIndexableKeys == null || providerNonIndexableKeys.isEmpty()) { Loading @@ -123,22 +153,71 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { } if (providerNonIndexableKeys.removeAll(INVALID_KEYS)) { Log.v(TAG, clazz.getName() + " tried to add an empty non-indexable key"); Log.v(TAG, provider + " tried to add an empty non-indexable key"); } if (DEBUG) { final long totalTime = System.currentTimeMillis() - startTime; Log.d(TAG, "Non-indexables " + providerNonIndexableKeys.size() + ", total time " + totalTime); } values.addAll(providerNonIndexableKeys); nonIndexableKeys.addAll(providerNonIndexableKeys); } for (String nik : values) { return nonIndexableKeys; } final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; cursor.addRow(ref); private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) { Collection<Class> values = SearchIndexableResources.providerValues(); List<SearchIndexableResource> resourceList = new ArrayList<>(); for (Class<?> clazz : values) { Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); final List<SearchIndexableResource> resList = provider.getXmlResourcesToIndex(context, true); if (resList == null) { continue; } return cursor; for (SearchIndexableResource item : resList) { item.className = TextUtils.isEmpty(item.className) ? clazz.getName() : item.className; } resourceList.addAll(resList); } return resourceList; } private List<SearchIndexableRaw> getSearchIndexableRawFromProvider(Context context) { final Collection<Class> values = SearchIndexableResources.providerValues(); final List<SearchIndexableRaw> rawList = new ArrayList<>(); for (Class<?> clazz : values) { Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); final List<SearchIndexableRaw> providerRaws = provider.getRawDataToIndex(context, true /* enabled */); if (providerRaws == null) { continue; } for (SearchIndexableRaw raw : providerRaws) { // The classname and intent information comes from the PreIndexData // This will be more clear when provider conversion is done at PreIndex time. raw.className = clazz.getName(); } rawList.addAll(providerRaws); } return rawList; } } src/com/android/settings/search/indexing/IndexDataConverter.java +2 −90 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.util.Xml; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.search.Indexable; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; import com.android.settings.search.XmlParserUtils; Loading Loading @@ -89,22 +88,9 @@ public class IndexDataConverter { final SearchIndexableResource sir = (SearchIndexableResource) data; final Set<String> resourceNonIndexableKeys = getNonIndexableKeysForResource(nonIndexableKeys, sir.packageName); if (sir.xmlResId == 0) { // Index from provider final Indexable.SearchIndexProvider provider = getSearchProvider(sir); if (provider == null) { continue; } indexData.addAll(convertIndexProvider(provider, sir, resourceNonIndexableKeys)); } else { final List<IndexData> resourceData = convertResource(sir, resourceNonIndexableKeys); final List<IndexData> resourceData = convertResource(sir, resourceNonIndexableKeys); indexData.addAll(resourceData); } } } final long endConversion = System.currentTimeMillis(); Loading Loading @@ -305,84 +291,10 @@ public class IndexDataConverter { return resourceIndexData; } private List<IndexData> convertIndexProvider(Indexable.SearchIndexProvider provider, SearchIndexableResource sir, Set<String> nonIndexableKeys) { final List<IndexData> indexData = new ArrayList<>(); final String className = sir.className; final String intentAction = sir.intentAction; final String intentTargetPackage = sir.intentTargetPackage; // TODO (b/65376542) Move provider conversion to PreIndexTime // TODO (b/37741509) Providers don't use general non-indexable keys nonIndexableKeys.addAll(provider.getNonIndexableKeys(mContext)); final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(mContext, true /* enabled */); if (rawList != null) { for (SearchIndexableRaw raw : rawList) { // The classname and intent information comes from the PreIndexData // This will be more clear when provider conversion is done at PreIndex time. raw.className = className; raw.intentAction = intentAction; raw.intentTargetPackage = intentTargetPackage; IndexData.Builder builder = convertRaw(raw, nonIndexableKeys); if (builder != null) { indexData.add(builder.build(mContext)); } } } final List<SearchIndexableResource> resList = provider.getXmlResourcesToIndex(mContext, true); if (resList != null) { for (SearchIndexableResource item : resList) { item.className = TextUtils.isEmpty(item.className) ? className : item.className; item.intentAction = TextUtils.isEmpty(item.intentAction) ? intentAction : item.intentAction; item.intentTargetPackage = TextUtils.isEmpty(item.intentTargetPackage) ? intentTargetPackage : item.intentTargetPackage; indexData.addAll(convertResource(item, nonIndexableKeys)); } } return indexData; } private Set<String> getNonIndexableKeysForResource(Map<String, Set<String>> nonIndexableKeys, String packageName) { return nonIndexableKeys.containsKey(packageName) ? nonIndexableKeys.get(packageName) : new HashSet<>(); } /** * @return Return the {@link Indexable.SearchIndexProvider} corresponding to the * class specified by the Class name specified by {@param sir}. */ private Indexable.SearchIndexProvider getSearchProvider(SearchIndexableResource sir) { if (TextUtils.isEmpty(sir.className)) { Log.w(LOG_TAG, "Cannot index an empty Search Provider name!"); return null; } final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className); if (clazz == null) { Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className + "' should implement the " + Indexable.class.getName() + " interface!"); return null; } // Will be non null only for a Local provider implementing a // SEARCH_INDEX_DATA_PROVIDER field return DatabaseIndexingUtils.getSearchIndexProvider(clazz); } } tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java +1 −2 Original line number Diff line number Diff line Loading @@ -114,11 +114,10 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { continue; } // Must be in SearchProviderRegistry if (SearchIndexableResources.getResourceByName(className) == null) { if (!SearchIndexableResources.providerValues().contains(clazz)) { if (!notInSearchIndexableRegistryGrandfatherList.remove(className)) { notInSearchProviderRegistry.add(className); } continue; } } Loading tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java +26 −28 Original line number Diff line number Diff line Loading @@ -17,12 +17,13 @@ package com.android.settings.search; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; import static com.android.settings.search.SearchIndexableResources.NO_RES_ID; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.fail; import static org.mockito.Mockito.spy; import android.database.Cursor; import android.provider.SearchIndexableResource; import android.text.TextUtils; import com.android.settings.TestConfig; Loading @@ -35,60 +36,48 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; import java.util.HashMap; import java.util.Map; import java.util.HashSet; import java.util.Set; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SearchIndexableResourcesTest { Map<String, SearchIndexableResource> sResMapCopy; Set<Class> sProviderClassCopy; @Before public void setUp() { sResMapCopy = new HashMap<>(SearchIndexableResources.sResMap); sProviderClassCopy = new HashSet<>(SearchIndexableResources.sProviders); } @After public void cleanUp() { SearchIndexableResources.sResMap.clear(); for (String key : sResMapCopy.keySet()) { SearchIndexableResources.sResMap.put(key, sResMapCopy.get(key)); } SearchIndexableResources.sProviders.clear(); SearchIndexableResources.sProviders.addAll(sProviderClassCopy); } @Test public void testAddIndex() { final Class stringClass = java.lang.String.class; // Confirms that String.class isn't contained in SearchIndexableResources. assertThat(SearchIndexableResources.getResourceByName("java.lang.String")).isNull(); final int beforeCount = SearchIndexableResources.values().size(); assertThat(SearchIndexableResources.sProviders).doesNotContain(stringClass); final int beforeCount = SearchIndexableResources.providerValues().size(); SearchIndexableResources.addIndex(java.lang.String.class); final SearchIndexableResource index = SearchIndexableResources .getResourceByName("java.lang.String"); assertThat(index).isNotNull(); assertThat(index.className).isEqualTo("java.lang.String"); assertThat(index.xmlResId).isEqualTo(NO_RES_ID); assertThat(index.iconResId).isEqualTo(NO_RES_ID); final int afterCount = SearchIndexableResources.values().size(); assertThat(SearchIndexableResources.sProviders).contains(stringClass); final int afterCount = SearchIndexableResources.providerValues().size(); assertThat(afterCount).isEqualTo(beforeCount + 1); } @Test public void testIndexHasWifiSettings() { final SearchIndexableResource index = SearchIndexableResources .getResourceByName(WifiSettings.class.getName()); assertThat(index).isNotNull(); assertThat(index.className).isEqualTo(WifiSettings.class.getName()); assertThat(index.xmlResId).isEqualTo(NO_RES_ID); assertThat(index.iconResId).isEqualTo(NO_RES_ID); assertThat(sProviderClassCopy).contains(WifiSettings.class); } @Test public void testNonIndexableKeys_GetsKeyFromProvider() { SearchIndexableResources.sResMap.clear(); SearchIndexableResources.sProviders.clear(); SearchIndexableResources.addIndex(FakeIndexProvider.class); SettingsSearchIndexablesProvider provider = spy(new SettingsSearchIndexablesProvider()); Loading @@ -105,4 +94,13 @@ public class SearchIndexableResourcesTest { assertThat(hasTestKey).isTrue(); } @Test public void testAllClassNamesHaveProviders() { for (Class clazz: sProviderClassCopy) { if(DatabaseIndexingUtils.getSearchIndexProvider(clazz) == null) { fail(clazz.getName() + "is not an index provider"); } } } } Loading
src/com/android/settings/search/SearchIndexableResources.java +6 −23 Original line number Diff line number Diff line Loading @@ -16,9 +16,7 @@ package com.android.settings.search; import android.provider.SearchIndexableResource; import android.support.annotation.VisibleForTesting; import android.support.annotation.XmlRes; import com.android.settings.DateTimeSettings; import com.android.settings.DeviceInfoSettings; Loading Loading @@ -89,22 +87,17 @@ import com.android.settings.wifi.ConfigureWifiSettings; import com.android.settings.wifi.WifiSettings; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Set; public final class SearchIndexableResources { @XmlRes public static final int NO_RES_ID = 0; @VisibleForTesting static final HashMap<String, SearchIndexableResource> sResMap = new HashMap<>(); static final Set<Class> sProviders = new HashSet<>(); @VisibleForTesting static void addIndex(Class<?> indexClass) { String className = indexClass.getName(); SearchIndexableResource resource = new SearchIndexableResource( 0 /* rank */, NO_RES_ID, className, NO_RES_ID); sResMap.put(className, resource); static void addIndex(Class indexClass) { sProviders.add(indexClass); } static { Loading Loading @@ -180,15 +173,5 @@ public final class SearchIndexableResources { private SearchIndexableResources() { } public static int size() { return sResMap.size(); } public static SearchIndexableResource getResourceByName(String className) { return sResMap.get(className); } public static Collection<SearchIndexableResource> values() { return sResMap.values(); } public static Collection<Class> providerValues() { return sProviders;} } No newline at end of file
src/com/android/settings/search/SettingsSearchIndexablesProvider.java +111 −32 Original line number Diff line number Diff line Loading @@ -17,6 +17,19 @@ package com.android.settings.search; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION; Loading @@ -33,11 +46,12 @@ import android.database.Cursor; import android.database.MatrixCursor; import android.provider.SearchIndexableResource; import android.provider.SearchIndexablesProvider; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { Loading @@ -60,8 +74,9 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { @Override public Cursor queryXmlResources(String[] projection) { MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS); Collection<SearchIndexableResource> values = SearchIndexableResources.values(); for (SearchIndexableResource val : values) { final List<SearchIndexableResource> resources = getSearchIndexableResourcesFromProvider(getContext()); for (SearchIndexableResource val : resources) { Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length]; ref[COLUMN_INDEX_XML_RES_RANK] = val.rank; ref[COLUMN_INDEX_XML_RES_RESID] = val.xmlResId; Loading @@ -72,13 +87,33 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = null; // intent target class cursor.addRow(ref); } return cursor; } @Override public Cursor queryRawData(String[] projection) { MatrixCursor result = new MatrixCursor(INDEXABLES_RAW_COLUMNS); return result; MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS); final List<SearchIndexableRaw> raws = getSearchIndexableRawFromProvider(getContext()); for (SearchIndexableRaw val : raws) { Object[] ref = new Object[INDEXABLES_RAW_COLUMNS.length]; ref[COLUMN_INDEX_RAW_TITLE] = val.title; ref[COLUMN_INDEX_RAW_SUMMARY_ON] = val.summaryOn; ref[COLUMN_INDEX_RAW_SUMMARY_OFF] = val.summaryOff; ref[COLUMN_INDEX_RAW_ENTRIES] = val.entries; ref[COLUMN_INDEX_RAW_KEYWORDS] = val.keywords; ref[COLUMN_INDEX_RAW_SCREEN_TITLE] = val.screenTitle; ref[COLUMN_INDEX_RAW_CLASS_NAME] = val.className; ref[COLUMN_INDEX_RAW_ICON_RESID] = val.iconResId; ref[COLUMN_INDEX_RAW_INTENT_ACTION] = val.intentAction; ref[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = val.intentTargetPackage; ref[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = val.intentTargetClass; ref[COLUMN_INDEX_RAW_KEY] = val.key; ref[COLUMN_INDEX_RAW_USER_ID] = val.userId; cursor.addRow(ref); } return cursor; } /** Loading @@ -89,29 +124,24 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { @Override public Cursor queryNonIndexableKeys(String[] projection) { MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS); final Collection<String> values = new HashSet<>(); final Context context = getContext(); for (SearchIndexableResource sir : SearchIndexableResources.values()) { if (DEBUG) { Log.d(TAG, "Getting non-indexable from " + sir.className); } final long startTime = System.currentTimeMillis(); final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className); if (clazz == null) { Log.d(TAG, "SearchIndexableResource '" + sir.className + "' should implement the " + Indexable.class.getName() + " interface!"); continue; final List<String> nonIndexableKeys = getNonIndexableKeysFromProvider(getContext()); for (String nik : nonIndexableKeys) { final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; cursor.addRow(ref); } final Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(clazz); if (provider == null) { Log.d(TAG, "Unable to get SearchIndexableProvider from " + clazz); continue; return cursor; } private List<String> getNonIndexableKeysFromProvider(Context context) { final Collection<Class> values = SearchIndexableResources.providerValues(); final List<String> nonIndexableKeys = new ArrayList<>(); for (Class<?> clazz : values) { final long startTime = System.currentTimeMillis(); Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(context); if (providerNonIndexableKeys == null || providerNonIndexableKeys.isEmpty()) { Loading @@ -123,22 +153,71 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { } if (providerNonIndexableKeys.removeAll(INVALID_KEYS)) { Log.v(TAG, clazz.getName() + " tried to add an empty non-indexable key"); Log.v(TAG, provider + " tried to add an empty non-indexable key"); } if (DEBUG) { final long totalTime = System.currentTimeMillis() - startTime; Log.d(TAG, "Non-indexables " + providerNonIndexableKeys.size() + ", total time " + totalTime); } values.addAll(providerNonIndexableKeys); nonIndexableKeys.addAll(providerNonIndexableKeys); } for (String nik : values) { return nonIndexableKeys; } final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; cursor.addRow(ref); private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) { Collection<Class> values = SearchIndexableResources.providerValues(); List<SearchIndexableResource> resourceList = new ArrayList<>(); for (Class<?> clazz : values) { Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); final List<SearchIndexableResource> resList = provider.getXmlResourcesToIndex(context, true); if (resList == null) { continue; } return cursor; for (SearchIndexableResource item : resList) { item.className = TextUtils.isEmpty(item.className) ? clazz.getName() : item.className; } resourceList.addAll(resList); } return resourceList; } private List<SearchIndexableRaw> getSearchIndexableRawFromProvider(Context context) { final Collection<Class> values = SearchIndexableResources.providerValues(); final List<SearchIndexableRaw> rawList = new ArrayList<>(); for (Class<?> clazz : values) { Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider( clazz); final List<SearchIndexableRaw> providerRaws = provider.getRawDataToIndex(context, true /* enabled */); if (providerRaws == null) { continue; } for (SearchIndexableRaw raw : providerRaws) { // The classname and intent information comes from the PreIndexData // This will be more clear when provider conversion is done at PreIndex time. raw.className = clazz.getName(); } rawList.addAll(providerRaws); } return rawList; } }
src/com/android/settings/search/indexing/IndexDataConverter.java +2 −90 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.util.Xml; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.search.DatabaseIndexingUtils; import com.android.settings.search.Indexable; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; import com.android.settings.search.XmlParserUtils; Loading Loading @@ -89,22 +88,9 @@ public class IndexDataConverter { final SearchIndexableResource sir = (SearchIndexableResource) data; final Set<String> resourceNonIndexableKeys = getNonIndexableKeysForResource(nonIndexableKeys, sir.packageName); if (sir.xmlResId == 0) { // Index from provider final Indexable.SearchIndexProvider provider = getSearchProvider(sir); if (provider == null) { continue; } indexData.addAll(convertIndexProvider(provider, sir, resourceNonIndexableKeys)); } else { final List<IndexData> resourceData = convertResource(sir, resourceNonIndexableKeys); final List<IndexData> resourceData = convertResource(sir, resourceNonIndexableKeys); indexData.addAll(resourceData); } } } final long endConversion = System.currentTimeMillis(); Loading Loading @@ -305,84 +291,10 @@ public class IndexDataConverter { return resourceIndexData; } private List<IndexData> convertIndexProvider(Indexable.SearchIndexProvider provider, SearchIndexableResource sir, Set<String> nonIndexableKeys) { final List<IndexData> indexData = new ArrayList<>(); final String className = sir.className; final String intentAction = sir.intentAction; final String intentTargetPackage = sir.intentTargetPackage; // TODO (b/65376542) Move provider conversion to PreIndexTime // TODO (b/37741509) Providers don't use general non-indexable keys nonIndexableKeys.addAll(provider.getNonIndexableKeys(mContext)); final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(mContext, true /* enabled */); if (rawList != null) { for (SearchIndexableRaw raw : rawList) { // The classname and intent information comes from the PreIndexData // This will be more clear when provider conversion is done at PreIndex time. raw.className = className; raw.intentAction = intentAction; raw.intentTargetPackage = intentTargetPackage; IndexData.Builder builder = convertRaw(raw, nonIndexableKeys); if (builder != null) { indexData.add(builder.build(mContext)); } } } final List<SearchIndexableResource> resList = provider.getXmlResourcesToIndex(mContext, true); if (resList != null) { for (SearchIndexableResource item : resList) { item.className = TextUtils.isEmpty(item.className) ? className : item.className; item.intentAction = TextUtils.isEmpty(item.intentAction) ? intentAction : item.intentAction; item.intentTargetPackage = TextUtils.isEmpty(item.intentTargetPackage) ? intentTargetPackage : item.intentTargetPackage; indexData.addAll(convertResource(item, nonIndexableKeys)); } } return indexData; } private Set<String> getNonIndexableKeysForResource(Map<String, Set<String>> nonIndexableKeys, String packageName) { return nonIndexableKeys.containsKey(packageName) ? nonIndexableKeys.get(packageName) : new HashSet<>(); } /** * @return Return the {@link Indexable.SearchIndexProvider} corresponding to the * class specified by the Class name specified by {@param sir}. */ private Indexable.SearchIndexProvider getSearchProvider(SearchIndexableResource sir) { if (TextUtils.isEmpty(sir.className)) { Log.w(LOG_TAG, "Cannot index an empty Search Provider name!"); return null; } final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className); if (clazz == null) { Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className + "' should implement the " + Indexable.class.getName() + " interface!"); return null; } // Will be non null only for a Local provider implementing a // SEARCH_INDEX_DATA_PROVIDER field return DatabaseIndexingUtils.getSearchIndexProvider(clazz); } }
tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java +1 −2 Original line number Diff line number Diff line Loading @@ -114,11 +114,10 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { continue; } // Must be in SearchProviderRegistry if (SearchIndexableResources.getResourceByName(className) == null) { if (!SearchIndexableResources.providerValues().contains(clazz)) { if (!notInSearchIndexableRegistryGrandfatherList.remove(className)) { notInSearchProviderRegistry.add(className); } continue; } } Loading
tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java +26 −28 Original line number Diff line number Diff line Loading @@ -17,12 +17,13 @@ package com.android.settings.search; import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; import static com.android.settings.search.SearchIndexableResources.NO_RES_ID; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.fail; import static org.mockito.Mockito.spy; import android.database.Cursor; import android.provider.SearchIndexableResource; import android.text.TextUtils; import com.android.settings.TestConfig; Loading @@ -35,60 +36,48 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; import java.util.HashMap; import java.util.Map; import java.util.HashSet; import java.util.Set; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SearchIndexableResourcesTest { Map<String, SearchIndexableResource> sResMapCopy; Set<Class> sProviderClassCopy; @Before public void setUp() { sResMapCopy = new HashMap<>(SearchIndexableResources.sResMap); sProviderClassCopy = new HashSet<>(SearchIndexableResources.sProviders); } @After public void cleanUp() { SearchIndexableResources.sResMap.clear(); for (String key : sResMapCopy.keySet()) { SearchIndexableResources.sResMap.put(key, sResMapCopy.get(key)); } SearchIndexableResources.sProviders.clear(); SearchIndexableResources.sProviders.addAll(sProviderClassCopy); } @Test public void testAddIndex() { final Class stringClass = java.lang.String.class; // Confirms that String.class isn't contained in SearchIndexableResources. assertThat(SearchIndexableResources.getResourceByName("java.lang.String")).isNull(); final int beforeCount = SearchIndexableResources.values().size(); assertThat(SearchIndexableResources.sProviders).doesNotContain(stringClass); final int beforeCount = SearchIndexableResources.providerValues().size(); SearchIndexableResources.addIndex(java.lang.String.class); final SearchIndexableResource index = SearchIndexableResources .getResourceByName("java.lang.String"); assertThat(index).isNotNull(); assertThat(index.className).isEqualTo("java.lang.String"); assertThat(index.xmlResId).isEqualTo(NO_RES_ID); assertThat(index.iconResId).isEqualTo(NO_RES_ID); final int afterCount = SearchIndexableResources.values().size(); assertThat(SearchIndexableResources.sProviders).contains(stringClass); final int afterCount = SearchIndexableResources.providerValues().size(); assertThat(afterCount).isEqualTo(beforeCount + 1); } @Test public void testIndexHasWifiSettings() { final SearchIndexableResource index = SearchIndexableResources .getResourceByName(WifiSettings.class.getName()); assertThat(index).isNotNull(); assertThat(index.className).isEqualTo(WifiSettings.class.getName()); assertThat(index.xmlResId).isEqualTo(NO_RES_ID); assertThat(index.iconResId).isEqualTo(NO_RES_ID); assertThat(sProviderClassCopy).contains(WifiSettings.class); } @Test public void testNonIndexableKeys_GetsKeyFromProvider() { SearchIndexableResources.sResMap.clear(); SearchIndexableResources.sProviders.clear(); SearchIndexableResources.addIndex(FakeIndexProvider.class); SettingsSearchIndexablesProvider provider = spy(new SettingsSearchIndexablesProvider()); Loading @@ -105,4 +94,13 @@ public class SearchIndexableResourcesTest { assertThat(hasTestKey).isTrue(); } @Test public void testAllClassNamesHaveProviders() { for (Class clazz: sProviderClassCopy) { if(DatabaseIndexingUtils.getSearchIndexProvider(clazz) == null) { fail(clazz.getName() + "is not an index provider"); } } } }