diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java index 65c2d4c524f..a5e5c3e7267 100644 --- a/src/com/android/settings/nfc/NfcPreferenceController.java +++ b/src/com/android/settings/nfc/NfcPreferenceController.java @@ -44,7 +44,6 @@ public class NfcPreferenceController extends PreferenceController private NfcEnabler mNfcEnabler; private NfcAdapter mNfcAdapter; - private final Handler mHandler = new Handler(); private int mAirplaneMode; private AirplaneModeObserver mAirplaneModeObserver; private SwitchPreference mNfcPreference; @@ -146,7 +145,7 @@ public class NfcPreferenceController extends PreferenceController Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON); private AirplaneModeObserver() { - super(mHandler); + super(new Handler()); } public void register() { diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 4f9f92cda45..489f20fb856 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -86,7 +86,8 @@ public final class SearchIndexableResources { @XmlRes public static final int NO_DATA_RES_ID = 0; - private static final HashMap sResMap = new HashMap<>(); + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + static final HashMap sResMap = new HashMap<>(); @VisibleForTesting static void addIndex(Class indexClass, @XmlRes int xmlResId, diff --git a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java index b2be146fb0f..b83f9fd0f66 100644 --- a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java +++ b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java @@ -16,13 +16,20 @@ package com.android.settings.search; +import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.provider.SearchIndexableResource; import android.provider.SearchIndexablesProvider; +import android.util.Log; + +import com.android.settings.search2.DatabaseIndexingUtils; import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE; 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; @@ -35,7 +42,7 @@ import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUM import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS; public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { - private static final String TAG = "SettingsSearchIndexablesProvider"; + private static final String TAG = "SettingsSearchProvider"; @Override public boolean onCreate() { @@ -47,7 +54,7 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS); Collection values = SearchIndexableResources.values(); for (SearchIndexableResource val : values) { - Object[] ref = new Object[7]; + 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; ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = val.className; @@ -66,9 +73,45 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { return result; } + /** + * Gets a combined list non-indexable keys that come from providers inside of settings. + * The non-indexable keys are used in Settings search at both index and update time to verify + * the validity of results in the database. + */ @Override public Cursor queryNonIndexableKeys(String[] projection) { MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS); + final Collection values = new HashSet<>(); + final Context context = getContext(); + + for (SearchIndexableResource sir : SearchIndexableResources.values()) { + 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 Indexable.SearchIndexProvider provider = + DatabaseIndexingUtils.getSearchIndexProvider(clazz); + + if (provider == null) { + Log.d(TAG, "Unable to get SearchIndexableProvider from " + + Indexable.class.getName()); + continue; + } + + List providerNonIndexableKeys = provider.getNonIndexableKeys(context); + if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) { + 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); + } return cursor; } } diff --git a/tests/robotests/src/com/android/settings/search/FakeIndexProvider.java b/tests/robotests/src/com/android/settings/search/FakeIndexProvider.java new file mode 100644 index 00000000000..35486ef59f5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/search/FakeIndexProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.settings.search; + +import android.content.Context; +import android.provider.SearchIndexableResource; +import com.android.settings.core.PreferenceController; + +import java.util.ArrayList; +import java.util.List; + +public class FakeIndexProvider implements Indexable { + + public static final String KEY = "TestKey"; + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex(Context context, + boolean enabled) { + return null; + } + + @Override + public List getNonIndexableKeys(Context context) { + ArrayList result = new ArrayList<>(); + result.add(KEY); + return result; + } + + @Override + public List getPreferenceControllers(Context context) { + return null; + } + }; + +} diff --git a/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java b/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java index efb5cbc3d19..62bb7fb042f 100644 --- a/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java @@ -16,14 +16,20 @@ 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_DATA_RES_ID; +import static com.android.settings.search.SearchIndexableResources.sResMap; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; import android.annotation.DrawableRes; import android.annotation.XmlRes; +import android.database.Cursor; import android.provider.SearchIndexableResource; +import android.text.TextUtils; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; @@ -31,8 +37,11 @@ import com.android.settings.wifi.WifiSettings; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import java.util.HashMap; + @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SearchIndexableResourcesTest { @@ -72,4 +81,24 @@ public class SearchIndexableResourcesTest { assertThat(index.xmlResId).isEqualTo(NO_DATA_RES_ID); assertThat(index.iconResId).isEqualTo(R.drawable.ic_settings_wireless); } + + @Test + public void testNonIndexableKeys_GetsKeyFromProvider() { + SearchIndexableResources.sResMap.clear(); + SearchIndexableResources.addIndex(FakeIndexProvider.class, 0, 0); + + SettingsSearchIndexablesProvider provider = spy(new SettingsSearchIndexablesProvider()); + + Cursor cursor = provider.queryNonIndexableKeys(null); + boolean hasTestKey = false; + while(cursor.moveToNext()) { + String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE); + if (TextUtils.equals(key, FakeIndexProvider.KEY)) { + hasTestKey = true; + break; + } + } + + assertThat(hasTestKey).isTrue(); + } }