From c1c708f979fc2838efa729cde971121b60ce4e40 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 1 Mar 2017 11:48:27 -0800 Subject: [PATCH] Ensure DashboardFragment shares pref controlls with search Test: make RunSettingsRoboTests Change-Id: I48be270d9706539925d00874bae29d46406ac491 Fix: 35812240 --- .../BuildNumberPreferenceController.java | 2 +- .../EmergencyBroadcastPreferenceController.java | 2 +- ...t_sharing_pref_controllers_with_search_provider | 11 ++++ .../DashboardFeatureProviderImplTest.java | 5 +- ...hboardFragmentSearchIndexProviderInspector.java | 74 ++++++++++++++++++++++ .../BuildNumberPreferenceControllerTest.java | 2 + .../search/SearchIndexProviderCodeInspector.java | 55 ++++++++++++---- 7 files changed, 136 insertions(+), 15 deletions(-) create mode 100644 tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider create mode 100644 tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java index 6c492cc01d..d6fe1aa03b 100644 --- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java @@ -67,7 +67,7 @@ public class BuildNumberPreferenceController extends PreferenceController super(context); mActivity = activity; mFragment = fragment; - mUm = UserManager.get(context); + mUm = (UserManager) context.getSystemService(Context.USER_SERVICE); mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); if (lifecycle != null) { lifecycle.addObserver(this); diff --git a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java index 1154493805..8f26ed8247 100644 --- a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java +++ b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java @@ -48,7 +48,7 @@ public class EmergencyBroadcastPreferenceController extends PreferenceController EmergencyBroadcastPreferenceController(Context context, AccountRestrictionHelper helper) { super(context); mHelper = helper; - mUserManager = UserManager.get(context); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mPm = mContext.getPackageManager(); // Enable link to CMAS app settings depending on the value in config.xml. mCellBroadcastAppLinkEnabled = isCellBroadcastAppLinkEnabled(); diff --git a/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider new file mode 100644 index 0000000000..cb04679fc4 --- /dev/null +++ b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider @@ -0,0 +1,11 @@ +com.android.settings.gestures.PickupGestureSettings +com.android.settings.language.LanguageAndInputSettings +com.android.settings.enterprise.EnterprisePrivacySettings +com.android.settings.gestures.DoubleTapScreenSettings +com.android.settings.applications.AdvancedAppSettings +com.android.settings.gestures.AssistGestureSettings +com.android.settings.fuelgauge.PowerUsageSummary +com.android.settings.gestures.SwipeToNotificationSettings +com.android.settings.inputmethod.InputMethodAndLanguageSettings +com.android.settings.gestures.DoubleTapPowerSettings +com.android.settings.gestures.DoubleTwistGestureSettings \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java index 8e46343264..5902ec020a 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java @@ -32,6 +32,7 @@ import com.android.settings.SettingsActivity; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settingslib.drawer.CategoryKey; import com.android.settingslib.drawer.CategoryManager; import com.android.settingslib.drawer.DashboardCategory; @@ -62,7 +63,9 @@ import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION, + shadows = ShadowUserManager.class) public class DashboardFeatureProviderImplTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java new file mode 100644 index 0000000000..6b22f7b544 --- /dev/null +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java @@ -0,0 +1,74 @@ +/* + * 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.dashboard; + +import android.app.Fragment; +import android.content.Context; + +import com.android.settings.core.PreferenceController; +import com.android.settings.search.Indexable; +import com.android.settings.search2.DatabaseIndexingUtils; + +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +public class DashboardFragmentSearchIndexProviderInspector { + + public static boolean isSharingPreferenceControllers(Class clazz) { + final Context context = RuntimeEnvironment.application; + final Fragment fragment; + try { + fragment = Fragment.instantiate(context, clazz.getName()); + } catch (Throwable e) { + // Can't do much with exception, assume the test passed. + return true; + } + if (!(fragment instanceof DashboardFragment)) { + return true; + } + + final Indexable.SearchIndexProvider provider = + DatabaseIndexingUtils.getSearchIndexProvider(clazz); + if (provider == null) { + return true; + } + final List controllersFromSearchIndexProvider; + final List controllersFromFragment; + try { + controllersFromSearchIndexProvider = provider.getPreferenceControllers(context); + } catch (Throwable e) { + // Can't do much with exception, assume the test passed. + return true; + } + try { + controllersFromFragment = + ((DashboardFragment) fragment).getPreferenceControllers(context); + } catch (Throwable e) { + // Can't do much with exception, assume the test passed. + return true; + } + + if (controllersFromFragment == controllersFromSearchIndexProvider) { + return true; + } else if (controllersFromFragment != null && controllersFromSearchIndexProvider != null) { + return controllersFromFragment.size() == controllersFromSearchIndexProvider.size(); + } else { + return false; + } + } +} diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java index 0a74cc44ba..5455b13b18 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java @@ -47,6 +47,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -117,6 +118,7 @@ public class BuildNumberPreferenceControllerTest { mController = new BuildNumberPreferenceController( context, mActivity, mFragment, mLifecycle); ReflectionHelpers.setField(mController, "mContext", context); + ReflectionHelpers.setField(mController, "mUm", mUserManager); assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); verify(mFactory.metricsFeatureProvider).action( diff --git a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java index 3c820ec241..801b50964f 100644 --- a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java +++ b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java @@ -21,6 +21,7 @@ import android.util.Log; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.codeinspection.CodeInspector; +import com.android.settings.dashboard.DashboardFragmentSearchIndexProviderInspector; import java.lang.reflect.Field; import java.util.ArrayList; @@ -40,6 +41,9 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { private static final String NOT_CONTAINING_PROVIDER_OBJECT_ERROR = "Indexable should have public field " + Index.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + " but these are not:\n"; + private static final String NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER = + "DashboardFragment should share pref controllers with its SearchIndexProvider, but " + + " these are not: \n"; private static final String NOT_IN_INDEXABLE_PROVIDER_REGISTRY = "Class containing " + Index.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + " must be added to " + SearchIndexableResources.class.getName() + " but these are not: \n"; @@ -47,18 +51,22 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { private final List notImplementingIndexableGrandfatherList; private final List notImplementingIndexProviderGrandfatherList; private final List notInSearchIndexableRegistryGrandfatherList; + private final List notSharingPrefControllersGrandfatherList; public SearchIndexProviderCodeInspector(List> classes) { super(classes); notImplementingIndexableGrandfatherList = new ArrayList<>(); notImplementingIndexProviderGrandfatherList = new ArrayList<>(); notInSearchIndexableRegistryGrandfatherList = new ArrayList<>(); + notSharingPrefControllersGrandfatherList = new ArrayList<>(); initializeGrandfatherList(notImplementingIndexableGrandfatherList, "grandfather_not_implementing_indexable"); initializeGrandfatherList(notImplementingIndexProviderGrandfatherList, "grandfather_not_implementing_index_provider"); initializeGrandfatherList(notInSearchIndexableRegistryGrandfatherList, "grandfather_not_in_search_index_provider_registry"); + initializeGrandfatherList(notSharingPrefControllersGrandfatherList, + "grandfather_not_sharing_pref_controllers_with_search_provider"); } @Override @@ -66,6 +74,7 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { final Set notImplementingIndexable = new ArraySet<>(); final Set notImplementingIndexProvider = new ArraySet<>(); final Set notInSearchProviderRegistry = new ArraySet<>(); + final Set notSharingPreferenceControllers = new ArraySet<>(); for (Class clazz : mClasses) { if (!isConcreteSettingsClass(clazz)) { @@ -78,20 +87,36 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { } // If it's a SettingsPreferenceFragment, it must also be Indexable. final boolean implementsIndexable = Indexable.class.isAssignableFrom(clazz); - if (!implementsIndexable - && !notImplementingIndexableGrandfatherList.contains(className)) { - notImplementingIndexable.add(className); + if (!implementsIndexable) { + if (!notImplementingIndexableGrandfatherList.contains(className)) { + notImplementingIndexable.add(className); + } + continue; } final boolean hasSearchIndexProvider = hasSearchIndexProvider(clazz); // If it implements Indexable, it must also implement the index provider field. - if (implementsIndexable && !hasSearchIndexProvider - && !notImplementingIndexProviderGrandfatherList.contains(className)) { - notImplementingIndexProvider.add(className); + if (!hasSearchIndexProvider) { + if (!notImplementingIndexProviderGrandfatherList.contains(className)) { + notImplementingIndexProvider.add(className); + } + continue; + } + // If it implements index provider field AND it's a DashboardFragment, its fragment and + // search provider must share the same set of PreferenceControllers. + final boolean isSharingPrefControllers = DashboardFragmentSearchIndexProviderInspector + .isSharingPreferenceControllers(clazz); + if (!isSharingPrefControllers) { + if (!notSharingPrefControllersGrandfatherList.contains(className)) { + notSharingPreferenceControllers.add(className); + } + continue; } - if (hasSearchIndexProvider - && SearchIndexableResources.getResourceByName(className) == null - && !notInSearchIndexableRegistryGrandfatherList.contains(className)) { - notInSearchProviderRegistry.add(className); + // Must be in SearchProviderRegistry + if (SearchIndexableResources.getResourceByName(className) == null) { + if (!notInSearchIndexableRegistryGrandfatherList.contains(className)) { + notInSearchProviderRegistry.add(className); + } + continue; } } @@ -100,15 +125,21 @@ public class SearchIndexProviderCodeInspector extends CodeInspector { notImplementingIndexable); final String indexProviderError = buildErrorMessage(NOT_CONTAINING_PROVIDER_OBJECT_ERROR, notImplementingIndexProvider); + final String notSharingPrefControllerError = buildErrorMessage( + NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER, + notSharingPreferenceControllers); final String notInProviderRegistryError = buildErrorMessage(NOT_IN_INDEXABLE_PROVIDER_REGISTRY, notInSearchProviderRegistry); assertWithMessage(indexableError) .that(notImplementingIndexable) .isEmpty(); - assertWithMessage(indexProviderError.toString()) + assertWithMessage(indexProviderError) .that(notImplementingIndexProvider) .isEmpty(); - assertWithMessage(notInProviderRegistryError.toString()) + assertWithMessage(notSharingPrefControllerError) + .that(notSharingPreferenceControllers) + .isEmpty(); + assertWithMessage(notInProviderRegistryError) .that(notInSearchProviderRegistry) .isEmpty(); } -- 2.11.0