Bug: 35315463 Test: adb shell am start -a android.settings.INPUT_METHOD_SUBTYPE_SETTINGS Change-Id: I17e6e64ff2c01577d4036bccafe7d0b4ad1d5ca5
575 lines
23 KiB
Java
575 lines
23 KiB
Java
/*
|
|
* Copyright (C) 2016 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.inputmethod;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.app.Activity;
|
|
import android.app.LoaderManager;
|
|
import android.content.AsyncTaskLoader;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.Loader;
|
|
import android.database.ContentObserver;
|
|
import android.hardware.input.InputDeviceIdentifier;
|
|
import android.hardware.input.InputManager;
|
|
import android.hardware.input.KeyboardLayout;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.UserHandle;
|
|
import android.provider.Settings.Secure;
|
|
import android.support.v14.preference.SwitchPreference;
|
|
import android.support.v7.preference.Preference;
|
|
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
|
import android.support.v7.preference.PreferenceCategory;
|
|
import android.support.v7.preference.PreferenceScreen;
|
|
import android.text.TextUtils;
|
|
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.logging.nano.MetricsProto.MetricsEvent;
|
|
import com.android.internal.util.Preconditions;
|
|
import com.android.settings.R;
|
|
import com.android.settings.Settings;
|
|
import com.android.settings.SettingsPreferenceFragment;
|
|
import com.android.settings.search.BaseSearchIndexProvider;
|
|
import com.android.settings.search.Indexable;
|
|
import com.android.settings.search.SearchIndexableRaw;
|
|
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
|
|
|
|
import java.text.Collator;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
|
implements InputManager.InputDeviceListener, Indexable {
|
|
|
|
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 KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
|
|
private static final String IM_SUBTYPE_MODE_KEYBOARD = "keyboard";
|
|
|
|
@NonNull
|
|
private final List<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;
|
|
@NonNull
|
|
private PreferenceCategory mKeyboardAssistanceCategory;
|
|
@NonNull
|
|
private SwitchPreference mShowVirtualKeyboardSwitch;
|
|
@NonNull
|
|
private InputMethodUtils.InputMethodSettings mSettings;
|
|
|
|
@Override
|
|
public void onCreatePreferences(Bundle bundle, String s) {
|
|
Activity activity = Preconditions.checkNotNull(getActivity());
|
|
addPreferencesFromResource(R.xml.physical_keyboard_settings);
|
|
mIm = Preconditions.checkNotNull(activity.getSystemService(InputManager.class));
|
|
mSettings = new InputMethodUtils.InputMethodSettings(
|
|
activity.getResources(),
|
|
getContentResolver(),
|
|
new HashMap<>(),
|
|
new ArrayList<>(),
|
|
UserHandle.myUserId(),
|
|
false /* copyOnWrite */);
|
|
mKeyboardAssistanceCategory = Preconditions.checkNotNull(
|
|
(PreferenceCategory) findPreference(KEYBOARD_ASSISTANCE_CATEGORY));
|
|
mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
|
|
(SwitchPreference) mKeyboardAssistanceCategory.findPreference(
|
|
SHOW_VIRTUAL_KEYBOARD_SWITCH));
|
|
findPreference(KEYBOARD_SHORTCUTS_HELPER).setOnPreferenceClickListener(
|
|
new Preference.OnPreferenceClickListener() {
|
|
@Override
|
|
public boolean onPreferenceClick(Preference preference) {
|
|
toggleKeyboardShortcutsMenu();
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
clearLoader();
|
|
mLastHardKeyboards.clear();
|
|
updateHardKeyboards();
|
|
mIm.registerInputDeviceListener(this, null);
|
|
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
|
|
mShowVirtualKeyboardSwitchPreferenceChangeListener);
|
|
registerShowVirtualKeyboardSettingsObserver();
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
super.onPause();
|
|
clearLoader();
|
|
mLastHardKeyboards.clear();
|
|
mIm.unregisterInputDeviceListener(this);
|
|
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
|
|
unregisterShowVirtualKeyboardSettingsObserver();
|
|
}
|
|
|
|
public 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
|
|
public void onInputDeviceAdded(int deviceId) {
|
|
updateHardKeyboards();
|
|
}
|
|
|
|
@Override
|
|
public void onInputDeviceRemoved(int deviceId) {
|
|
updateHardKeyboards();
|
|
}
|
|
|
|
@Override
|
|
public void onInputDeviceChanged(int deviceId) {
|
|
updateHardKeyboards();
|
|
}
|
|
|
|
@Override
|
|
public int getMetricsCategory() {
|
|
return MetricsEvent.PHYSICAL_KEYBOARDS;
|
|
}
|
|
|
|
@NonNull
|
|
private static ArrayList<HardKeyboardDeviceInfo> getHardKeyboards() {
|
|
final ArrayList<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
|
|
final int[] devicesIds = InputDevice.getDeviceIds();
|
|
for (int deviceId : devicesIds) {
|
|
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() {
|
|
final ArrayList<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
|
|
if (!Objects.equals(newHardKeyboards, mLastHardKeyboards)) {
|
|
clearLoader();
|
|
mLastHardKeyboards.clear();
|
|
mLastHardKeyboards.addAll(newHardKeyboards);
|
|
mLoaderIDs.add(mNextLoaderId);
|
|
getLoaderManager().initLoader(mNextLoaderId, null,
|
|
new Callbacks(getContext(), this, mLastHardKeyboards));
|
|
++mNextLoaderId;
|
|
}
|
|
}
|
|
|
|
private void showKeyboardLayoutScreen(
|
|
@NonNull InputDeviceIdentifier inputDeviceIdentifier,
|
|
@NonNull InputMethodInfo imi,
|
|
@Nullable InputMethodSubtype imSubtype) {
|
|
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
|
intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
|
|
intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
|
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() {
|
|
unregisterShowVirtualKeyboardSettingsObserver();
|
|
getActivity().getContentResolver().registerContentObserver(
|
|
Secure.getUriFor(Secure.SHOW_IME_WITH_HARD_KEYBOARD),
|
|
false,
|
|
mContentObserver,
|
|
UserHandle.myUserId());
|
|
updateShowVirtualKeyboardSwitch();
|
|
}
|
|
|
|
private void unregisterShowVirtualKeyboardSettingsObserver() {
|
|
getActivity().getContentResolver().unregisterContentObserver(mContentObserver);
|
|
}
|
|
|
|
private void updateShowVirtualKeyboardSwitch() {
|
|
mShowVirtualKeyboardSwitch.setChecked(mSettings.isShowImeWithHardKeyboardEnabled());
|
|
}
|
|
|
|
private void toggleKeyboardShortcutsMenu() {
|
|
getActivity().requestShowKeyboardShortcuts();
|
|
}
|
|
|
|
private final OnPreferenceChangeListener mShowVirtualKeyboardSwitchPreferenceChangeListener =
|
|
new OnPreferenceChangeListener() {
|
|
@Override
|
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
mSettings.setShowImeWithHardKeyboard((Boolean) newValue);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
private final ContentObserver mContentObserver = new ContentObserver(new Handler(true)) {
|
|
@Override
|
|
public void onChange(boolean selfChange) {
|
|
updateShowVirtualKeyboardSwitch();
|
|
}
|
|
};
|
|
|
|
private static final class Callbacks implements LoaderManager.LoaderCallbacks<List<Keyboards>> {
|
|
@NonNull
|
|
final Context mContext;
|
|
@NonNull
|
|
final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
|
|
@NonNull
|
|
final List<HardKeyboardDeviceInfo> mHardKeyboards;
|
|
public Callbacks(
|
|
@NonNull Context context,
|
|
@NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
|
|
@NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
|
|
mContext = context;
|
|
mPhysicalKeyboardFragment = physicalKeyboardFragment;
|
|
mHardKeyboards = hardKeyboards;
|
|
}
|
|
|
|
@Override
|
|
public Loader<List<Keyboards>> onCreateLoader(int id, Bundle args) {
|
|
return new KeyboardLayoutLoader(mContext, mHardKeyboards);
|
|
}
|
|
|
|
@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>> {
|
|
@NonNull
|
|
private final List<HardKeyboardDeviceInfo> mHardKeyboards;
|
|
|
|
public KeyboardLayoutLoader(
|
|
@NonNull Context context,
|
|
@NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
|
|
super(context);
|
|
mHardKeyboards = Preconditions.checkNotNull(hardKeyboards);
|
|
}
|
|
|
|
private Keyboards loadInBackground(HardKeyboardDeviceInfo deviceInfo) {
|
|
final ArrayList<Keyboards.KeyboardInfo> keyboardInfoList = new ArrayList<>();
|
|
final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
|
|
final InputManager im = getContext().getSystemService(InputManager.class);
|
|
if (imm != null && im != null) {
|
|
for (InputMethodInfo imi : imm.getEnabledInputMethodList()) {
|
|
final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(
|
|
imi, true /* allowsImplicitlySelectedSubtypes */);
|
|
if (subtypes.isEmpty()) {
|
|
// Here we use null to indicate that this IME has no subtype.
|
|
final InputMethodSubtype nullSubtype = null;
|
|
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);
|
|
}
|
|
|
|
@Override
|
|
public List<Keyboards> loadInBackground() {
|
|
List<Keyboards> keyboardsList = new ArrayList<>(mHardKeyboards.size());
|
|
for (HardKeyboardDeviceInfo deviceInfo : mHardKeyboards) {
|
|
keyboardsList.add(loadInBackground(deviceInfo));
|
|
}
|
|
return keyboardsList;
|
|
}
|
|
|
|
@Override
|
|
protected void onStartLoading() {
|
|
super.onStartLoading();
|
|
forceLoad();
|
|
}
|
|
|
|
@Override
|
|
protected void onStopLoading() {
|
|
super.onStopLoading();
|
|
cancelLoad();
|
|
}
|
|
}
|
|
|
|
public static final class HardKeyboardDeviceInfo {
|
|
@NonNull
|
|
public final String mDeviceName;
|
|
@NonNull
|
|
public final InputDeviceIdentifier mDeviceIdentifier;
|
|
|
|
public HardKeyboardDeviceInfo(
|
|
@Nullable final String deviceName,
|
|
@NonNull final InputDeviceIdentifier deviceIdentifier) {
|
|
mDeviceName = deviceName != null ? deviceName : "";
|
|
mDeviceIdentifier = deviceIdentifier;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (o == this) return true;
|
|
if (o == null) return false;
|
|
|
|
if (!(o instanceof HardKeyboardDeviceInfo)) return false;
|
|
|
|
final HardKeyboardDeviceInfo that = (HardKeyboardDeviceInfo) o;
|
|
if (!TextUtils.equals(mDeviceName, that.mDeviceName)) {
|
|
return false;
|
|
}
|
|
if (mDeviceIdentifier.getVendorId() != that.mDeviceIdentifier.getVendorId()) {
|
|
return false;
|
|
}
|
|
if (mDeviceIdentifier.getProductId() != that.mDeviceIdentifier.getProductId()) {
|
|
return false;
|
|
}
|
|
if (!TextUtils.equals(mDeviceIdentifier.getDescriptor(),
|
|
that.mDeviceIdentifier.getDescriptor())) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
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 List<InputDevice> getPhysicalFullKeyboards() {
|
|
List<InputDevice> keyboards = null;
|
|
for (final int deviceId : InputDevice.getDeviceIds()) {
|
|
final InputDevice device = InputDevice.getDevice(deviceId);
|
|
if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
|
|
if (keyboards == null) keyboards = new ArrayList<>();
|
|
keyboards.add(device);
|
|
}
|
|
}
|
|
return (keyboards == null) ? Collections.emptyList() : keyboards;
|
|
}
|
|
|
|
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
|
new BaseSearchIndexProvider() {
|
|
@Override
|
|
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
|
|
final InputManager inputManager = (InputManager) context.getSystemService(
|
|
Context.INPUT_SERVICE);
|
|
final String screenTitle = context.getString(R.string.physical_keyboard_title);
|
|
final List<SearchIndexableRaw> indexes = new ArrayList<>();
|
|
for (final InputDevice device : getPhysicalFullKeyboards()) {
|
|
final String keyboardLayoutDescriptor = inputManager
|
|
.getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
|
|
final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
|
|
? inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
|
|
final String summary = (keyboardLayout != null)
|
|
? keyboardLayout.toString()
|
|
: context.getString(R.string.keyboard_layout_default_label);
|
|
final SearchIndexableRaw index = new SearchIndexableRaw(context);
|
|
index.key = device.getName();
|
|
index.title = device.getName();
|
|
index.summaryOn = summary;
|
|
index.summaryOff = summary;
|
|
index.screenTitle = screenTitle;
|
|
indexes.add(index);
|
|
}
|
|
return indexes;
|
|
}
|
|
};
|
|
}
|