Add SettingsPrefController for Slices
Adds a new abstraction layer between preference controllers and the AbstractPreferenceController. The layer is used to consolidate the logic for each the setting type for getting and setting values. This will be extended to support UI information for Slices. For reference how this fits into Slices, look at the like-named classes added in this prototype: ag/3221891 The changes in Search are as a transition into deprecation. The code for Search in Settings is out-of-date from the unbundled counterpart, and this change is made so that the current code behaves as normal. Test: robotests Bug: 67996707 Change-Id: Ib1faab706485039edad66119a27a3fd5cabe6009
This commit is contained in:
159
src/com/android/settings/core/BasePreferenceController.java
Normal file
159
src/com/android/settings/core/BasePreferenceController.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package com.android.settings.core;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.app.slice.Slice;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract class to consolidate utility between preference controllers and act as an interface
|
||||
* for Slices. The abstract classes that inherit from this class will act as the direct interfaces
|
||||
* for each type when plugging into Slices.
|
||||
*/
|
||||
public abstract class BasePreferenceController extends AbstractPreferenceController {
|
||||
|
||||
private static final String TAG = "SettingsPrefController";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({AVAILABLE, DISABLED_UNSUPPORTED, DISABLED_FOR_USER, DISABLED_DEPENDENT_SETTING,
|
||||
UNAVAILABLE_UNKNOWN})
|
||||
public @interface AvailabilityStatus {
|
||||
}
|
||||
|
||||
/**
|
||||
* The setting is available.
|
||||
*/
|
||||
public static final int AVAILABLE = 0;
|
||||
|
||||
/**
|
||||
* The setting is not supported by the device.
|
||||
*/
|
||||
public static final int DISABLED_UNSUPPORTED = 1;
|
||||
|
||||
/**
|
||||
* The setting cannot be changed by the current user.
|
||||
*/
|
||||
public static final int DISABLED_FOR_USER = 2;
|
||||
|
||||
/**
|
||||
* The setting has a dependency in the Settings App which is currently blocking access.
|
||||
*/
|
||||
public static final int DISABLED_DEPENDENT_SETTING = 3;
|
||||
|
||||
/**
|
||||
* A catch-all case for internal errors and inexplicable unavailability.
|
||||
*/
|
||||
public static final int UNAVAILABLE_UNKNOWN = 4;
|
||||
|
||||
private final String mPreferenceKey;
|
||||
|
||||
public BasePreferenceController(Context context, String preferenceKey) {
|
||||
super(context);
|
||||
mPreferenceKey = preferenceKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()},
|
||||
* {@link #isSupported()}
|
||||
*/
|
||||
@AvailabilityStatus
|
||||
public abstract int getAvailabilityStatus();
|
||||
|
||||
/**
|
||||
* @return A slice for the corresponding setting.
|
||||
*/
|
||||
public abstract Slice getSettingSlice();
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return mPreferenceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAvailable() {
|
||||
return getAvailabilityStatus() == AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code false} if the setting is not applicable to the device. This covers both
|
||||
* settings which were only introduced in future versions of android, or settings that have
|
||||
* hardware dependencies.
|
||||
* </p>
|
||||
* Note that a return value of {@code true} does not mean that the setting is available.
|
||||
*/
|
||||
public final boolean isSupported() {
|
||||
return getAvailabilityStatus() != DISABLED_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates non-indexable keys for search provider.
|
||||
*
|
||||
* Called by SearchIndexProvider#getNonIndexableKeys
|
||||
*/
|
||||
public void updateNonIndexableKeys(List<String> keys) {
|
||||
if (this instanceof AbstractPreferenceController) {
|
||||
if (!isAvailable()) {
|
||||
final String key = getPreferenceKey();
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
Log.w(TAG,
|
||||
"Skipping updateNonIndexableKeys due to empty key " + this.toString());
|
||||
return;
|
||||
}
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates raw data for search provider.
|
||||
*
|
||||
* Called by SearchIndexProvider#getRawDataToIndex
|
||||
*/
|
||||
public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ResultPayload} corresponding to the search result type for the preference.
|
||||
* TODO (b/69808376) Remove this method.
|
||||
* Do not extend this method. It will not launch with P.
|
||||
*/
|
||||
@Deprecated
|
||||
public ResultPayload getResultPayload() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO (b/69380366) Add Method to get preference UI
|
||||
|
||||
// TODO (b/69380464) Add method to get intent
|
||||
|
||||
// TODO (b/69380560) Add method to get broadcast intent
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* A controller mixin that adds mobile settings specific functionality
|
||||
* TODO (b/69808530) Replace with BasePreferenceController.
|
||||
*/
|
||||
public interface PreferenceControllerMixin {
|
||||
|
||||
@@ -60,7 +61,11 @@ public interface PreferenceControllerMixin {
|
||||
|
||||
/**
|
||||
* @return the {@link ResultPayload} corresponding to the search result type for the preference.
|
||||
*
|
||||
* Do not rely on this method for intent-based or inline results. It will be removed in the
|
||||
* unbundling effort.
|
||||
*/
|
||||
@Deprecated
|
||||
default ResultPayload getResultPayload() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package com.android.settings.core;
|
||||
|
||||
import android.app.slice.Slice;
|
||||
import android.content.Context;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
/**
|
||||
* Abstract class that consolidates logic for updating toggle controllers.
|
||||
* It automatically handles the getting and setting of the switch UI element.
|
||||
* Children of this class implement methods to get and set the underlying value of the setting.
|
||||
*/
|
||||
public abstract class TogglePreferenceController extends BasePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "TogglePrefController";
|
||||
|
||||
public TogglePreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the Setting is enabled.
|
||||
*/
|
||||
public abstract boolean isChecked();
|
||||
|
||||
/**
|
||||
* Set the Setting to {@param isChecked}
|
||||
*
|
||||
* @param isChecked Is {@true} when the setting should be enabled.
|
||||
*/
|
||||
public abstract void setChecked(boolean isChecked);
|
||||
|
||||
@Override
|
||||
public final void updateState(Preference preference) {
|
||||
((SwitchPreference) preference).setChecked(isChecked());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean auto = (Boolean) newValue;
|
||||
setChecked(auto);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSettingSlice() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -16,65 +16,54 @@ package com.android.settings.display;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.DisplaySettings;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settings.search.DatabaseIndexingUtils;
|
||||
import com.android.settings.search.InlineSwitchPayload;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
|
||||
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
|
||||
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
|
||||
|
||||
|
||||
public class AutoBrightnessPreferenceController extends AbstractPreferenceController implements
|
||||
PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private final String mAutoBrightnessKey;
|
||||
public class AutoBrightnessPreferenceController extends TogglePreferenceController {
|
||||
|
||||
private final String SYSTEM_KEY = SCREEN_BRIGHTNESS_MODE;
|
||||
private final int DEFAULT_VALUE = SCREEN_BRIGHTNESS_MODE_MANUAL;
|
||||
|
||||
public AutoBrightnessPreferenceController(Context context, String key) {
|
||||
super(context);
|
||||
mAutoBrightnessKey = key;
|
||||
super(context, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_automatic_brightness_available);
|
||||
public boolean isChecked() {
|
||||
return Settings.System.getInt(mContext.getContentResolver(),
|
||||
SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return mAutoBrightnessKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
int brightnessMode = Settings.System.getInt(mContext.getContentResolver(),
|
||||
SYSTEM_KEY, DEFAULT_VALUE);
|
||||
((SwitchPreference) preference).setChecked(brightnessMode != DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean auto = (Boolean) newValue;
|
||||
public void setChecked(boolean isChecked) {
|
||||
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
|
||||
auto ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : DEFAULT_VALUE);
|
||||
return true;
|
||||
isChecked ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_automatic_brightness_available)
|
||||
? AVAILABLE
|
||||
: DISABLED_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultPayload getResultPayload() {
|
||||
// TODO remove result payload
|
||||
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext,
|
||||
DisplaySettings.class.getName(), mAutoBrightnessKey,
|
||||
DisplaySettings.class.getName(), getPreferenceKey(),
|
||||
mContext.getString(R.string.display_settings));
|
||||
|
||||
return new InlineSwitchPayload(SYSTEM_KEY,
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
@@ -71,6 +72,9 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
|
||||
if (controller instanceof PreferenceControllerMixin) {
|
||||
((PreferenceControllerMixin) controller)
|
||||
.updateNonIndexableKeys(nonIndexableKeys);
|
||||
} else if (controller instanceof BasePreferenceController) {
|
||||
((BasePreferenceController) controller).updateNonIndexableKeys(
|
||||
nonIndexableKeys);
|
||||
} else {
|
||||
throw new IllegalStateException(controller.getClass().getName()
|
||||
+ " must implement " + PreferenceControllerMixin.class.getName());
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.Log;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
@@ -72,10 +73,11 @@ public class DatabaseIndexingUtils {
|
||||
* @return A map between {@link Uri}s and {@link PreferenceControllerMixin}s to get the payload
|
||||
* types for Settings.
|
||||
*/
|
||||
public static Map<String, PreferenceControllerMixin> getPreferenceControllerUriMap(
|
||||
public static Map<String, ResultPayload> getPayloadKeyMap(
|
||||
String className, Context context) {
|
||||
ArrayMap<String, ResultPayload> map = new ArrayMap<>();
|
||||
if (context == null) {
|
||||
return null;
|
||||
return map;
|
||||
}
|
||||
|
||||
final Class<?> clazz = getIndexableClass(className);
|
||||
@@ -83,7 +85,7 @@ public class DatabaseIndexingUtils {
|
||||
if (clazz == null) {
|
||||
Log.d(TAG, "SearchIndexableResource '" + className +
|
||||
"' should implement the " + Indexable.class.getName() + " interface!");
|
||||
return null;
|
||||
return map;
|
||||
}
|
||||
|
||||
// Will be non null only for a Local provider implementing a
|
||||
@@ -94,44 +96,28 @@ public class DatabaseIndexingUtils {
|
||||
provider.getPreferenceControllers(context);
|
||||
|
||||
if (controllers == null) {
|
||||
return null;
|
||||
return map;
|
||||
}
|
||||
|
||||
ArrayMap<String, PreferenceControllerMixin> map = new ArrayMap<>();
|
||||
|
||||
for (AbstractPreferenceController controller : controllers) {
|
||||
ResultPayload payload;
|
||||
if (controller instanceof PreferenceControllerMixin) {
|
||||
map.put(controller.getPreferenceKey(), (PreferenceControllerMixin) controller);
|
||||
payload = ((PreferenceControllerMixin) controller).getResultPayload();
|
||||
|
||||
} else if (controller instanceof BasePreferenceController) {
|
||||
payload = ((BasePreferenceController) controller).getResultPayload();
|
||||
} else {
|
||||
throw new IllegalStateException(controller.getClass().getName()
|
||||
+ " must implement " + PreferenceControllerMixin.class.getName());
|
||||
}
|
||||
if (payload != null) {
|
||||
map.put(controller.getPreferenceKey(), payload);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uriMap Map between the {@link PreferenceControllerMixin} keys
|
||||
* and the controllers themselves.
|
||||
* @param key The look-up key
|
||||
* @return The Payload from the {@link PreferenceControllerMixin} specified by the key,
|
||||
* if it exists. Otherwise null.
|
||||
*/
|
||||
public static ResultPayload getPayloadFromUriMap(Map<String, PreferenceControllerMixin> uriMap,
|
||||
String key) {
|
||||
if (uriMap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PreferenceControllerMixin controller = uriMap.get(key);
|
||||
if (controller == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return controller.getResultPayload();
|
||||
}
|
||||
|
||||
public static Class<?> getIndexableClass(String className) {
|
||||
final Class<?> clazz;
|
||||
try {
|
||||
@@ -164,4 +150,4 @@ public class DatabaseIndexingUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -178,11 +179,11 @@ public class IndexDataConverter {
|
||||
final String intentTargetPackage = sir.intentTargetPackage;
|
||||
final String intentTargetClass = sir.intentTargetClass;
|
||||
|
||||
Map<String, PreferenceControllerMixin> controllerUriMap = null;
|
||||
Map<String, ResultPayload> controllerUriMap = new HashMap<>();
|
||||
|
||||
if (fragmentName != null) {
|
||||
controllerUriMap = DatabaseIndexingUtils
|
||||
.getPreferenceControllerUriMap(fragmentName, context);
|
||||
.getPayloadKeyMap(fragmentName, context);
|
||||
}
|
||||
|
||||
headerTitle = XmlParserUtils.getDataTitle(context, attrs);
|
||||
@@ -249,7 +250,7 @@ public class IndexDataConverter {
|
||||
}
|
||||
|
||||
// TODO (b/62254931) index primitives instead of payload
|
||||
payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
|
||||
payload = controllerUriMap.get(key);
|
||||
childFragment = XmlParserUtils.getDataChildFragment(context, attrs);
|
||||
|
||||
builder.setSummaryOn(summary)
|
||||
|
||||
Reference in New Issue
Block a user