From 92751770025e75552714653deb160454f518699c Mon Sep 17 00:00:00 2001 From: Ben Lin Date: Thu, 21 Dec 2017 17:32:34 -0800 Subject: [PATCH] Change underlying preferenceControllers to an ArrayMap of Lists. Previously, DashboardFragment stores preference controllers in an ArrayMap of . Thus when there are multiple controllers of same class (ie. multiple PreferenceCategoryControllers), they cannot be stored simultaneously. This changes the value to a List so we can store multiple controllers of the same Class without extraneous sub-classing. Bug: 70949662 Test: All existing tests still pass. Added DashboardFragmentTest#testPreferenceControllerSetter_shouldAddAndNotReplace and DashboardFragmentTest#updateState_doesNotSkipControllersOfSameClass. Change-Id: I397e8c91977ea1180d48a3af75dd4058bf1175c0 --- .../settings/dashboard/DashboardFragment.java | 63 ++++++++++++------- .../dashboard/DashboardFragmentTest.java | 30 +++++++++ .../screenlock/ScreenLockSettingsTest.java | 8 ++- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java index 3e1e8818568..6a88a38c99b 100644 --- a/src/com/android/settings/dashboard/DashboardFragment.java +++ b/src/com/android/settings/dashboard/DashboardFragment.java @@ -54,7 +54,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment SummaryLoader.SummaryConsumer { private static final String TAG = "DashboardFragment"; - private final Map mPreferenceControllers = + private final Map> mPreferenceControllers = new ArrayMap<>(); private final Set mDashboardTilePrefKeys = new ArraySet<>(); @@ -156,14 +156,17 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment @Override public boolean onPreferenceTreeClick(Preference preference) { - Collection controllers = mPreferenceControllers.values(); + Collection> controllers = + mPreferenceControllers.values(); // If preference contains intent, log it before handling. mMetricsFeatureProvider.logDashboardStartIntent( getContext(), preference.getIntent(), getMetricsCategory()); // Give all controllers a chance to handle click. - for (AbstractPreferenceController controller : controllers) { - if (controller.handlePreferenceTreeClick(preference)) { - return true; + for (List controllerList : controllers) { + for (AbstractPreferenceController controller : controllerList) { + if (controller.handlePreferenceTreeClick(preference)) { + return true; + } } } return super.onPreferenceTreeClick(preference); @@ -189,12 +192,23 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment protected abstract int getPreferenceScreenResId(); protected T getPreferenceController(Class clazz) { - AbstractPreferenceController controller = mPreferenceControllers.get(clazz); - return (T) controller; + List controllerList = mPreferenceControllers.get(clazz); + if (controllerList != null) { + if (controllerList.size() > 1) { + Log.w(TAG, "Multiple controllers of Class " + clazz.getSimpleName() + + " found, returning first one."); + } + return (T) controllerList.get(0); + } + + return null; } protected void addPreferenceController(AbstractPreferenceController controller) { - mPreferenceControllers.put(controller.getClass(), controller); + if (mPreferenceControllers.get(controller.getClass()) == null) { + mPreferenceControllers.put(controller.getClass(), new ArrayList<>()); + } + mPreferenceControllers.get(controller.getClass()).add(controller); } /** @@ -249,31 +263,32 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } addPreferencesFromResource(resId); final PreferenceScreen screen = getPreferenceScreen(); - Collection controllers = mPreferenceControllers.values(); - for (AbstractPreferenceController controller : controllers) { - controller.displayPreference(screen); - } + mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach( + controller -> controller.displayPreference(screen)); } /** * Update state of each preference managed by PreferenceController. */ protected void updatePreferenceStates() { - Collection controllers = mPreferenceControllers.values(); final PreferenceScreen screen = getPreferenceScreen(); - for (AbstractPreferenceController controller : controllers) { - if (!controller.isAvailable()) { - continue; - } - final String key = controller.getPreferenceKey(); + Collection> controllerLists = + mPreferenceControllers.values(); + for (List controllerList : controllerLists) { + for (AbstractPreferenceController controller : controllerList) { + if (!controller.isAvailable()) { + continue; + } + final String key = controller.getPreferenceKey(); - final Preference preference = screen.findPreference(key); - if (preference == null) { - Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s", - key, controller.getClass().getSimpleName())); - continue; + final Preference preference = screen.findPreference(key); + if (preference == null) { + Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s", + key, controller.getClass().getSimpleName())); + continue; + } + controller.updateState(preference); } - controller.updateState(preference); } } diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java index c330340b901..6c663ab6cef 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java @@ -90,6 +90,19 @@ public class DashboardFragmentTest { assertThat(controller).isSameAs(retrievedController); } + @Test + public void testPreferenceControllerSetter_shouldAddAndNotReplace() { + final TestPreferenceController controller1 = new TestPreferenceController(mContext); + mTestFragment.addPreferenceController(controller1); + final TestPreferenceController controller2 = new TestPreferenceController(mContext); + mTestFragment.addPreferenceController(controller2); + + final TestPreferenceController retrievedController = mTestFragment.getPreferenceController + (TestPreferenceController.class); + + assertThat(controller1).isSameAs(retrievedController); + } + @Test public void displayTilesAsPreference_shouldAddTilesWithIntent() { when(mFakeFeatureFactory.dashboardFeatureProvider @@ -145,6 +158,23 @@ public class DashboardFragmentTest { verify(mockController2).getPreferenceKey(); } + @Test + public void updateState_doesNotSkipControllersOfSameClass() { + final AbstractPreferenceController mockController1 = + mock(AbstractPreferenceController.class); + final AbstractPreferenceController mockController2 = + mock(AbstractPreferenceController.class); + mTestFragment.addPreferenceController(mockController1); + mTestFragment.addPreferenceController(mockController2); + when(mockController1.isAvailable()).thenReturn(true); + when(mockController2.isAvailable()).thenReturn(true); + + mTestFragment.updatePreferenceStates(); + + verify(mockController1).getPreferenceKey(); + verify(mockController2).getPreferenceKey(); + } + @Test public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() { final Tile tile = new Tile(); diff --git a/tests/robotests/src/com/android/settings/security/screenlock/ScreenLockSettingsTest.java b/tests/robotests/src/com/android/settings/security/screenlock/ScreenLockSettingsTest.java index 4213fc526a5..374b7ecd276 100644 --- a/tests/robotests/src/com/android/settings/security/screenlock/ScreenLockSettingsTest.java +++ b/tests/robotests/src/com/android/settings/security/screenlock/ScreenLockSettingsTest.java @@ -33,6 +33,8 @@ import org.junit.runner.RunWith; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; +import java.util.ArrayList; +import java.util.List; import java.util.Map; @RunWith(SettingsRobolectricTestRunner.class) @@ -55,10 +57,12 @@ public class ScreenLockSettingsTest { @Test public void onOwnerInfoUpdated_shouldUpdateOwnerInfoController() { - final Map preferenceControllers = + final Map> preferenceControllers = ReflectionHelpers.getField(mSettings, "mPreferenceControllers"); final OwnerInfoPreferenceController controller = mock(OwnerInfoPreferenceController.class); - preferenceControllers.put(OwnerInfoPreferenceController.class, controller); + List controllerList = new ArrayList<>(); + controllerList.add(controller); + preferenceControllers.put(OwnerInfoPreferenceController.class, controllerList); mSettings.onOwnerInfoUpdated();