Merge "Add bluetooth as a supported Slice"

This commit is contained in:
TreeHugger Robot
2018-01-24 18:39:18 +00:00
committed by Android (Google) Code Review
6 changed files with 91 additions and 49 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}