Change underlying preferenceControllers to an ArrayMap of Lists.
Previously, DashboardFragment stores preference controllers in an
ArrayMap of <Class, AbstractPreferenceController>. 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
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 3e1e881..6a88a38 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -54,7 +54,7 @@
SummaryLoader.SummaryConsumer {
private static final String TAG = "DashboardFragment";
- private final Map<Class, AbstractPreferenceController> mPreferenceControllers =
+ private final Map<Class, List<AbstractPreferenceController>> mPreferenceControllers =
new ArrayMap<>();
private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
@@ -156,14 +156,17 @@
@Override
public boolean onPreferenceTreeClick(Preference preference) {
- Collection<AbstractPreferenceController> controllers = mPreferenceControllers.values();
+ Collection<List<AbstractPreferenceController>> 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<AbstractPreferenceController> controllerList : controllers) {
+ for (AbstractPreferenceController controller : controllerList) {
+ if (controller.handlePreferenceTreeClick(preference)) {
+ return true;
+ }
}
}
return super.onPreferenceTreeClick(preference);
@@ -189,12 +192,23 @@
protected abstract int getPreferenceScreenResId();
protected <T extends AbstractPreferenceController> T getPreferenceController(Class<T> clazz) {
- AbstractPreferenceController controller = mPreferenceControllers.get(clazz);
- return (T) controller;
+ List<AbstractPreferenceController> 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 @@
}
addPreferencesFromResource(resId);
final PreferenceScreen screen = getPreferenceScreen();
- Collection<AbstractPreferenceController> 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<AbstractPreferenceController> controllers = mPreferenceControllers.values();
final PreferenceScreen screen = getPreferenceScreen();
- for (AbstractPreferenceController controller : controllers) {
- if (!controller.isAvailable()) {
- continue;
- }
- final String key = controller.getPreferenceKey();
+ Collection<List<AbstractPreferenceController>> controllerLists =
+ mPreferenceControllers.values();
+ for (List<AbstractPreferenceController> 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 c330340..6c663ab 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -91,6 +91,19 @@
}
@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
.getTilesForCategory(nullable(String.class)))
@@ -146,6 +159,23 @@
}
@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();
tile.icon = mock(Icon.class);
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 4213fc5..374b7ec 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.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 @@
@Test
public void onOwnerInfoUpdated_shouldUpdateOwnerInfoController() {
- final Map<Class, AbstractPreferenceController> preferenceControllers =
+ final Map<Class, List<AbstractPreferenceController>> preferenceControllers =
ReflectionHelpers.getField(mSettings, "mPreferenceControllers");
final OwnerInfoPreferenceController controller = mock(OwnerInfoPreferenceController.class);
- preferenceControllers.put(OwnerInfoPreferenceController.class, controller);
+ List<AbstractPreferenceController> controllerList = new ArrayList<>();
+ controllerList.add(controller);
+ preferenceControllers.put(OwnerInfoPreferenceController.class, controllerList);
mSettings.onOwnerInfoUpdated();