Snap for 4648297 from decea2055d to pi-release
Change-Id: I05ca8725fe9d9ee0a1efc1bd3d9d2f0a55424001
This commit is contained in:
@@ -3231,7 +3231,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<provider android:name=".slices.SettingsSliceProvider"
|
<provider android:name=".slices.SettingsSliceProvider"
|
||||||
android:authorities="com.android.settings.slices"
|
android:authorities="com.android.settings.slices;android.settings.slices"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
|||||||
@@ -96,8 +96,12 @@
|
|||||||
|
|
||||||
<!-- For Search -->
|
<!-- For Search -->
|
||||||
<declare-styleable name="Preference">
|
<declare-styleable name="Preference">
|
||||||
|
<!-- Synonyms for search results -->
|
||||||
<attr name="keywords" format="string" />
|
<attr name="keywords" format="string" />
|
||||||
|
<!-- Classname of a PreferenceController corresponding to the preference -->
|
||||||
<attr name="controller" format="string" />
|
<attr name="controller" format="string" />
|
||||||
|
<!-- {@code true} when the controller declared represents a slice from {@link android.app.SettingsSliceContract} -->
|
||||||
|
<attr name="platform_slice" format="boolean" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<!-- For DotsPageIndicator -->
|
<!-- For DotsPageIndicator -->
|
||||||
|
|||||||
@@ -4177,10 +4177,6 @@
|
|||||||
<string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
|
<string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
|
||||||
<!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
|
<!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
|
||||||
<string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
|
<string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
|
||||||
<!--
|
|
||||||
Format string for a physical device in the form: InputMethodSubtype - InputMethodEditor.
|
|
||||||
e.g. English (US) - X Keyboard -->
|
|
||||||
<string name="physical_device_title" translatable="false"><xliff:g id="input_method_editor" example="X Keyboard">%1$s</xliff:g> - <xliff:g id="input_method_subtype" example="English (US)">%2$s</xliff:g></string>
|
|
||||||
|
|
||||||
<!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
|
<!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
|
||||||
<string name="default_keyboard_layout">Default</string>
|
<string name="default_keyboard_layout">Default</string>
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
android:icon="@drawable/ic_settings_bluetooth"
|
android:icon="@drawable/ic_settings_bluetooth"
|
||||||
android:summary="@string/bluetooth_pref_summary"
|
android:summary="@string/bluetooth_pref_summary"
|
||||||
android:order="-7"
|
android:order="-7"
|
||||||
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"/>
|
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
|
||||||
|
settings:platform_slice="true"/>
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="toggle_nfc"
|
android:key="toggle_nfc"
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public class PreferenceXmlParserUtils {
|
|||||||
int FLAG_NEED_PREF_TITLE = 1 << 4;
|
int FLAG_NEED_PREF_TITLE = 1 << 4;
|
||||||
int FLAG_NEED_PREF_SUMMARY = 1 << 5;
|
int FLAG_NEED_PREF_SUMMARY = 1 << 5;
|
||||||
int FLAG_NEED_PREF_ICON = 1 << 6;
|
int FLAG_NEED_PREF_ICON = 1 << 6;
|
||||||
|
int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String METADATA_PREF_TYPE = "type";
|
public static final String METADATA_PREF_TYPE = "type";
|
||||||
@@ -84,35 +85,48 @@ public class PreferenceXmlParserUtils {
|
|||||||
public static final String METADATA_TITLE = "title";
|
public static final String METADATA_TITLE = "title";
|
||||||
public static final String METADATA_SUMMARY = "summary";
|
public static final String METADATA_SUMMARY = "summary";
|
||||||
public static final String METADATA_ICON = "icon";
|
public static final String METADATA_ICON = "icon";
|
||||||
|
public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice";
|
||||||
|
|
||||||
private static final String ENTRIES_SEPARATOR = "|";
|
private static final String ENTRIES_SEPARATOR = "|";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_KEY} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getDataKey(Context context, AttributeSet attrs) {
|
public static String getDataKey(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getStringData(context, attrs,
|
||||||
com.android.internal.R.styleable.Preference,
|
com.android.internal.R.styleable.Preference,
|
||||||
com.android.internal.R.styleable.Preference_key);
|
com.android.internal.R.styleable.Preference_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_TITLE} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getDataTitle(Context context, AttributeSet attrs) {
|
public static String getDataTitle(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getStringData(context, attrs,
|
||||||
com.android.internal.R.styleable.Preference,
|
com.android.internal.R.styleable.Preference,
|
||||||
com.android.internal.R.styleable.Preference_title);
|
com.android.internal.R.styleable.Preference_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_SUMMARY} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getDataSummary(Context context, AttributeSet attrs) {
|
public static String getDataSummary(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getStringData(context, attrs,
|
||||||
com.android.internal.R.styleable.Preference,
|
com.android.internal.R.styleable.Preference,
|
||||||
com.android.internal.R.styleable.Preference_summary);
|
com.android.internal.R.styleable.Preference_summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataSummaryOn(Context context, AttributeSet attrs) {
|
public static String getDataSummaryOn(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getStringData(context, attrs,
|
||||||
com.android.internal.R.styleable.CheckBoxPreference,
|
com.android.internal.R.styleable.CheckBoxPreference,
|
||||||
com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
|
com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataSummaryOff(Context context, AttributeSet attrs) {
|
public static String getDataSummaryOff(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs,
|
return getStringData(context, attrs,
|
||||||
com.android.internal.R.styleable.CheckBoxPreference,
|
com.android.internal.R.styleable.CheckBoxPreference,
|
||||||
com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
|
com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
|
||||||
}
|
}
|
||||||
@@ -124,13 +138,23 @@ public class PreferenceXmlParserUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataKeywords(Context context, AttributeSet attrs) {
|
public static String getDataKeywords(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
|
return getStringData(context, attrs, R.styleable.Preference,
|
||||||
|
R.styleable.Preference_keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_CONTROLLER} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getController(Context context, AttributeSet attrs) {
|
public static String getController(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_controller);
|
return getStringData(context, attrs, R.styleable.Preference,
|
||||||
|
R.styleable.Preference_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_ICON} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static int getDataIcon(Context context, AttributeSet attrs) {
|
public static int getDataIcon(Context context, AttributeSet attrs) {
|
||||||
final TypedArray ta = context.obtainStyledAttributes(attrs,
|
final TypedArray ta = context.obtainStyledAttributes(attrs,
|
||||||
com.android.internal.R.styleable.Preference);
|
com.android.internal.R.styleable.Preference);
|
||||||
@@ -176,25 +200,35 @@ public class PreferenceXmlParserUtils {
|
|||||||
}
|
}
|
||||||
final Bundle preferenceMetadata = new Bundle();
|
final Bundle preferenceMetadata = new Bundle();
|
||||||
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
|
||||||
|
R.styleable.Preference);
|
||||||
|
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
|
||||||
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
|
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
|
||||||
}
|
}
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEY)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEY)) {
|
||||||
preferenceMetadata.putString(METADATA_KEY, getDataKey(context, attrs));
|
preferenceMetadata.putString(METADATA_KEY, getKey(preferenceAttributes));
|
||||||
}
|
}
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_CONTROLLER)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_CONTROLLER)) {
|
||||||
preferenceMetadata.putString(METADATA_CONTROLLER, getController(context, attrs));
|
preferenceMetadata.putString(METADATA_CONTROLLER,
|
||||||
|
getController(preferenceAttributes));
|
||||||
}
|
}
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
|
||||||
preferenceMetadata.putString(METADATA_TITLE, getDataTitle(context, attrs));
|
preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes));
|
||||||
}
|
}
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_SUMMARY)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_SUMMARY)) {
|
||||||
preferenceMetadata.putString(METADATA_SUMMARY, getDataSummary(context, attrs));
|
preferenceMetadata.putString(METADATA_SUMMARY, getSummary(preferenceAttributes));
|
||||||
}
|
}
|
||||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_ICON)) {
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_ICON)) {
|
||||||
preferenceMetadata.putInt(METADATA_ICON, getDataIcon(context, attrs));
|
preferenceMetadata.putInt(METADATA_ICON, getIcon(preferenceAttributes));
|
||||||
|
}
|
||||||
|
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG)) {
|
||||||
|
preferenceMetadata.putBoolean(METADATA_PLATFORM_SLICE_FLAG,
|
||||||
|
getPlatformSlice(preferenceAttributes));
|
||||||
}
|
}
|
||||||
metadata.add(preferenceMetadata);
|
metadata.add(preferenceMetadata);
|
||||||
|
|
||||||
|
preferenceAttributes.recycle();
|
||||||
} while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
} while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
|
||||||
parser.close();
|
parser.close();
|
||||||
@@ -205,12 +239,16 @@ public class PreferenceXmlParserUtils {
|
|||||||
* Returns the fragment name if this preference launches a child fragment.
|
* Returns the fragment name if this preference launches a child fragment.
|
||||||
*/
|
*/
|
||||||
public static String getDataChildFragment(Context context, AttributeSet attrs) {
|
public static String getDataChildFragment(Context context, AttributeSet attrs) {
|
||||||
return getData(context, attrs, R.styleable.Preference,
|
return getStringData(context, attrs, R.styleable.Preference,
|
||||||
R.styleable.Preference_android_fragment);
|
R.styleable.Preference_android_fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link #extractMetadata(Context, int, int)} with a {@link MetadataFlag} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
|
private static String getStringData(Context context, AttributeSet set, int[] attrs, int resId) {
|
||||||
final TypedArray ta = context.obtainStyledAttributes(set, attrs);
|
final TypedArray ta = context.obtainStyledAttributes(set, attrs);
|
||||||
String data = ta.getString(resId);
|
String data = ta.getString(resId);
|
||||||
ta.recycle();
|
ta.recycle();
|
||||||
@@ -243,4 +281,28 @@ public class PreferenceXmlParserUtils {
|
|||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getKey(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getString(com.android.internal.R.styleable.Preference_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getTitle(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getString(com.android.internal.R.styleable.Preference_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSummary(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getString(com.android.internal.R.styleable.Preference_summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getController(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getString(R.styleable.Preference_controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getIcon(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getResourceId(com.android.internal.R.styleable.Icon_icon, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean getPlatformSlice(TypedArray styledAttributes) {
|
||||||
|
return styledAttributes.getBoolean(R.styleable.Preference_platform_slice, false /* def */);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,43 +16,31 @@
|
|||||||
|
|
||||||
package com.android.settings.inputmethod;
|
package com.android.settings.inputmethod;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.content.Context;
|
||||||
import android.app.Activity;
|
|
||||||
import android.hardware.input.InputDeviceIdentifier;
|
import android.hardware.input.InputDeviceIdentifier;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.hardware.input.InputManager.InputDeviceListener;
|
import android.hardware.input.InputManager.InputDeviceListener;
|
||||||
import android.hardware.input.KeyboardLayout;
|
import android.hardware.input.KeyboardLayout;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.preference.CheckBoxPreference;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
|
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
|
||||||
import com.android.internal.logging.MetricsLogger;
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
import com.android.settings.R;
|
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
import com.android.settings.inputmethod.PhysicalKeyboardFragment.KeyboardInfoPreference;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
|
public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
|
||||||
implements InputDeviceListener {
|
implements InputDeviceListener {
|
||||||
|
|
||||||
private InputDeviceIdentifier mInputDeviceIdentifier;
|
private InputDeviceIdentifier mInputDeviceIdentifier;
|
||||||
private int mInputDeviceId = -1;
|
private int mInputDeviceId = -1;
|
||||||
private InputManager mIm;
|
private InputManager mIm;
|
||||||
private InputMethodInfo mImi;
|
|
||||||
@Nullable
|
|
||||||
private InputMethodSubtype mSubtype;
|
|
||||||
private KeyboardLayout[] mKeyboardLayouts;
|
private KeyboardLayout[] mKeyboardLayouts;
|
||||||
private Map<Preference, KeyboardLayout> mPreferenceMap = new HashMap<>();
|
private HashMap<CheckBoxPreference, KeyboardLayout> mPreferenceMap = new HashMap<>();
|
||||||
|
|
||||||
// TODO: Make these constants public API for b/25752827
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intent extra: The input device descriptor of the keyboard whose keyboard
|
* Intent extra: The input device descriptor of the keyboard whose keyboard
|
||||||
@@ -60,16 +48,6 @@ public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragme
|
|||||||
*/
|
*/
|
||||||
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
|
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
|
||||||
|
|
||||||
/**
|
|
||||||
* Intent extra: The associated {@link InputMethodInfo}.
|
|
||||||
*/
|
|
||||||
public static final String EXTRA_INPUT_METHOD_INFO = "input_method_info";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intent extra: The associated {@link InputMethodSubtype}.
|
|
||||||
*/
|
|
||||||
public static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
return MetricsEvent.INPUTMETHOD_KEYBOARD;
|
return MetricsEvent.INPUTMETHOD_KEYBOARD;
|
||||||
@@ -78,18 +56,14 @@ public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragme
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
Activity activity = Preconditions.checkNotNull(getActivity());
|
|
||||||
|
|
||||||
mInputDeviceIdentifier = activity.getIntent().getParcelableExtra(
|
mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
|
||||||
EXTRA_INPUT_DEVICE_IDENTIFIER);
|
EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||||
mImi = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_INFO);
|
if (mInputDeviceIdentifier == null) {
|
||||||
mSubtype = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_SUBTYPE);
|
getActivity().finish();
|
||||||
|
|
||||||
if (mInputDeviceIdentifier == null || mImi == null) {
|
|
||||||
activity.finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mIm = activity.getSystemService(InputManager.class);
|
mIm = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
||||||
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
|
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
|
||||||
Arrays.sort(mKeyboardLayouts);
|
Arrays.sort(mKeyboardLayouts);
|
||||||
setPreferenceScreen(createPreferenceHierarchy());
|
setPreferenceScreen(createPreferenceHierarchy());
|
||||||
@@ -108,6 +82,8 @@ public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragme
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mInputDeviceId = inputDevice.getId();
|
mInputDeviceId = inputDevice.getId();
|
||||||
|
|
||||||
|
updateCheckedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -120,21 +96,34 @@ public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceTreeClick(Preference preference) {
|
public boolean onPreferenceTreeClick(Preference preference) {
|
||||||
KeyboardLayout layout = mPreferenceMap.get(preference);
|
if (preference instanceof CheckBoxPreference) {
|
||||||
if (layout != null) {
|
CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
|
||||||
mIm.setKeyboardLayoutForInputDevice(mInputDeviceIdentifier, mImi, mSubtype,
|
KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
|
||||||
layout.getDescriptor());
|
if (layout != null) {
|
||||||
getActivity().finish();
|
boolean checked = checkboxPref.isChecked();
|
||||||
return true;
|
if (checked) {
|
||||||
|
mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
|
||||||
|
layout.getDescriptor());
|
||||||
|
} else {
|
||||||
|
mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
|
||||||
|
layout.getDescriptor());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.onPreferenceTreeClick(preference);
|
return super.onPreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceAdded(int deviceId) {}
|
public void onInputDeviceAdded(int deviceId) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceChanged(int deviceId) {}
|
public void onInputDeviceChanged(int deviceId) {
|
||||||
|
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
|
||||||
|
updateCheckedState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceRemoved(int deviceId) {
|
public void onInputDeviceRemoved(int deviceId) {
|
||||||
@@ -147,14 +136,23 @@ public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragme
|
|||||||
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
|
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
|
||||||
|
|
||||||
for (KeyboardLayout layout : mKeyboardLayouts) {
|
for (KeyboardLayout layout : mKeyboardLayouts) {
|
||||||
Preference pref = new Preference(getPrefContext());
|
CheckBoxPreference pref = new CheckBoxPreference(getPrefContext());
|
||||||
pref.setTitle(layout.getLabel());
|
pref.setTitle(layout.getLabel());
|
||||||
pref.setSummary(layout.getCollection());
|
pref.setSummary(layout.getCollection());
|
||||||
root.addPreference(pref);
|
root.addPreference(pref);
|
||||||
mPreferenceMap.put(pref, layout);
|
mPreferenceMap.put(pref, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setTitle(KeyboardInfoPreference.getDisplayName(getContext(), mImi, mSubtype));
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateCheckedState() {
|
||||||
|
String[] enabledKeyboardLayouts = mIm.getEnabledKeyboardLayoutsForInputDevice(
|
||||||
|
mInputDeviceIdentifier);
|
||||||
|
Arrays.sort(enabledKeyboardLayouts);
|
||||||
|
|
||||||
|
for (Map.Entry<CheckBoxPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
|
||||||
|
entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
|
||||||
|
entry.getValue().getDescriptor()) >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,8 @@ package com.android.settings.inputmethod;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.LoaderManager;
|
|
||||||
import android.content.AsyncTaskLoader;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Loader;
|
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.hardware.input.InputDeviceIdentifier;
|
import android.hardware.input.InputDeviceIdentifier;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
@@ -40,9 +37,6 @@ import android.support.v7.preference.PreferenceCategory;
|
|||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
|
||||||
|
|
||||||
import com.android.internal.inputmethod.InputMethodUtils;
|
import com.android.internal.inputmethod.InputMethodUtils;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
@@ -52,33 +46,25 @@ import com.android.settings.Settings;
|
|||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.search.Indexable;
|
import com.android.settings.search.Indexable;
|
||||||
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
||||||
implements InputManager.InputDeviceListener, Indexable {
|
implements InputManager.InputDeviceListener,
|
||||||
|
KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable {
|
||||||
|
|
||||||
private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
|
private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
|
||||||
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
|
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
|
||||||
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
|
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
|
||||||
private static final String IM_SUBTYPE_MODE_KEYBOARD = "keyboard";
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final List<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
|
private final ArrayList<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
|
||||||
@NonNull
|
|
||||||
private final List<KeyboardInfoPreference> mTempKeyboardInfoList = new ArrayList<>();
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final HashSet<Integer> mLoaderIDs = new HashSet<>();
|
|
||||||
private int mNextLoaderId = 0;
|
|
||||||
|
|
||||||
private InputManager mIm;
|
private InputManager mIm;
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -88,6 +74,8 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
@NonNull
|
@NonNull
|
||||||
private InputMethodUtils.InputMethodSettings mSettings;
|
private InputMethodUtils.InputMethodSettings mSettings;
|
||||||
|
|
||||||
|
private Intent mIntentWaitingForResult;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
Activity activity = Preconditions.checkNotNull(getActivity());
|
Activity activity = Preconditions.checkNotNull(getActivity());
|
||||||
@@ -118,9 +106,8 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
clearLoader();
|
|
||||||
mLastHardKeyboards.clear();
|
mLastHardKeyboards.clear();
|
||||||
updateHardKeyboards();
|
scheduleUpdateHardKeyboards();
|
||||||
mIm.registerInputDeviceListener(this, null);
|
mIm.registerInputDeviceListener(this, null);
|
||||||
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
|
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
|
||||||
mShowVirtualKeyboardSwitchPreferenceChangeListener);
|
mShowVirtualKeyboardSwitchPreferenceChangeListener);
|
||||||
@@ -130,67 +117,25 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
clearLoader();
|
|
||||||
mLastHardKeyboards.clear();
|
mLastHardKeyboards.clear();
|
||||||
mIm.unregisterInputDeviceListener(this);
|
mIm.unregisterInputDeviceListener(this);
|
||||||
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
|
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
|
||||||
unregisterShowVirtualKeyboardSettingsObserver();
|
unregisterShowVirtualKeyboardSettingsObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLoadFinishedInternal(
|
|
||||||
final int loaderId, @NonNull final List<Keyboards> keyboardsList) {
|
|
||||||
if (!mLoaderIDs.remove(loaderId)) {
|
|
||||||
// Already destroyed loader. Ignore.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(keyboardsList);
|
|
||||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
|
||||||
preferenceScreen.removeAll();
|
|
||||||
for (Keyboards keyboards : keyboardsList) {
|
|
||||||
final PreferenceCategory category = new PreferenceCategory(getPrefContext(), null);
|
|
||||||
category.setTitle(keyboards.mDeviceInfo.mDeviceName);
|
|
||||||
category.setOrder(0);
|
|
||||||
preferenceScreen.addPreference(category);
|
|
||||||
for (Keyboards.KeyboardInfo info : keyboards.mKeyboardInfoList) {
|
|
||||||
mTempKeyboardInfoList.clear();
|
|
||||||
final InputMethodInfo imi = info.mImi;
|
|
||||||
final InputMethodSubtype imSubtype = info.mImSubtype;
|
|
||||||
if (imi != null) {
|
|
||||||
KeyboardInfoPreference pref =
|
|
||||||
new KeyboardInfoPreference(getPrefContext(), info);
|
|
||||||
pref.setOnPreferenceClickListener(preference -> {
|
|
||||||
showKeyboardLayoutScreen(
|
|
||||||
keyboards.mDeviceInfo.mDeviceIdentifier, imi, imSubtype);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
mTempKeyboardInfoList.add(pref);
|
|
||||||
Collections.sort(mTempKeyboardInfoList);
|
|
||||||
}
|
|
||||||
for (KeyboardInfoPreference pref : mTempKeyboardInfoList) {
|
|
||||||
category.addPreference(pref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mTempKeyboardInfoList.clear();
|
|
||||||
mKeyboardAssistanceCategory.setOrder(1);
|
|
||||||
preferenceScreen.addPreference(mKeyboardAssistanceCategory);
|
|
||||||
updateShowVirtualKeyboardSwitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceAdded(int deviceId) {
|
public void onInputDeviceAdded(int deviceId) {
|
||||||
updateHardKeyboards();
|
scheduleUpdateHardKeyboards();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceRemoved(int deviceId) {
|
public void onInputDeviceRemoved(int deviceId) {
|
||||||
updateHardKeyboards();
|
scheduleUpdateHardKeyboards();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputDeviceChanged(int deviceId) {
|
public void onInputDeviceChanged(int deviceId) {
|
||||||
updateHardKeyboards();
|
scheduleUpdateHardKeyboards();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -198,50 +143,57 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
return MetricsEvent.PHYSICAL_KEYBOARDS;
|
return MetricsEvent.PHYSICAL_KEYBOARDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
private void scheduleUpdateHardKeyboards() {
|
||||||
public static List<HardKeyboardDeviceInfo> getHardKeyboards() {
|
final Context context = getContext();
|
||||||
final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
|
ThreadUtils.postOnBackgroundThread(() -> {
|
||||||
final int[] devicesIds = InputDevice.getDeviceIds();
|
final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards(context);
|
||||||
for (int deviceId : devicesIds) {
|
ThreadUtils.postOnMainThread(() -> updateHardKeyboards(newHardKeyboards));
|
||||||
final InputDevice device = InputDevice.getDevice(deviceId);
|
});
|
||||||
if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
|
|
||||||
keyboards.add(new HardKeyboardDeviceInfo(device.getName(), device.getIdentifier()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keyboards;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateHardKeyboards() {
|
private void updateHardKeyboards(@NonNull List<HardKeyboardDeviceInfo> newHardKeyboards) {
|
||||||
final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
|
if (Objects.equals(mLastHardKeyboards, newHardKeyboards)) {
|
||||||
if (!Objects.equals(newHardKeyboards, mLastHardKeyboards)) {
|
// Nothing has changed. Ignore.
|
||||||
clearLoader();
|
return;
|
||||||
mLastHardKeyboards.clear();
|
|
||||||
mLastHardKeyboards.addAll(newHardKeyboards);
|
|
||||||
mLoaderIDs.add(mNextLoaderId);
|
|
||||||
getLoaderManager().initLoader(mNextLoaderId, null,
|
|
||||||
new Callbacks(getContext(), this, mLastHardKeyboards));
|
|
||||||
++mNextLoaderId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(yukawa): Maybe we should follow the style used in ConnectedDeviceDashboardFragment.
|
||||||
|
|
||||||
|
mLastHardKeyboards.clear();
|
||||||
|
mLastHardKeyboards.addAll(newHardKeyboards);
|
||||||
|
|
||||||
|
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
|
preferenceScreen.removeAll();
|
||||||
|
final PreferenceCategory category = new PreferenceCategory(getPrefContext());
|
||||||
|
category.setTitle(R.string.builtin_keyboard_settings_title);
|
||||||
|
category.setOrder(0);
|
||||||
|
preferenceScreen.addPreference(category);
|
||||||
|
|
||||||
|
for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
|
||||||
|
// TODO(yukawa): Consider using com.android.settings.widget.GearPreference
|
||||||
|
final Preference pref = new Preference(getPrefContext());
|
||||||
|
pref.setTitle(hardKeyboardDeviceInfo.mDeviceName);
|
||||||
|
pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
|
||||||
|
pref.setOnPreferenceClickListener(preference -> {
|
||||||
|
showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
category.addPreference(pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
mKeyboardAssistanceCategory.setOrder(1);
|
||||||
|
preferenceScreen.addPreference(mKeyboardAssistanceCategory);
|
||||||
|
updateShowVirtualKeyboardSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showKeyboardLayoutScreen(
|
private void showKeyboardLayoutDialog(InputDeviceIdentifier inputDeviceIdentifier) {
|
||||||
@NonNull InputDeviceIdentifier inputDeviceIdentifier,
|
KeyboardLayoutDialogFragment fragment = (KeyboardLayoutDialogFragment)
|
||||||
@NonNull InputMethodInfo imi,
|
getFragmentManager().findFragmentByTag("keyboardLayout");
|
||||||
@Nullable InputMethodSubtype imSubtype) {
|
if (fragment == null) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
fragment = new KeyboardLayoutDialogFragment(inputDeviceIdentifier);
|
||||||
intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
|
fragment.setTargetFragment(this, 0);
|
||||||
intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
fragment.show(getActivity().getFragmentManager(), "keyboardLayout");
|
||||||
inputDeviceIdentifier);
|
|
||||||
intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_INFO, imi);
|
|
||||||
intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_SUBTYPE, imSubtype);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearLoader() {
|
|
||||||
for (final int loaderId : mLoaderIDs) {
|
|
||||||
getLoaderManager().destroyLoader(loaderId);
|
|
||||||
}
|
}
|
||||||
mLoaderIDs.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerShowVirtualKeyboardSettingsObserver() {
|
private void registerShowVirtualKeyboardSettingsObserver() {
|
||||||
@@ -282,102 +234,75 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final class Callbacks implements LoaderManager.LoaderCallbacks<List<Keyboards>> {
|
@Override
|
||||||
@NonNull
|
public void onSetupKeyboardLayouts(InputDeviceIdentifier inputDeviceIdentifier) {
|
||||||
final Context mContext;
|
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||||
@NonNull
|
intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
|
||||||
final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
|
intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
||||||
@NonNull
|
inputDeviceIdentifier);
|
||||||
final List<HardKeyboardDeviceInfo> mHardKeyboards;
|
mIntentWaitingForResult = intent;
|
||||||
|
startActivityForResult(intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public Callbacks(
|
@Override
|
||||||
@NonNull Context context,
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
@NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
@NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
|
|
||||||
mContext = context;
|
|
||||||
mPhysicalKeyboardFragment = physicalKeyboardFragment;
|
|
||||||
mHardKeyboards = hardKeyboards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (mIntentWaitingForResult != null) {
|
||||||
public Loader<List<Keyboards>> onCreateLoader(int id, Bundle args) {
|
InputDeviceIdentifier inputDeviceIdentifier = mIntentWaitingForResult
|
||||||
return new KeyboardLayoutLoader(mContext, mHardKeyboards);
|
.getParcelableExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||||
}
|
mIntentWaitingForResult = null;
|
||||||
|
showKeyboardLayoutDialog(inputDeviceIdentifier);
|
||||||
@Override
|
|
||||||
public void onLoadFinished(Loader<List<Keyboards>> loader, List<Keyboards> data) {
|
|
||||||
mPhysicalKeyboardFragment.onLoadFinishedInternal(loader.getId(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaderReset(Loader<List<Keyboards>> loader) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class KeyboardLayoutLoader extends AsyncTaskLoader<List<Keyboards>> {
|
private static String getLayoutLabel(@NonNull InputDevice device,
|
||||||
@NonNull
|
@NonNull Context context, @NonNull InputManager im) {
|
||||||
private final List<HardKeyboardDeviceInfo> mHardKeyboards;
|
final String currentLayoutDesc =
|
||||||
|
im.getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
|
||||||
public KeyboardLayoutLoader(
|
if (currentLayoutDesc == null) {
|
||||||
@NonNull Context context,
|
return context.getString(R.string.keyboard_layout_default_label);
|
||||||
@NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
|
|
||||||
super(context);
|
|
||||||
mHardKeyboards = Preconditions.checkNotNull(hardKeyboards);
|
|
||||||
}
|
}
|
||||||
|
final KeyboardLayout currentLayout = im.getKeyboardLayout(currentLayoutDesc);
|
||||||
|
if (currentLayout == null) {
|
||||||
|
return context.getString(R.string.keyboard_layout_default_label);
|
||||||
|
}
|
||||||
|
// If current layout is specified but the layout is null, just return an empty string
|
||||||
|
// instead of falling back to R.string.keyboard_layout_default_label.
|
||||||
|
return TextUtils.emptyIfNull(currentLayout.getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
private Keyboards loadInBackground(HardKeyboardDeviceInfo deviceInfo) {
|
@NonNull
|
||||||
final ArrayList<Keyboards.KeyboardInfo> keyboardInfoList = new ArrayList<>();
|
static List<HardKeyboardDeviceInfo> getHardKeyboards(@NonNull Context context) {
|
||||||
final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
|
final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
|
||||||
final InputManager im = getContext().getSystemService(InputManager.class);
|
final InputManager im = context.getSystemService(InputManager.class);
|
||||||
if (imm != null && im != null) {
|
if (im == null) {
|
||||||
for (InputMethodInfo imi : imm.getEnabledInputMethodList()) {
|
return new ArrayList<>();
|
||||||
final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(
|
}
|
||||||
imi, true /* allowsImplicitlySelectedSubtypes */);
|
for (int deviceId : InputDevice.getDeviceIds()) {
|
||||||
if (subtypes.isEmpty()) {
|
final InputDevice device = InputDevice.getDevice(deviceId);
|
||||||
// Here we use null to indicate that this IME has no subtype.
|
if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
|
||||||
final InputMethodSubtype nullSubtype = null;
|
continue;
|
||||||
final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
|
|
||||||
deviceInfo.mDeviceIdentifier, imi, nullSubtype);
|
|
||||||
keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, nullSubtype, layout));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the IME supports subtypes, we pick up "keyboard" subtypes only.
|
|
||||||
final int N = subtypes.size();
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
final InputMethodSubtype subtype = subtypes.get(i);
|
|
||||||
if (!IM_SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
|
|
||||||
deviceInfo.mDeviceIdentifier, imi, subtype);
|
|
||||||
keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, subtype, layout));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new Keyboards(deviceInfo, keyboardInfoList);
|
keyboards.add(new HardKeyboardDeviceInfo(
|
||||||
|
device.getName(), device.getIdentifier(), getLayoutLabel(device, context, im)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// We intentionally don't reuse Comparator because Collator may not be thread-safe.
|
||||||
public List<Keyboards> loadInBackground() {
|
final Collator collator = Collator.getInstance();
|
||||||
List<Keyboards> keyboardsList = new ArrayList<>(mHardKeyboards.size());
|
keyboards.sort((a, b) -> {
|
||||||
for (HardKeyboardDeviceInfo deviceInfo : mHardKeyboards) {
|
int result = collator.compare(a.mDeviceName, b.mDeviceName);
|
||||||
keyboardsList.add(loadInBackground(deviceInfo));
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return keyboardsList;
|
result = a.mDeviceIdentifier.getDescriptor().compareTo(
|
||||||
}
|
b.mDeviceIdentifier.getDescriptor());
|
||||||
|
if (result != 0) {
|
||||||
@Override
|
return result;
|
||||||
protected void onStartLoading() {
|
}
|
||||||
super.onStartLoading();
|
return collator.compare(a.mLayoutLabel, b.mLayoutLabel);
|
||||||
forceLoad();
|
});
|
||||||
}
|
return keyboards;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStopLoading() {
|
|
||||||
super.onStopLoading();
|
|
||||||
cancelLoad();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class HardKeyboardDeviceInfo {
|
public static final class HardKeyboardDeviceInfo {
|
||||||
@@ -385,12 +310,16 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
public final String mDeviceName;
|
public final String mDeviceName;
|
||||||
@NonNull
|
@NonNull
|
||||||
public final InputDeviceIdentifier mDeviceIdentifier;
|
public final InputDeviceIdentifier mDeviceIdentifier;
|
||||||
|
@NonNull
|
||||||
|
public final String mLayoutLabel;
|
||||||
|
|
||||||
public HardKeyboardDeviceInfo(
|
public HardKeyboardDeviceInfo(
|
||||||
@Nullable final String deviceName,
|
@Nullable String deviceName,
|
||||||
@NonNull final InputDeviceIdentifier deviceIdentifier) {
|
@NonNull InputDeviceIdentifier deviceIdentifier,
|
||||||
mDeviceName = deviceName != null ? deviceName : "";
|
@NonNull String layoutLabel) {
|
||||||
|
mDeviceName = TextUtils.emptyIfNull(deviceName);
|
||||||
mDeviceIdentifier = deviceIdentifier;
|
mDeviceIdentifier = deviceIdentifier;
|
||||||
|
mLayoutLabel = layoutLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -404,14 +333,10 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
if (!TextUtils.equals(mDeviceName, that.mDeviceName)) {
|
if (!TextUtils.equals(mDeviceName, that.mDeviceName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mDeviceIdentifier.getVendorId() != that.mDeviceIdentifier.getVendorId()) {
|
if (!Objects.equals(mDeviceIdentifier, that.mDeviceIdentifier)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mDeviceIdentifier.getProductId() != that.mDeviceIdentifier.getProductId()) {
|
if (!TextUtils.equals(mLayoutLabel, that.mLayoutLabel)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!TextUtils.equals(mDeviceIdentifier.getDescriptor(),
|
|
||||||
that.mDeviceIdentifier.getDescriptor())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,121 +344,6 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Keyboards implements Comparable<Keyboards> {
|
|
||||||
@NonNull
|
|
||||||
public final HardKeyboardDeviceInfo mDeviceInfo;
|
|
||||||
@NonNull
|
|
||||||
public final ArrayList<KeyboardInfo> mKeyboardInfoList;
|
|
||||||
@NonNull
|
|
||||||
public final Collator mCollator = Collator.getInstance();
|
|
||||||
|
|
||||||
public Keyboards(
|
|
||||||
@NonNull final HardKeyboardDeviceInfo deviceInfo,
|
|
||||||
@NonNull final ArrayList<KeyboardInfo> keyboardInfoList) {
|
|
||||||
mDeviceInfo = deviceInfo;
|
|
||||||
mKeyboardInfoList = keyboardInfoList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(@NonNull Keyboards another) {
|
|
||||||
return mCollator.compare(mDeviceInfo.mDeviceName, another.mDeviceInfo.mDeviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class KeyboardInfo {
|
|
||||||
@NonNull
|
|
||||||
public final InputMethodInfo mImi;
|
|
||||||
@Nullable
|
|
||||||
public final InputMethodSubtype mImSubtype;
|
|
||||||
@NonNull
|
|
||||||
public final KeyboardLayout mLayout;
|
|
||||||
|
|
||||||
public KeyboardInfo(
|
|
||||||
@NonNull final InputMethodInfo imi,
|
|
||||||
@Nullable final InputMethodSubtype imSubtype,
|
|
||||||
@NonNull final KeyboardLayout layout) {
|
|
||||||
mImi = imi;
|
|
||||||
mImSubtype = imSubtype;
|
|
||||||
mLayout = layout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class KeyboardInfoPreference extends Preference {
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final CharSequence mImeName;
|
|
||||||
@Nullable
|
|
||||||
private final CharSequence mImSubtypeName;
|
|
||||||
@NonNull
|
|
||||||
private final Collator collator = Collator.getInstance();
|
|
||||||
|
|
||||||
private KeyboardInfoPreference(
|
|
||||||
@NonNull Context context, @NonNull Keyboards.KeyboardInfo info) {
|
|
||||||
super(context);
|
|
||||||
mImeName = info.mImi.loadLabel(context.getPackageManager());
|
|
||||||
mImSubtypeName = getImSubtypeName(context, info.mImi, info.mImSubtype);
|
|
||||||
setTitle(formatDisplayName(context, mImeName, mImSubtypeName));
|
|
||||||
if (info.mLayout != null) {
|
|
||||||
setSummary(info.mLayout.getLabel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
static CharSequence getDisplayName(
|
|
||||||
@NonNull Context context, @NonNull InputMethodInfo imi,
|
|
||||||
@Nullable InputMethodSubtype imSubtype) {
|
|
||||||
final CharSequence imeName = imi.loadLabel(context.getPackageManager());
|
|
||||||
final CharSequence imSubtypeName = getImSubtypeName(context, imi, imSubtype);
|
|
||||||
return formatDisplayName(context, imeName, imSubtypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CharSequence formatDisplayName(
|
|
||||||
@NonNull Context context,
|
|
||||||
@NonNull CharSequence imeName, @Nullable CharSequence imSubtypeName) {
|
|
||||||
if (imSubtypeName == null) {
|
|
||||||
return imeName;
|
|
||||||
}
|
|
||||||
return String.format(
|
|
||||||
context.getString(R.string.physical_device_title), imeName, imSubtypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static CharSequence getImSubtypeName(
|
|
||||||
@NonNull Context context, @NonNull InputMethodInfo imi,
|
|
||||||
@Nullable InputMethodSubtype imSubtype) {
|
|
||||||
if (imSubtype != null) {
|
|
||||||
return InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
|
|
||||||
imSubtype, context, imi);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(@NonNull Preference object) {
|
|
||||||
if (!(object instanceof KeyboardInfoPreference)) {
|
|
||||||
return super.compareTo(object);
|
|
||||||
}
|
|
||||||
KeyboardInfoPreference another = (KeyboardInfoPreference) object;
|
|
||||||
int result = compare(mImeName, another.mImeName);
|
|
||||||
if (result == 0) {
|
|
||||||
result = compare(mImSubtypeName, another.mImSubtypeName);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int compare(@Nullable CharSequence lhs, @Nullable CharSequence rhs) {
|
|
||||||
if (!TextUtils.isEmpty(lhs) && !TextUtils.isEmpty(rhs)) {
|
|
||||||
return collator.compare(lhs.toString(), rhs.toString());
|
|
||||||
} else if (TextUtils.isEmpty(lhs) && TextUtils.isEmpty(rhs)) {
|
|
||||||
return 0;
|
|
||||||
} else if (!TextUtils.isEmpty(lhs)) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider() {
|
new BaseSearchIndexProvider() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class PhysicalKeyboardPreferenceController extends AbstractPreferenceCont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final List<HardKeyboardDeviceInfo> keyboards =
|
final List<HardKeyboardDeviceInfo> keyboards =
|
||||||
PhysicalKeyboardFragment.getHardKeyboards();
|
PhysicalKeyboardFragment.getHardKeyboards(mContext);
|
||||||
if (keyboards.isEmpty()) {
|
if (keyboards.isEmpty()) {
|
||||||
mPreference.setSummary(R.string.disconnected);
|
mPreference.setSummary(R.string.disconnected);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.content.Intent;
|
|||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.provider.SettingsSlicesContract;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -63,6 +64,10 @@ public class SettingsSliceProvider extends SliceProvider {
|
|||||||
|
|
||||||
private static final String TAG = "SettingsSliceProvider";
|
private static final String TAG = "SettingsSliceProvider";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authority for Settings slices not officially supported by the platform, but extensible for
|
||||||
|
* OEMs.
|
||||||
|
*/
|
||||||
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
|
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
|
||||||
|
|
||||||
public static final String PATH_WIFI = "wifi";
|
public static final String PATH_WIFI = "wifi";
|
||||||
@@ -82,13 +87,6 @@ public class SettingsSliceProvider extends SliceProvider {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Map<Uri, SliceData> mSliceDataCache;
|
Map<Uri, SliceData> mSliceDataCache;
|
||||||
|
|
||||||
public static Uri getUri(String path) {
|
|
||||||
return new Uri.Builder()
|
|
||||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
|
||||||
.authority(SLICE_AUTHORITY)
|
|
||||||
.appendPath(path).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateSliceProvider() {
|
public boolean onCreateSliceProvider() {
|
||||||
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
|
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
|
||||||
@@ -176,7 +174,8 @@ public class SettingsSliceProvider extends SliceProvider {
|
|||||||
.setSubtitle(state)
|
.setSubtitle(state)
|
||||||
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
|
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
|
||||||
null, finalWifiEnabled))
|
null, finalWifiEnabled))
|
||||||
.setPrimaryAction(new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
|
.setPrimaryAction(
|
||||||
|
new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
|
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
|
||||||
Handler h = new Handler();
|
Handler h = new Handler();
|
||||||
h.postDelayed(() -> {
|
h.postDelayed(() -> {
|
||||||
Uri uri = SettingsSliceProvider.getUri(SettingsSliceProvider.PATH_WIFI);
|
Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
|
||||||
|
false /* isPlatformSlice */);
|
||||||
context.getContentResolver().notifyChange(uri, null);
|
context.getContentResolver().notifyChange(uri, null);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -19,9 +19,12 @@ package com.android.settings.slices;
|
|||||||
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
|
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.SettingsSlicesContract;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -98,6 +101,17 @@ public class SliceBuilderUtils {
|
|||||||
sliceData.getKey());
|
sliceData.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Uri getUri(String path, boolean isPlatformSlice) {
|
||||||
|
final String authority = isPlatformSlice
|
||||||
|
? SettingsSlicesContract.AUTHORITY
|
||||||
|
: SettingsSliceProvider.SLICE_AUTHORITY;
|
||||||
|
return new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(authority)
|
||||||
|
.appendPath(path)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private static BasePreferenceController getPreferenceController(Context context,
|
private static BasePreferenceController getPreferenceController(Context context,
|
||||||
String controllerClassName, String controllerKey) {
|
String controllerClassName, String controllerKey) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public class SliceData {
|
|||||||
@SliceType
|
@SliceType
|
||||||
private final int mSliceType;
|
private final int mSliceType;
|
||||||
|
|
||||||
|
private final boolean mIsPlatformDefined;
|
||||||
|
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return mKey;
|
return mKey;
|
||||||
}
|
}
|
||||||
@@ -106,6 +108,10 @@ public class SliceData {
|
|||||||
return mSliceType;
|
return mSliceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPlatformDefined() {
|
||||||
|
return mIsPlatformDefined;
|
||||||
|
}
|
||||||
|
|
||||||
private SliceData(Builder builder) {
|
private SliceData(Builder builder) {
|
||||||
mKey = builder.mKey;
|
mKey = builder.mKey;
|
||||||
mTitle = builder.mTitle;
|
mTitle = builder.mTitle;
|
||||||
@@ -116,6 +122,7 @@ public class SliceData {
|
|||||||
mUri = builder.mUri;
|
mUri = builder.mUri;
|
||||||
mPreferenceController = builder.mPrefControllerClassName;
|
mPreferenceController = builder.mPrefControllerClassName;
|
||||||
mSliceType = builder.mSliceType;
|
mSliceType = builder.mSliceType;
|
||||||
|
mIsPlatformDefined = builder.mIsPlatformDefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -151,6 +158,8 @@ public class SliceData {
|
|||||||
|
|
||||||
private int mSliceType;
|
private int mSliceType;
|
||||||
|
|
||||||
|
private boolean mIsPlatformDefined;
|
||||||
|
|
||||||
public Builder setKey(String key) {
|
public Builder setKey(String key) {
|
||||||
mKey = key;
|
mKey = key;
|
||||||
return this;
|
return this;
|
||||||
@@ -196,6 +205,11 @@ public class SliceData {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setPlatformDefined(boolean isPlatformDefined) {
|
||||||
|
mIsPlatformDefined = isPlatformDefined;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SliceData build() {
|
public SliceData build() {
|
||||||
if (TextUtils.isEmpty(mKey)) {
|
if (TextUtils.isEmpty(mKey)) {
|
||||||
throw new IllegalStateException("Key cannot be empty");
|
throw new IllegalStateException("Key cannot be empty");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.settings.slices;
|
|||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
|
||||||
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFORM_SLICE_FLAG;
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
|
||||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
|
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
|
||||||
|
|
||||||
@@ -164,7 +165,8 @@ class SliceDataConverter {
|
|||||||
| MetadataFlag.FLAG_NEED_PREF_TYPE
|
| MetadataFlag.FLAG_NEED_PREF_TYPE
|
||||||
| MetadataFlag.FLAG_NEED_PREF_TITLE
|
| MetadataFlag.FLAG_NEED_PREF_TITLE
|
||||||
| MetadataFlag.FLAG_NEED_PREF_ICON
|
| MetadataFlag.FLAG_NEED_PREF_ICON
|
||||||
| MetadataFlag.FLAG_NEED_PREF_SUMMARY);
|
| MetadataFlag.FLAG_NEED_PREF_SUMMARY
|
||||||
|
| MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG);
|
||||||
|
|
||||||
for (Bundle bundle : metadata) {
|
for (Bundle bundle : metadata) {
|
||||||
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
|
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
|
||||||
@@ -179,6 +181,7 @@ class SliceDataConverter {
|
|||||||
final int iconResId = bundle.getInt(METADATA_ICON);
|
final int iconResId = bundle.getInt(METADATA_ICON);
|
||||||
final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName,
|
final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName,
|
||||||
key);
|
key);
|
||||||
|
final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG);
|
||||||
|
|
||||||
final SliceData xmlSlice = new SliceData.Builder()
|
final SliceData xmlSlice = new SliceData.Builder()
|
||||||
.setKey(key)
|
.setKey(key)
|
||||||
@@ -189,6 +192,7 @@ class SliceDataConverter {
|
|||||||
.setPreferenceControllerClassName(controllerClassName)
|
.setPreferenceControllerClassName(controllerClassName)
|
||||||
.setFragmentName(fragmentName)
|
.setFragmentName(fragmentName)
|
||||||
.setSliceType(sliceType)
|
.setSliceType(sliceType)
|
||||||
|
.setPlatformDefined(isPlatformSlice)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
xmlSliceData.add(xmlSlice);
|
xmlSliceData.add(xmlSlice);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
android:title="title"
|
android:title="title"
|
||||||
android:icon="@drawable/ic_android"
|
android:icon="@drawable/ic_android"
|
||||||
android:summary="summary"
|
android:summary="summary"
|
||||||
settings:controller="com.android.settings.slices.FakePreferenceController"/>
|
settings:controller="com.android.settings.slices.FakePreferenceController"
|
||||||
|
settings:platform_slice="true"/>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -55,7 +55,7 @@ public class PhysicalKeyboardPreferenceControllerTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
|
when(mContext.getSystemService(InputManager.class)).thenReturn(mIm);
|
||||||
mController = new PhysicalKeyboardPreferenceController(mContext, null /* lifecycle */);
|
mController = new PhysicalKeyboardPreferenceController(mContext, null /* lifecycle */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
package com.android.settings.slices;
|
package com.android.settings.slices;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Mockito.doReturn;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -28,6 +27,7 @@ import android.content.ContentValues;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.provider.SettingsSlicesContract;
|
||||||
|
|
||||||
import com.android.settings.testutils.DatabaseTestUtils;
|
import com.android.settings.testutils.DatabaseTestUtils;
|
||||||
import com.android.settings.testutils.FakeToggleController;
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
@@ -50,6 +50,8 @@ import java.util.HashMap;
|
|||||||
public class SettingsSliceProviderTest {
|
public class SettingsSliceProviderTest {
|
||||||
|
|
||||||
private final String KEY = "KEY";
|
private final String KEY = "KEY";
|
||||||
|
private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
|
||||||
|
private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
|
||||||
private final String TITLE = "title";
|
private final String TITLE = "title";
|
||||||
private final String SUMMARY = "summary";
|
private final String SUMMARY = "summary";
|
||||||
private final String SCREEN_TITLE = "screen title";
|
private final String SCREEN_TITLE = "screen title";
|
||||||
@@ -67,6 +69,8 @@ public class SettingsSliceProviderTest {
|
|||||||
mProvider = spy(new SettingsSliceProvider());
|
mProvider = spy(new SettingsSliceProvider());
|
||||||
mProvider.mSliceDataCache = new HashMap<>();
|
mProvider.mSliceDataCache = new HashMap<>();
|
||||||
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
|
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
|
||||||
|
when(mProvider.getContext()).thenReturn(mContext);
|
||||||
|
|
||||||
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
||||||
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
|
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
|
||||||
}
|
}
|
||||||
@@ -78,34 +82,18 @@ public class SettingsSliceProviderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitialSliceReturned_emptySlice() {
|
public void testInitialSliceReturned_emptySlice() {
|
||||||
insertSpecialCase(KEY);
|
insertSpecialCase(INTENT_PATH);
|
||||||
ContentResolver mockResolver = mock(ContentResolver.class);
|
Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
|
||||||
doReturn(mockResolver).when(mContext).getContentResolver();
|
|
||||||
when(mProvider.getContext()).thenReturn(mContext);
|
|
||||||
|
|
||||||
Uri uri = SettingsSliceProvider.getUri(KEY);
|
|
||||||
Slice slice = mProvider.onBindSlice(uri);
|
Slice slice = mProvider.onBindSlice(uri);
|
||||||
|
|
||||||
assertThat(slice.getUri()).isEqualTo(uri);
|
assertThat(slice.getUri()).isEqualTo(uri);
|
||||||
assertThat(slice.getItems()).isEmpty();
|
assertThat(slice.getItems()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUriBuilder_returnsValidSliceUri() {
|
|
||||||
Uri uri = SettingsSliceProvider.getUri(KEY);
|
|
||||||
|
|
||||||
assertThat(uri.getScheme()).isEqualTo(ContentResolver.SCHEME_CONTENT);
|
|
||||||
assertThat(uri.getAuthority()).isEqualTo(SettingsSliceProvider.SLICE_AUTHORITY);
|
|
||||||
assertThat(uri.getLastPathSegment()).isEqualTo(KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadSlice_returnsSliceFromAccessor() {
|
public void testLoadSlice_returnsSliceFromAccessor() {
|
||||||
ContentResolver mockResolver = mock(ContentResolver.class);
|
|
||||||
doReturn(mockResolver).when(mContext).getContentResolver();
|
|
||||||
when(mProvider.getContext()).thenReturn(mContext);
|
|
||||||
insertSpecialCase(KEY);
|
insertSpecialCase(KEY);
|
||||||
Uri uri = SettingsSliceProvider.getUri(KEY);
|
Uri uri = SliceBuilderUtils.getUri(KEY, false);
|
||||||
|
|
||||||
mProvider.loadSlice(uri);
|
mProvider.loadSlice(uri);
|
||||||
SliceData data = mProvider.mSliceDataCache.get(uri);
|
SliceData data = mProvider.mSliceDataCache.get(uri);
|
||||||
@@ -116,7 +104,6 @@ public class SettingsSliceProviderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadSlice_cachedEntryRemovedOnBuild() {
|
public void testLoadSlice_cachedEntryRemovedOnBuild() {
|
||||||
when(mProvider.getContext()).thenReturn(mContext);
|
|
||||||
SliceData data = getDummyData();
|
SliceData data = getDummyData();
|
||||||
mProvider.mSliceDataCache.put(data.getUri(), data);
|
mProvider.mSliceDataCache.put(data.getUri(), data);
|
||||||
mProvider.onBindSlice(data.getUri());
|
mProvider.onBindSlice(data.getUri());
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.provider.SettingsSlicesContract;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
@@ -48,6 +50,9 @@ public class SliceBuilderUtilsTest {
|
|||||||
private final Class PREF_CONTROLLER = FakeToggleController.class;
|
private final Class PREF_CONTROLLER = FakeToggleController.class;
|
||||||
private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
|
private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
|
||||||
|
|
||||||
|
private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
|
||||||
|
private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -62,6 +67,58 @@ public class SliceBuilderUtilsTest {
|
|||||||
assertThat(slice).isNotNull(); // TODO improve test for Slice content
|
assertThat(slice).isNotNull(); // TODO improve test for Slice content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
|
||||||
|
Uri expectedUri = new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||||
|
.appendPath(INTENT_PATH)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Uri actualUri = SliceBuilderUtils.getUri(INTENT_PATH, false);
|
||||||
|
|
||||||
|
assertThat(actualUri).isEqualTo(expectedUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUriBuilder_oemAuthority_actionPath_returnsValidSliceUri() {
|
||||||
|
Uri expectedUri = new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||||
|
.appendPath(ACTION_PATH)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, false);
|
||||||
|
|
||||||
|
assertThat(actualUri).isEqualTo(expectedUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUriBuilder_platformAuthority_intentPath_returnsValidSliceUri() {
|
||||||
|
Uri expectedUri = new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(SettingsSlicesContract.AUTHORITY)
|
||||||
|
.appendPath(ACTION_PATH)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
|
||||||
|
|
||||||
|
assertThat(actualUri).isEqualTo(expectedUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUriBuilder_platformAuthority_actionPath_returnsValidSliceUri() {
|
||||||
|
Uri expectedUri = new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(SettingsSlicesContract.AUTHORITY)
|
||||||
|
.appendPath(ACTION_PATH)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
|
||||||
|
|
||||||
|
assertThat(actualUri).isEqualTo(expectedUri);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPreferenceController_buildsMatchingController() {
|
public void testGetPreferenceController_buildsMatchingController() {
|
||||||
BasePreferenceController controller =
|
BasePreferenceController controller =
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ public class SliceDataConverterTest {
|
|||||||
assertThat(fakeSlice.getUri()).isNull();
|
assertThat(fakeSlice.getUri()).isNull();
|
||||||
assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
|
assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
|
||||||
assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
|
assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
|
||||||
assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
|
assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); // from XML
|
||||||
|
assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,7 @@ public class SliceDataTest {
|
|||||||
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
|
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
|
||||||
private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
|
private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
|
||||||
private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
|
private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
|
||||||
|
private final boolean IS_PLATFORM_DEFINED = true;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuilder_buildsMatchingObject() {
|
public void testBuilder_buildsMatchingObject() {
|
||||||
@@ -49,7 +50,8 @@ public class SliceDataTest {
|
|||||||
.setFragmentName(FRAGMENT_NAME)
|
.setFragmentName(FRAGMENT_NAME)
|
||||||
.setUri(URI)
|
.setUri(URI)
|
||||||
.setPreferenceControllerClassName(PREF_CONTROLLER)
|
.setPreferenceControllerClassName(PREF_CONTROLLER)
|
||||||
.setSliceType(SLICE_TYPE);
|
.setSliceType(SLICE_TYPE)
|
||||||
|
.setPlatformDefined(IS_PLATFORM_DEFINED);
|
||||||
|
|
||||||
SliceData data = builder.build();
|
SliceData data = builder.build();
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ public class SliceDataTest {
|
|||||||
assertThat(data.getUri()).isEqualTo(URI);
|
assertThat(data.getUri()).isEqualTo(URI);
|
||||||
assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
|
assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
|
||||||
assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
|
assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
|
||||||
|
assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class SlicesDatabaseAccessorTest {
|
|||||||
public void testGetSliceFromUri_validUri_validSliceReturned() {
|
public void testGetSliceFromUri_validUri_validSliceReturned() {
|
||||||
String key = "key";
|
String key = "key";
|
||||||
insertSpecialCase(key);
|
insertSpecialCase(key);
|
||||||
Uri uri = SettingsSliceProvider.getUri(key);
|
Uri uri = SliceBuilderUtils.getUri(key, false);
|
||||||
|
|
||||||
SliceData data = mAccessor.getSliceDataFromUri(uri);
|
SliceData data = mAccessor.getSliceDataFromUri(uri);
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ public class SlicesDatabaseAccessorTest {
|
|||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testGetSliceFromUri_invalidUri_errorThrown() {
|
public void testGetSliceFromUri_invalidUri_errorThrown() {
|
||||||
Uri uri = SettingsSliceProvider.getUri("durr");
|
Uri uri = SliceBuilderUtils.getUri("durr", false);
|
||||||
|
|
||||||
mAccessor.getSliceDataFromUri(uri);
|
mAccessor.getSliceDataFromUri(uri);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user