Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64aa50c0 authored by Matthew Fritze's avatar Matthew Fritze
Browse files

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
parent 578d0e8e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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">

@@ -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
+0 −1
Original line number Diff line number Diff line
@@ -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;

+36 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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);
        }
    }

+12 −36
Original line number Diff line number Diff line
@@ -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<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));
@@ -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<Integer> 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
+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