Loading src/com/android/settings/core/BasePreferenceController.java +9 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.util.Log; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; import com.android.settings.slices.SliceData; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; Loading Loading @@ -153,6 +154,14 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl return getAvailabilityStatus() != DISABLED_UNSUPPORTED; } /** * @return the UI type supported by the controller. */ @SliceData.SliceType public int getSliceType() { return SliceData.SliceType.INTENT; } /** * Updates non-indexable keys for search provider. * Loading src/com/android/settings/core/TogglePreferenceController.java +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.TwoStatePreference; import com.android.settings.slices.SliceData; import com.android.settings.widget.MasterSwitchPreference; /** Loading Loading @@ -59,4 +60,11 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle public final boolean onPreferenceChange(Preference preference, Object newValue) { return setChecked((Boolean) newValue); } @Override @SliceData.SliceType public int getSliceType() { return SliceData.SliceType.SWITCH; } } No newline at end of file src/com/android/settings/slices/SliceBuilderUtils.java +20 −8 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ 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 @@ -67,7 +66,7 @@ public class SliceBuilderUtils { // TODO (b/71640747) Respect setting availability. if (controller instanceof TogglePreferenceController) { if (sliceData.getSliceType() == SliceData.SliceType.SWITCH) { addToggleAction(context, builder, ((TogglePreferenceController) controller).isChecked(), sliceData.getKey()); } Loading @@ -77,23 +76,36 @@ public class SliceBuilderUtils { .build(); } /** * @return the {@link SliceData.SliceType} for the {@param controllerClassName} and key. */ @SliceData.SliceType public static int getSliceType(Context context, String controllerClassName, String controllerKey) { BasePreferenceController controller = getPreferenceController(context, controllerClassName, controllerKey); return controller.getSliceType(); } /** * Looks at the {@link SliceData#preferenceController} from {@param sliceData} and attempts to * build an {@link AbstractPreferenceController}. */ public static BasePreferenceController getPreferenceController(Context context, SliceData sliceData) { return getPreferenceController(context, sliceData.getPreferenceController(), sliceData.getKey()); } private static BasePreferenceController getPreferenceController(Context context, String controllerClassName, String controllerKey) { try { return BasePreferenceController.createInstance(context, sliceData.getPreferenceController()); return BasePreferenceController.createInstance(context, controllerClassName); } catch (IllegalStateException e) { // Do nothing Log.d(TAG, "Could not find Context-only controller for preference controller: " + sliceData.getKey()); } return BasePreferenceController.createInstance(context, sliceData.getPreferenceController(), sliceData.getKey()); return BasePreferenceController.createInstance(context, controllerClassName, controllerKey); } private static void addToggleAction(Context context, RowBuilder builder, boolean isChecked, Loading src/com/android/settings/slices/SliceData.java +69 −27 Original line number Diff line number Diff line Loading @@ -16,76 +16,111 @@ package com.android.settings.slices; import android.annotation.IntDef; import android.net.Uri; import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Data class representing a slice stored by {@link SlicesIndexer}. * Note that {@link #key} is treated as a primary key for this class and determines equality. * Note that {@link #mKey} is treated as a primary key for this class and determines equality. */ public class SliceData { private final String key; /** * Flags indicating the UI type of the Slice. */ @IntDef({SliceType.INTENT, SliceType.SWITCH, SliceType.SLIDER}) @Retention(RetentionPolicy.SOURCE) public @interface SliceType { /** * Only supports content intent. */ int INTENT = 0; /** * Supports toggle action. */ int SWITCH = 1; /** * Supports progress bar. */ int SLIDER = 2; } private final String mKey; private final String title; private final String mTitle; private final String summary; private final String mSummary; private final String screenTitle; private final String mScreenTitle; private final int iconResource; private final int mIconResource; private final String fragmentClassName; private final String mFragmentClassName; private final Uri uri; private final Uri mUri; private final String preferenceController; private final String mPreferenceController; @SliceType private final int mSliceType; public String getKey() { return key; return mKey; } public String getTitle() { return title; return mTitle; } public String getSummary() { return summary; return mSummary; } public String getScreenTitle() { return screenTitle; return mScreenTitle; } public int getIconResource() { return iconResource; return mIconResource; } public String getFragmentClassName() { return fragmentClassName; return mFragmentClassName; } public Uri getUri() { return uri; return mUri; } public String getPreferenceController() { return preferenceController; return mPreferenceController; } public int getSliceType() { return mSliceType; } private SliceData(Builder builder) { key = builder.mKey; title = builder.mTitle; summary = builder.mSummary; screenTitle = builder.mScreenTitle; iconResource = builder.mIconResource; fragmentClassName = builder.mFragmentClassName; uri = builder.mUri; preferenceController = builder.mPrefControllerClassName; mKey = builder.mKey; mTitle = builder.mTitle; mSummary = builder.mSummary; mScreenTitle = builder.mScreenTitle; mIconResource = builder.mIconResource; mFragmentClassName = builder.mFragmentClassName; mUri = builder.mUri; mPreferenceController = builder.mPrefControllerClassName; mSliceType = builder.mSliceType; } @Override public int hashCode() { return key.hashCode(); return mKey.hashCode(); } @Override Loading @@ -94,7 +129,7 @@ public class SliceData { return false; } SliceData newObject = (SliceData) obj; return TextUtils.equals(key, newObject.key); return TextUtils.equals(mKey, newObject.mKey); } static class Builder { Loading @@ -114,6 +149,8 @@ public class SliceData { private String mPrefControllerClassName; private int mSliceType; public Builder setKey(String key) { mKey = key; return this; Loading Loading @@ -154,6 +191,11 @@ public class SliceData { return this; } public Builder setSliceType(@SliceType int sliceType) { mSliceType = sliceType; return this; } public SliceData build() { if (TextUtils.isEmpty(mKey)) { throw new IllegalStateException("Key cannot be empty"); Loading src/com/android/settings/slices/SliceDataConverter.java +12 −13 Original line number Diff line number Diff line Loading @@ -127,11 +127,6 @@ class SliceDataConverter { XmlResourceParser parser = null; final List<SliceData> xmlSliceData = new ArrayList<>(); String key; String title; String summary; @DrawableRes int iconResId; String controllerClassName; try { parser = mContext.getResources().getXml(xmlResId); Loading @@ -155,30 +150,33 @@ class SliceDataConverter { // TODO (b/67996923) Investigate if we need headers for Slices, since they never // correspond to an actual setting. SliceData xmlSlice; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } // TODO (b/67996923) Non-controller Slices should become intent-only slices. // Note that without a controller, dynamic summaries are impossible. // TODO (b/67996923) This will not work if preferences have nested intents: // <pref ....> // <intent action="blab"/> </pref> controllerClassName = PreferenceXmlParserUtils.getController(mContext, attrs); final String controllerClassName = PreferenceXmlParserUtils.getController(mContext, attrs); if (TextUtils.isEmpty(controllerClassName)) { continue; } title = PreferenceXmlParserUtils.getDataTitle(mContext, attrs); key = PreferenceXmlParserUtils.getDataKey(mContext, attrs); iconResId = PreferenceXmlParserUtils.getDataIcon(mContext, attrs); summary = PreferenceXmlParserUtils.getDataSummary(mContext, attrs); final String title = PreferenceXmlParserUtils.getDataTitle(mContext, attrs); final String key = PreferenceXmlParserUtils.getDataKey(mContext, attrs); @DrawableRes final int iconResId = PreferenceXmlParserUtils.getDataIcon(mContext, attrs); final String summary = PreferenceXmlParserUtils.getDataSummary(mContext, attrs); final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName, key); xmlSlice = new SliceData.Builder() final SliceData xmlSlice = new SliceData.Builder() .setKey(key) .setTitle(title) .setSummary(summary) Loading @@ -186,6 +184,7 @@ class SliceDataConverter { .setScreenTitle(screenTitle) .setPreferenceControllerClassName(controllerClassName) .setFragmentName(fragmentName) .setSliceType(sliceType) .build(); xmlSliceData.add(xmlSlice); Loading Loading
src/com/android/settings/core/BasePreferenceController.java +9 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.util.Log; import com.android.settings.search.ResultPayload; import com.android.settings.search.SearchIndexableRaw; import com.android.settings.slices.SliceData; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; Loading Loading @@ -153,6 +154,14 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl return getAvailabilityStatus() != DISABLED_UNSUPPORTED; } /** * @return the UI type supported by the controller. */ @SliceData.SliceType public int getSliceType() { return SliceData.SliceType.INTENT; } /** * Updates non-indexable keys for search provider. * Loading
src/com/android/settings/core/TogglePreferenceController.java +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.TwoStatePreference; import com.android.settings.slices.SliceData; import com.android.settings.widget.MasterSwitchPreference; /** Loading Loading @@ -59,4 +60,11 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle public final boolean onPreferenceChange(Preference preference, Object newValue) { return setChecked((Boolean) newValue); } @Override @SliceData.SliceType public int getSliceType() { return SliceData.SliceType.SWITCH; } } No newline at end of file
src/com/android/settings/slices/SliceBuilderUtils.java +20 −8 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ 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 @@ -67,7 +66,7 @@ public class SliceBuilderUtils { // TODO (b/71640747) Respect setting availability. if (controller instanceof TogglePreferenceController) { if (sliceData.getSliceType() == SliceData.SliceType.SWITCH) { addToggleAction(context, builder, ((TogglePreferenceController) controller).isChecked(), sliceData.getKey()); } Loading @@ -77,23 +76,36 @@ public class SliceBuilderUtils { .build(); } /** * @return the {@link SliceData.SliceType} for the {@param controllerClassName} and key. */ @SliceData.SliceType public static int getSliceType(Context context, String controllerClassName, String controllerKey) { BasePreferenceController controller = getPreferenceController(context, controllerClassName, controllerKey); return controller.getSliceType(); } /** * Looks at the {@link SliceData#preferenceController} from {@param sliceData} and attempts to * build an {@link AbstractPreferenceController}. */ public static BasePreferenceController getPreferenceController(Context context, SliceData sliceData) { return getPreferenceController(context, sliceData.getPreferenceController(), sliceData.getKey()); } private static BasePreferenceController getPreferenceController(Context context, String controllerClassName, String controllerKey) { try { return BasePreferenceController.createInstance(context, sliceData.getPreferenceController()); return BasePreferenceController.createInstance(context, controllerClassName); } catch (IllegalStateException e) { // Do nothing Log.d(TAG, "Could not find Context-only controller for preference controller: " + sliceData.getKey()); } return BasePreferenceController.createInstance(context, sliceData.getPreferenceController(), sliceData.getKey()); return BasePreferenceController.createInstance(context, controllerClassName, controllerKey); } private static void addToggleAction(Context context, RowBuilder builder, boolean isChecked, Loading
src/com/android/settings/slices/SliceData.java +69 −27 Original line number Diff line number Diff line Loading @@ -16,76 +16,111 @@ package com.android.settings.slices; import android.annotation.IntDef; import android.net.Uri; import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Data class representing a slice stored by {@link SlicesIndexer}. * Note that {@link #key} is treated as a primary key for this class and determines equality. * Note that {@link #mKey} is treated as a primary key for this class and determines equality. */ public class SliceData { private final String key; /** * Flags indicating the UI type of the Slice. */ @IntDef({SliceType.INTENT, SliceType.SWITCH, SliceType.SLIDER}) @Retention(RetentionPolicy.SOURCE) public @interface SliceType { /** * Only supports content intent. */ int INTENT = 0; /** * Supports toggle action. */ int SWITCH = 1; /** * Supports progress bar. */ int SLIDER = 2; } private final String mKey; private final String title; private final String mTitle; private final String summary; private final String mSummary; private final String screenTitle; private final String mScreenTitle; private final int iconResource; private final int mIconResource; private final String fragmentClassName; private final String mFragmentClassName; private final Uri uri; private final Uri mUri; private final String preferenceController; private final String mPreferenceController; @SliceType private final int mSliceType; public String getKey() { return key; return mKey; } public String getTitle() { return title; return mTitle; } public String getSummary() { return summary; return mSummary; } public String getScreenTitle() { return screenTitle; return mScreenTitle; } public int getIconResource() { return iconResource; return mIconResource; } public String getFragmentClassName() { return fragmentClassName; return mFragmentClassName; } public Uri getUri() { return uri; return mUri; } public String getPreferenceController() { return preferenceController; return mPreferenceController; } public int getSliceType() { return mSliceType; } private SliceData(Builder builder) { key = builder.mKey; title = builder.mTitle; summary = builder.mSummary; screenTitle = builder.mScreenTitle; iconResource = builder.mIconResource; fragmentClassName = builder.mFragmentClassName; uri = builder.mUri; preferenceController = builder.mPrefControllerClassName; mKey = builder.mKey; mTitle = builder.mTitle; mSummary = builder.mSummary; mScreenTitle = builder.mScreenTitle; mIconResource = builder.mIconResource; mFragmentClassName = builder.mFragmentClassName; mUri = builder.mUri; mPreferenceController = builder.mPrefControllerClassName; mSliceType = builder.mSliceType; } @Override public int hashCode() { return key.hashCode(); return mKey.hashCode(); } @Override Loading @@ -94,7 +129,7 @@ public class SliceData { return false; } SliceData newObject = (SliceData) obj; return TextUtils.equals(key, newObject.key); return TextUtils.equals(mKey, newObject.mKey); } static class Builder { Loading @@ -114,6 +149,8 @@ public class SliceData { private String mPrefControllerClassName; private int mSliceType; public Builder setKey(String key) { mKey = key; return this; Loading Loading @@ -154,6 +191,11 @@ public class SliceData { return this; } public Builder setSliceType(@SliceType int sliceType) { mSliceType = sliceType; return this; } public SliceData build() { if (TextUtils.isEmpty(mKey)) { throw new IllegalStateException("Key cannot be empty"); Loading
src/com/android/settings/slices/SliceDataConverter.java +12 −13 Original line number Diff line number Diff line Loading @@ -127,11 +127,6 @@ class SliceDataConverter { XmlResourceParser parser = null; final List<SliceData> xmlSliceData = new ArrayList<>(); String key; String title; String summary; @DrawableRes int iconResId; String controllerClassName; try { parser = mContext.getResources().getXml(xmlResId); Loading @@ -155,30 +150,33 @@ class SliceDataConverter { // TODO (b/67996923) Investigate if we need headers for Slices, since they never // correspond to an actual setting. SliceData xmlSlice; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } // TODO (b/67996923) Non-controller Slices should become intent-only slices. // Note that without a controller, dynamic summaries are impossible. // TODO (b/67996923) This will not work if preferences have nested intents: // <pref ....> // <intent action="blab"/> </pref> controllerClassName = PreferenceXmlParserUtils.getController(mContext, attrs); final String controllerClassName = PreferenceXmlParserUtils.getController(mContext, attrs); if (TextUtils.isEmpty(controllerClassName)) { continue; } title = PreferenceXmlParserUtils.getDataTitle(mContext, attrs); key = PreferenceXmlParserUtils.getDataKey(mContext, attrs); iconResId = PreferenceXmlParserUtils.getDataIcon(mContext, attrs); summary = PreferenceXmlParserUtils.getDataSummary(mContext, attrs); final String title = PreferenceXmlParserUtils.getDataTitle(mContext, attrs); final String key = PreferenceXmlParserUtils.getDataKey(mContext, attrs); @DrawableRes final int iconResId = PreferenceXmlParserUtils.getDataIcon(mContext, attrs); final String summary = PreferenceXmlParserUtils.getDataSummary(mContext, attrs); final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName, key); xmlSlice = new SliceData.Builder() final SliceData xmlSlice = new SliceData.Builder() .setKey(key) .setTitle(title) .setSummary(summary) Loading @@ -186,6 +184,7 @@ class SliceDataConverter { .setScreenTitle(screenTitle) .setPreferenceControllerClassName(controllerClassName) .setFragmentName(fragmentName) .setSliceType(sliceType) .build(); xmlSliceData.add(xmlSlice); Loading