Loading res/xml/connected_devices_advanced.xml +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="connected_devices_screen" android:title="@string/connected_device_connections_title"> Loading @@ -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"/> <SwitchPreference Loading src/com/android/settings/slices/SettingsSliceProvider.java +0 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.util.Log; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; Loading src/com/android/settings/slices/SliceBuilderUtils.java +36 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; Loading Loading @@ -85,17 +86,46 @@ public class SliceBuilderUtils { */ public static BasePreferenceController getPreferenceController(Context context, SliceData sliceData) { // TODO check for context-only controller first. try { return getController(context, sliceData, true /* isContextOnly */); } catch (IllegalStateException e) { // Do nothing Log.d(TAG, "Could not find Context-only controller for preference controller: " + sliceData.getKey()); } return getController(context, sliceData, false /* isContextOnly */); } /** * Attempts to build a {@link BasePreferenceController} from {@param SliceData}. * * @param sliceData Backing data for the Slice. * @param contextOnlyCtor {@code true} when the constructor for the * {@link BasePreferenceController} * only takes a {@link Context}. Else the constructor will be ({@link * Context}, {@code String}. */ private static BasePreferenceController getController(Context context, SliceData sliceData, boolean contextOnlyCtor) { try { Class<?> 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); } } Loading tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java +12 −36 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -112,7 +107,6 @@ public class XmlControllerAttributeTest { Set<String> invalidConstructors = new HashSet<>(); Set<String> invalidClassHierarchy = new HashSet<>(); Set<String> badClassNameControllers = new HashSet<>(); Set<String> badConstructorControllers = new HashSet<>(); for (int resId : xmlSet) { xmlControllers.addAll(getXmlControllers(resId)); Loading @@ -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); } } Loading @@ -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<Integer> getIndexableXml() { Loading Loading @@ -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 tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java 0 → 100644 +19 −0 Original line number Diff line number Diff line 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 Loading
res/xml/connected_devices_advanced.xml +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="connected_devices_screen" android:title="@string/connected_device_connections_title"> Loading @@ -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"/> <SwitchPreference Loading
src/com/android/settings/slices/SettingsSliceProvider.java +0 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.util.Log; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; Loading
src/com/android/settings/slices/SliceBuilderUtils.java +36 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; Loading Loading @@ -85,17 +86,46 @@ public class SliceBuilderUtils { */ public static BasePreferenceController getPreferenceController(Context context, SliceData sliceData) { // TODO check for context-only controller first. try { return getController(context, sliceData, true /* isContextOnly */); } catch (IllegalStateException e) { // Do nothing Log.d(TAG, "Could not find Context-only controller for preference controller: " + sliceData.getKey()); } return getController(context, sliceData, false /* isContextOnly */); } /** * Attempts to build a {@link BasePreferenceController} from {@param SliceData}. * * @param sliceData Backing data for the Slice. * @param contextOnlyCtor {@code true} when the constructor for the * {@link BasePreferenceController} * only takes a {@link Context}. Else the constructor will be ({@link * Context}, {@code String}. */ private static BasePreferenceController getController(Context context, SliceData sliceData, boolean contextOnlyCtor) { try { Class<?> 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); } } Loading
tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java +12 −36 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -112,7 +107,6 @@ public class XmlControllerAttributeTest { Set<String> invalidConstructors = new HashSet<>(); Set<String> invalidClassHierarchy = new HashSet<>(); Set<String> badClassNameControllers = new HashSet<>(); Set<String> badConstructorControllers = new HashSet<>(); for (int resId : xmlSet) { xmlControllers.addAll(getXmlControllers(resId)); Loading @@ -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); } } Loading @@ -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<Integer> getIndexableXml() { Loading Loading @@ -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
tests/robotests/src/com/android/settings/slices/FakeContextOnlyPreferenceController.java 0 → 100644 +19 −0 Original line number Diff line number Diff line 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