From 64aa50c006dd3d2be51241f837436ec3713753e0 Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Mon, 15 Jan 2018 14:27:30 -0800 Subject: [PATCH] Add bluetooth as a supported Slice To add bluetooth as a valid slice requires adding support for Context-only preference controller constructors, which was already planned work. Fixes: 67997327 Test: robotests Change-Id: I7efd20a05d5796c3327a26b1fc535d5436d1070f --- res/xml/connected_devices_advanced.xml | 2 + .../slices/SettingsSliceProvider.java | 1 - .../settings/slices/SliceBuilderUtils.java | 42 +++++++++++++--- .../core/XmlControllerAttributeTest.java | 48 +++++-------------- .../FakeContextOnlyPreferenceController.java | 19 ++++++++ .../slices/SliceBuilderUtilsTest.java | 28 ++++++++--- 6 files changed, 91 insertions(+), 49 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml index dfe23dfdeb3..7ca890df451 100644 --- a/res/xml/connected_devices_advanced.xml +++ b/res/xml/connected_devices_advanced.xml @@ -16,6 +16,7 @@ @@ -24,6 +25,7 @@ android:title="@string/bluetooth_settings_title" android:icon="@drawable/ic_settings_bluetooth" android:summary="@string/bluetooth_pref_summary" + settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController" android:order="-7"/> clazz = Class.forName(sliceData.getPreferenceController()); - Constructor preferenceConstructor = clazz.getConstructor(Context.class, - String.class); - return (BasePreferenceController) preferenceConstructor.newInstance( - new Object[]{context, sliceData.getKey()}); + Constructor preferenceConstructor; + Object[] params; + + if (contextOnlyCtor) { + preferenceConstructor = clazz.getConstructor(Context.class); + params = new Object[]{context}; + } else { + preferenceConstructor = clazz.getConstructor(Context.class, String.class); + params = new Object[]{context, sliceData.getKey()}; + } + + return (BasePreferenceController) preferenceConstructor.newInstance(params); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { throw new IllegalStateException( - "Invalid preference controller: " + sliceData.getPreferenceController()); + "Invalid preference controller: " + sliceData.getPreferenceController(), e); } } diff --git a/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java b/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java index 8ded9d66995..e6ca59b26c2 100644 --- a/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java +++ b/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java @@ -80,11 +80,6 @@ public class XmlControllerAttributeTest { private static final String BAD_CLASSNAME_ERROR = "The following controllers set in the XML did not have valid class names:\n"; - private static final String BAD_CONSTRUCTOR_ERROR = - "The constructor provided by the following classes were insufficient to instantiate " - + "the object. It could be due to being an interface, abstract, or an " - + "IllegalAccessException. Please fix the following classes:\n"; - Context mContext; SearchFeatureProvider mSearchProvider; private FakeFeatureFactory mFakeFeatureFactory; @@ -112,7 +107,6 @@ public class XmlControllerAttributeTest { Set invalidConstructors = new HashSet<>(); Set invalidClassHierarchy = new HashSet<>(); Set badClassNameControllers = new HashSet<>(); - Set badConstructorControllers = new HashSet<>(); for (int resId : xmlSet) { xmlControllers.addAll(getXmlControllers(resId)); @@ -133,13 +127,7 @@ public class XmlControllerAttributeTest { continue; } - Object controller = getObjectFromConstructor(constructor); - if (controller == null) { - badConstructorControllers.add(controllerClassName); - continue; - } - - if (!(controller instanceof BasePreferenceController)) { + if (!isBasePreferenceController(clazz)) { invalidClassHierarchy.add(controllerClassName); } } @@ -150,13 +138,10 @@ public class XmlControllerAttributeTest { invalidClassHierarchy); final String badClassNameError = buildErrorMessage(BAD_CLASSNAME_ERROR, badClassNameControllers); - final String badConstructorError = buildErrorMessage(BAD_CONSTRUCTOR_ERROR, - badConstructorControllers); assertWithMessage(invalidConstructorError).that(invalidConstructors).isEmpty(); assertWithMessage(invalidClassHierarchyError).that(invalidClassHierarchy).isEmpty(); assertWithMessage(badClassNameError).that(badClassNameControllers).isEmpty(); - assertWithMessage(badConstructorError).that(badConstructorControllers).isEmpty(); } private Set getIndexableXml() { @@ -260,25 +245,16 @@ public class XmlControllerAttributeTest { return constructor; } - private Object getObjectFromConstructor(Constructor constructor) { - Object controller = null; - - try { - controller = constructor.newInstance(mContext); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | - IllegalArgumentException e) { + /** + * Make sure that {@link BasePreferenceController} is in the class hierarchy. + */ + private boolean isBasePreferenceController(Class clazz) { + while (clazz != null) { + clazz = clazz.getSuperclass(); + if (BasePreferenceController.class.equals(clazz)) { + return true; + } } - - if (controller != null) { - return controller; - } - - try { - controller = constructor.newInstance(mContext, "key"); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | - IllegalArgumentException e) { - } - - return controller; + return false; } -} +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java b/tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java new file mode 100644 index 00000000000..214607ba597 --- /dev/null +++ b/tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java @@ -0,0 +1,19 @@ +package com.android.settings.slices; + +import android.content.Context; + +import com.android.settings.core.BasePreferenceController; + +public class FakeContextOnlyPreferenceController extends BasePreferenceController { + + public static final String KEY = "fakeController2"; + + public FakeContextOnlyPreferenceController(Context context) { + super(context, KEY); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java index 10e4b7694f9..0923571376c 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java @@ -50,8 +50,8 @@ public class SliceBuilderUtilsTest { private final String FRAGMENT_NAME = "fragment name"; private final int ICON = 1234; // I declare a thumb war private final Uri URI = Uri.parse("content://com.android.settings.slices/test"); - private final String PREF_CONTROLLER = FakeToggleController.class.getName(); - ; + private final Class PREF_CONTROLLER = FakeToggleController.class; + private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class; private Context mContext; @@ -75,6 +75,14 @@ public class SliceBuilderUtilsTest { assertThat(controller).isInstanceOf(FakeToggleController.class); } + @Test + public void testGetPreferenceController_contextOnly_buildsMatchingController() { + BasePreferenceController controller = SliceBuilderUtils.getPreferenceController(mContext, + getDummyData(PREF_CONTROLLER2)); + + assertThat(controller).isInstanceOf(FakeContextOnlyPreferenceController.class); + } + @Test public void testDynamicSummary_returnsSliceSummary() { SliceData data = getDummyData(); @@ -87,7 +95,7 @@ public class SliceBuilderUtilsTest { @Test public void testDynamicSummary_returnsFragmentSummary() { - SliceData data = getDummyData(null); + SliceData data = getDummyData((String) null); FakePreferenceController controller = spy(new FakePreferenceController(mContext, KEY)); String controllerSummary = "new_Summary"; doReturn(controllerSummary).when(controller).getSummary(); @@ -99,7 +107,7 @@ public class SliceBuilderUtilsTest { @Test public void testDynamicSummary_returnsSliceScreenTitle() { - SliceData data = getDummyData(null); + SliceData data = getDummyData((String) null); FakePreferenceController controller = new FakePreferenceController(mContext, KEY); String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); @@ -129,10 +137,18 @@ public class SliceBuilderUtilsTest { } private SliceData getDummyData() { - return getDummyData(SUMMARY); + return getDummyData(PREF_CONTROLLER, SUMMARY); } private SliceData getDummyData(String summary) { + return getDummyData(PREF_CONTROLLER, summary); + } + + private SliceData getDummyData(Class prefController) { + return getDummyData(prefController, SUMMARY); + } + + private SliceData getDummyData(Class prefController, String summary) { return new SliceData.Builder() .setKey(KEY) .setTitle(TITLE) @@ -141,7 +157,7 @@ public class SliceBuilderUtilsTest { .setIcon(ICON) .setFragmentName(FRAGMENT_NAME) .setUri(URI) - .setPreferenceControllerClassName(PREF_CONTROLLER) + .setPreferenceControllerClassName(prefController.getName()) .build(); } }