Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2260321f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move Index provider conversion into Settings provider"

parents c7652b99 55ce64dc
Loading
Loading
Loading
Loading
+6 −23
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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
+111 −32
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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;
@@ -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;
    }

    /**
@@ -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()) {
@@ -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;
    }
}
+2 −90
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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);
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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;
            }
        }

+26 −28
Original line number Diff line number Diff line
@@ -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;
@@ -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());
@@ -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