diff --git a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java index b83f9fd0f66..1bf0a153f7e 100644 --- a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java +++ b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java @@ -26,6 +26,7 @@ import android.util.Log; import com.android.settings.search2.DatabaseIndexingUtils; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -102,12 +103,21 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { } List providerNonIndexableKeys = provider.getNonIndexableKeys(context); - if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) { - values.addAll(providerNonIndexableKeys); + + if (providerNonIndexableKeys == null || providerNonIndexableKeys.isEmpty()) { + continue; } + + if (providerNonIndexableKeys.removeAll(Collections.singleton(null)) + || providerNonIndexableKeys.removeAll(Collections.singleton(""))) { + Log.v(TAG, clazz.getName() + " tried to add an empty non-indexable key"); + } + + values.addAll(providerNonIndexableKeys); } for (String nik : values) { + final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length]; ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik; cursor.addRow(ref); diff --git a/src/com/android/settings/search2/DatabaseIndexingManager.java b/src/com/android/settings/search2/DatabaseIndexingManager.java index ccc52838b98..80ae54fd7ae 100644 --- a/src/com/android/settings/search2/DatabaseIndexingManager.java +++ b/src/com/android/settings/search2/DatabaseIndexingManager.java @@ -426,6 +426,13 @@ public class DatabaseIndexingManager { if (count > 0) { while (cursor.moveToNext()) { final String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE); + + if (TextUtils.isEmpty(key) && Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + Log.v(LOG_TAG, "Empty non-indexable key from: " + + packageContext.getPackageName()); + continue; + } + result.add(key); } } diff --git a/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java b/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java index 047d867ac39..7bbda0fe2f0 100644 --- a/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java +++ b/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java @@ -31,9 +31,7 @@ import android.database.MatrixCursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Build; -import android.provider.SearchIndexableData; import android.provider.SearchIndexableResource; -import android.provider.SearchIndexablesContract; import android.util.ArrayMap; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; @@ -62,6 +60,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; @@ -69,6 +68,7 @@ import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -903,7 +903,7 @@ public class DatabaseIndexingManagerTest { } @Test - public void testUpdateDataInDatabase_DisabledResultsAreIndexable_BecomeEnabled() { + public void testUpdateDataInDatabase_disabledResultsAreIndexable_becomeEnabled() { // Both results are initially disabled, and then TITLE_TWO gets enabled. final boolean enabled = false; insertSpecialCase(TITLE_ONE, enabled, KEY_ONE); @@ -921,6 +921,18 @@ public class DatabaseIndexingManagerTest { assertThat(cursor.getString(2)).isEqualTo(TITLE_TWO); } + @Test + @Config(shadows = {ShadowContentResolver.class}) + public void testEmptyNonIndexableKeys_emptyDataKeyResources_addedToDatabase() { + insertSpecialCase(TITLE_ONE, true /* enabled */, null /* dataReferenceKey */); + + mManager.updateDatabase(false, localeStr); + + Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null); + cursor.moveToPosition(0); + assertThat(cursor.getCount()).isEqualTo(1); + assertThat(cursor.getString(2)).isEqualTo(TITLE_ONE); + } // Util functions private SearchIndexableRaw getFakeRaw() { @@ -986,11 +998,11 @@ public class DatabaseIndexingManagerTest { // TODO move this method and its counterpart in CursorToSearchResultConverterTest into // a util class with public fields to assert values. private Cursor getDummyCursor() { - MatrixCursor cursor = new MatrixCursor(SearchIndexablesContract.INDEXABLES_RAW_COLUMNS); + MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS); final String BLANK = ""; ArrayList item = - new ArrayList<>(SearchIndexablesContract.INDEXABLES_RAW_COLUMNS.length); + new ArrayList<>(INDEXABLES_RAW_COLUMNS.length); item.add("42"); // Rank item.add(TITLE_ONE); // Title item.add(BLANK); // Summary on diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java index 6ae695b97f6..36f170ab8e2 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java @@ -19,9 +19,15 @@ package com.android.settings.testutils.shadow; import android.content.ContentResolver; import android.content.SyncAdapterType; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.net.Uri; +import android.provider.SearchIndexablesContract; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; + @Implements(ContentResolver.class) public class ShadowContentResolver { @@ -29,4 +35,13 @@ public class ShadowContentResolver { public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { return new SyncAdapterType[0]; } + + @Implementation + public final Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS); + MatrixCursor.RowBuilder builder = cursor.newRow() + .add(SearchIndexablesContract.NonIndexableKey.COLUMN_KEY_VALUE, ""); + return cursor; + } }