Implement new keyboard settings UI.

Add enabled input method locales page
Add keyboard layout picker page
Add keyboard settings entry in BT device detail

Bug: 242680718
Test: local test
Change-Id: I07e068ecde553d394697b25cb573f806229f6f52
This commit is contained in:
danielwbhuang
2022-10-04 20:14:59 +08:00
parent d2378be135
commit 1639782df6
22 changed files with 898 additions and 20 deletions

View File

@@ -154,6 +154,7 @@ public class KeyboardLayoutPickerController extends BasePreferenceController imp
final SwitchPreference pref = new SwitchPreference(mScreen.getContext());
pref.setTitle(layout.getLabel());
pref.setSummary(layout.getCollection());
// TODO: Waiting for new API to use a prefix with special number to setKey
pref.setKey(layout.getDescriptor());
mScreen.addPreference(pref);
mPreferenceMap.put(pref, layout);

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2022 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.content.Context;
import android.view.View;
import android.widget.ImageView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
public class KeyboardLayoutPreference extends Preference {
private ImageView mCheckIcon;
private boolean mIsMark;
public KeyboardLayoutPreference(Context context, String layoutName, boolean defaultMark) {
super(context);
setWidgetLayoutResource(R.layout.preference_check_icon);
setTitle(layoutName);
mIsMark = defaultMark;
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mCheckIcon = (ImageView) holder.findViewById(R.id.keyboard_check_icon);
setCheckMark(mIsMark);
}
public void setCheckMark(boolean isMark) {
if (mCheckIcon != null) {
mCheckIcon.setVisibility(isMark ? View.VISIBLE : View.INVISIBLE);
mIsMark = isMark;
}
}
}

View File

@@ -78,9 +78,9 @@ public class KeyboardPreferenceController extends BasePreferenceController
@Override
public int getAvailabilityStatus() {
boolean isFeatureOn = FeatureFlagUtils
.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
return isFeatureOn ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)
? AVAILABLE
: CONDITIONALLY_UNAVAILABLE;
}
private void updateSummary() {

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 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.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.util.FeatureFlagUtils;
import androidx.annotation.NonNull;
import androidx.preference.Preference;
import com.android.settings.Settings.PhysicalKeyboardActivity;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import java.util.List;
public class KeyboardSettingsPreferenceController extends BasePreferenceController {
private Context mContext;
private CachedBluetoothDevice mCachedDevice;
private Activity mActivity;
public KeyboardSettingsPreferenceController(Context context, String key) {
super(context, key);
mContext = context;
}
public void init(@NonNull CachedBluetoothDevice cachedDevice, @NonNull Activity activity) {
mCachedDevice = cachedDevice;
mActivity = activity;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
intent.setClass(mContext, PhysicalKeyboardActivity.class);
intent.putExtra(PhysicalKeyboardFragment.EXTRA_BT_ADDRESS, mCachedDevice.getAddress());
mActivity.startActivityForResult(intent, 0);
return true;
}
@Override
public int getAvailabilityStatus() {
final List<HardKeyboardDeviceInfo> newHardKeyboards =
PhysicalKeyboardFragment.getHardKeyboards(mContext);
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)
&& !newHardKeyboards.isEmpty()) {
for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
if (mCachedDevice.getAddress() != null
&& hardKeyboardDeviceInfo.mBluetoothAddress != null
&& mCachedDevice.getAddress().equals(
hardKeyboardDeviceInfo.mBluetoothAddress)) {
return AVAILABLE;
}
}
}
return CONDITIONALLY_UNAVAILABLE;
}
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright (C) 2022 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.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.view.InputDevice;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
implements InputManager.InputDeviceListener {
private static final String TAG = "NewKeyboardLayoutEnabledLocalesFragment";
private static final String PREF_KEY_ENABLED_LOCALES = "enabled_locales_keyboard_layout";
static final String EXTRA_KEYBOARD_DEVICE_NAME = "extra_keyboard_device_name";
private InputManager mIm;
private InputDeviceIdentifier mInputDeviceIdentifier;
private int mInputDeviceId;
private Context mContext;
@Override
public void onActivityCreated(final Bundle icicle) {
super.onActivityCreated(icicle);
Bundle arguments = getArguments();
final String title = arguments.getString(EXTRA_KEYBOARD_DEVICE_NAME);
mInputDeviceIdentifier = arguments.getParcelable(
KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
getActivity().setTitle(title);
final PreferenceCategory category = findPreference(PREF_KEY_ENABLED_LOCALES);
// TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
// For example: InputMethodManager.getEnabledInputMethodLocales()
// InputManager.getKeyboardLayoutForLocale()
// Hardcode the default value for demo purpose
String[] keyboardLanguages = {"English (US)", "German (Germany)", "Spanish (Spain)"};
String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
for (int i = 0; i < keyboardLanguages.length; i++) {
final Preference pref = new Preference(mContext);
String key = "keyboard_language_label_" + String.valueOf(i);
String keyboardLanguageTitle = keyboardLanguages[i];
String keyboardLanguageSummary = keyboardLayouts[i];
// TODO: Waiting for new API to use a prefix with special number to setKey
pref.setKey(key);
pref.setTitle(keyboardLanguageTitle);
pref.setSummary(keyboardLanguageSummary);
pref.setOnPreferenceClickListener(
preference -> {
showKeyboardLayoutPicker(
keyboardLanguageTitle,
keyboardLanguageSummary,
mInputDeviceIdentifier);
return true;
});
category.addPreference(pref);
}
}
@Override
public void onInputDeviceAdded(int deviceId) {
// Do nothing.
}
@Override
public void onInputDeviceRemoved(int deviceId) {
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
getActivity().finish();
}
}
@Override
public void onInputDeviceChanged(int deviceId) {
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
// TODO(b/252816846): Need APIs to update the available keyboards.
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getContext();
mIm = mContext.getSystemService(InputManager.class);
mInputDeviceId = -1;
}
@Override
public void onStart() {
super.onStart();
mIm.registerInputDeviceListener(this, null);
final InputDevice inputDevice =
mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
if (inputDevice == null) {
getActivity().finish();
return;
}
mInputDeviceId = inputDevice.getId();
}
@Override
public void onStop() {
super.onStop();
mIm.unregisterInputDeviceListener(this);
mInputDeviceId = -1;
}
@Override
public void onResume() {
super.onResume();
// TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_KEYBOARDS_ENABLED_LOCALES;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.keyboard_settings_enabled_locales_list;
}
private void showKeyboardLayoutPicker(String language, String layout,
InputDeviceIdentifier inputDeviceIdentifier) {
Bundle arguments = new Bundle();
arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
inputDeviceIdentifier);
arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_TITLE, language);
arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_KEYBOARD_LAYOUT, layout);
new SubSettingLauncher(mContext)
.setSourceMetricsCategory(getMetricsCategory())
.setDestination(NewKeyboardLayoutPickerFragment.class.getName())
.setArguments(arguments)
.launch();
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2022 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.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
public class NewKeyboardLayoutPickerContent extends DashboardFragment {
private static final String TAG = "KeyboardLayoutPicker";
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
/**
* Intent extra: The input device descriptor of the keyboard whose keyboard
* layout is to be changed.
*/
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
@Override
public void onAttach(Context context) {
super.onAttach(context);
Bundle arguments = getArguments();
final String title = arguments.getString(EXTRA_TITLE);
final String layout = arguments.getString(EXTRA_KEYBOARD_LAYOUT);
final InputDeviceIdentifier inputDeviceIdentifier =
arguments.getParcelable(EXTRA_INPUT_DEVICE_IDENTIFIER);
if (inputDeviceIdentifier == null) {
getActivity().finish();
}
getActivity().setTitle(title);
use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/,
inputDeviceIdentifier, layout);
}
@Override
public int getMetricsCategory() {
// TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_CONTENT
return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER;
}
@Override
protected String getLogTag() {
return TAG;
}
protected int getPreferenceScreenResId() {
return R.xml.new_keyboard_layout_picker_fragment;
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2022 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.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
import android.view.InputDevice;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class NewKeyboardLayoutPickerController extends BasePreferenceController implements
InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop {
private final InputManager mIm;
private final Map<KeyboardLayoutPreference, KeyboardLayout> mPreferenceMap;
private Fragment mParent;
private int mInputDeviceId;
private InputDeviceIdentifier mInputDeviceIdentifier;
private KeyboardLayout[] mKeyboardLayouts;
private PreferenceScreen mScreen;
private String mPreviousSelection;
private String mLayout;
public NewKeyboardLayoutPickerController(Context context, String key) {
super(context, key);
mIm = context.getSystemService(InputManager.class);
mInputDeviceId = -1;
mPreferenceMap = new HashMap<>();
}
public void initialize(Fragment parent, InputDeviceIdentifier inputDeviceIdentifier,
String layout) {
mLayout = layout;
mParent = parent;
mInputDeviceIdentifier = inputDeviceIdentifier;
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
Arrays.sort(mKeyboardLayouts);
}
@Override
public void onStart() {
mIm.registerInputDeviceListener(this, null);
final InputDevice inputDevice =
mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
if (inputDevice == null) {
mParent.getActivity().finish();
return;
}
mInputDeviceId = inputDevice.getId();
}
@Override
public void onStop() {
mIm.unregisterInputDeviceListener(this);
mInputDeviceId = -1;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
createPreferenceHierarchy();
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!(preference instanceof KeyboardLayoutPreference)) {
return false;
}
final KeyboardLayoutPreference pref = (KeyboardLayoutPreference) preference;
// TODO(b/259530132): Need APIs to update the available keyboards for input device.
// For example:
// inputManager.setCurrentKeyboardLayoutForInputDevice(
// InputDevice..., Userid..., ImeSubType ..., String keyboardLayoutDescriptor)
if (mPreviousSelection != null && !mPreviousSelection.equals(preference.getKey())) {
KeyboardLayoutPreference preSelectedPref = mScreen.findPreference(mPreviousSelection);
pref.setCheckMark(true);
preSelectedPref.setCheckMark(false);
}
mPreviousSelection = preference.getKey();
return true;
}
@Override
public void onInputDeviceAdded(int deviceId) {
// Do nothing.
}
@Override
public void onInputDeviceRemoved(int deviceId) {
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
mParent.getActivity().finish();
}
}
@Override
public void onInputDeviceChanged(int deviceId) {
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
updateCheckedState();
}
}
private void updateCheckedState() {
// TODO(b/259530132): Need API to update the keyboard language layout list.
}
private void createPreferenceHierarchy() {
for (KeyboardLayout layout : mKeyboardLayouts) {
final KeyboardLayoutPreference pref;
if (mLayout.equals(layout.getLabel())) {
pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), true);
mPreviousSelection = layout.getLabel();
} else {
pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), false);
}
// TODO: Waiting for new API to use a prefix with special number to setKey
pref.setKey(layout.getLabel());
mScreen.addPreference(pref);
mPreferenceMap.put(pref, layout);
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2022 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.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
public class NewKeyboardLayoutPickerFragment extends Fragment {
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
/**
* Intent extra: The input device descriptor of the keyboard whose keyboard
* layout is to be changed.
*/
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
private ViewGroup mFragmentView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mFragmentView = (ViewGroup) inflater.inflate(
R.layout.keyboard_layout_picker, container, false);
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.keyboard_layout_title, new NewKeyboardLayoutPickerTitle())
.commit();
NewKeyboardLayoutPickerContent fragment = new NewKeyboardLayoutPickerContent();
fragment.setArguments(getArguments());
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.keyboard_layouts, fragment)
.commit();
return mFragmentView;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2022 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.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
public class NewKeyboardLayoutPickerTitle extends SettingsPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.new_keyboard_layout_picker_title);
}
@Override
public int getMetricsCategory() {
// TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_TITLE
return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.new_keyboard_layout_picker_title) {
@Override
protected boolean isPageSearchEnabled(Context context) {
return false;
}
};
}

View File

@@ -33,6 +33,7 @@ import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.view.InputDevice;
import androidx.preference.Preference;
@@ -45,6 +46,7 @@ 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.core.SubSettingLauncher;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.utils.ThreadUtils;
@@ -52,7 +54,9 @@ import com.android.settingslib.utils.ThreadUtils;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@SearchIndexable
@@ -60,7 +64,7 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
implements InputManager.InputDeviceListener,
KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener {
private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
private static final String KEYBOARD_OPTIONS_CATEGORY = "keyboard_options_category";
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
@@ -74,17 +78,25 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
private SwitchPreference mShowVirtualKeyboardSwitch;
private Intent mIntentWaitingForResult;
private boolean mIsNewKeyboardSettings;
static final String EXTRA_BT_ADDRESS = "extra_bt_address";
private String mBluetoothAddress;
@Override
public void onCreatePreferences(Bundle bundle, String s) {
Activity activity = Preconditions.checkNotNull(getActivity());
mBluetoothAddress = activity.getIntent().getStringExtra(EXTRA_BT_ADDRESS);
addPreferencesFromResource(R.xml.physical_keyboard_settings);
mIm = Preconditions.checkNotNull(activity.getSystemService(InputManager.class));
mKeyboardAssistanceCategory = Preconditions.checkNotNull(
(PreferenceCategory) findPreference(KEYBOARD_ASSISTANCE_CATEGORY));
(PreferenceCategory) findPreference(KEYBOARD_OPTIONS_CATEGORY));
mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
(SwitchPreference) mKeyboardAssistanceCategory.findPreference(
SHOW_VIRTUAL_KEYBOARD_SWITCH));
mIsNewKeyboardSettings = FeatureFlagUtils.isEnabled(
getContext(), FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
// TODO(b/247080921): Support shortcuts list & modifier keys
}
@Override
@@ -164,17 +176,55 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
preferenceScreen.addPreference(category);
for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
// if user go into this page from Connected devices entry, we should distinguish the
// user-selected keyboard from all enabled keyboards.
if (mBluetoothAddress != null
&& !mBluetoothAddress.equals(hardKeyboardDeviceInfo.mBluetoothAddress)) {
continue;
}
// 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;
});
if (mIsNewKeyboardSettings) {
// TODO(b/252816846): Need InputMethodManager to provide the enabled locales.
// Hardcode Languages for demo until inputMethodManager provides the latest API.
// For example: InputMethodManager.getEnabledInputMethodLocales();
String[] keyboardLanguages =
{"English (US)", "German (Germany)", "Spanish (Spain)"};
String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
Map<String, String> keyboardMap = new HashMap<>();
for (int i = 0; i < keyboardLanguages.length; i++) {
keyboardMap.put(keyboardLanguages[i], keyboardLayouts[i]);
}
if (!keyboardMap.isEmpty()) {
String summary = keyboardMap.get(keyboardLanguages[0]);
StringBuilder result = new StringBuilder(summary);
for (int i = 1; i < keyboardLanguages.length; i++) {
result.append(", ").append(keyboardMap.get(keyboardLanguages[i]));
}
pref.setSummary(result.toString());
} else {
pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
}
pref.setOnPreferenceClickListener(
preference -> {
showEnabledLocalesKeyboardLayoutList(
hardKeyboardDeviceInfo.mDeviceName,
hardKeyboardDeviceInfo.mDeviceIdentifier);
return true;
});
} else {
pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
pref.setOnPreferenceClickListener(
preference -> {
showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
return true;
});
}
category.addPreference(pref);
}
mKeyboardAssistanceCategory.setOrder(1);
preferenceScreen.addPreference(mKeyboardAssistanceCategory);
updateShowVirtualKeyboardSwitch();
@@ -187,6 +237,21 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
fragment.show(getActivity().getSupportFragmentManager(), "keyboardLayout");
}
private void showEnabledLocalesKeyboardLayoutList(String keyboardName,
InputDeviceIdentifier inputDeviceIdentifier) {
// TODO(b/252816846: Need to get enabled locales.
Bundle arguments = new Bundle();
arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
inputDeviceIdentifier);
arguments.putString(NewKeyboardLayoutEnabledLocalesFragment.EXTRA_KEYBOARD_DEVICE_NAME,
keyboardName);
new SubSettingLauncher(getContext())
.setSourceMetricsCategory(getMetricsCategory())
.setDestination(NewKeyboardLayoutEnabledLocalesFragment.class.getName())
.setArguments(arguments)
.launch();
}
private void registerShowVirtualKeyboardSettingsObserver() {
unregisterShowVirtualKeyboardSettingsObserver();
getActivity().getContentResolver().registerContentObserver(
@@ -277,7 +342,10 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
continue;
}
keyboards.add(new HardKeyboardDeviceInfo(
device.getName(), device.getIdentifier(), getLayoutLabel(device, context, im)));
device.getName(),
device.getIdentifier(),
getLayoutLabel(device, context, im),
device.getBluetoothAddress()));
}
// We intentionally don't reuse Comparator because Collator may not be thread-safe.
@@ -304,14 +372,18 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
public final InputDeviceIdentifier mDeviceIdentifier;
@NonNull
public final String mLayoutLabel;
@Nullable
public final String mBluetoothAddress;
public HardKeyboardDeviceInfo(
@Nullable String deviceName,
@NonNull InputDeviceIdentifier deviceIdentifier,
@NonNull String layoutLabel) {
@NonNull String layoutLabel,
@Nullable String bluetoothAddress) {
mDeviceName = TextUtils.emptyIfNull(deviceName);
mDeviceIdentifier = deviceIdentifier;
mLayoutLabel = layoutLabel;
mBluetoothAddress = bluetoothAddress;
}
@Override
@@ -331,6 +403,9 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
if (!TextUtils.equals(mLayoutLabel, that.mLayoutLabel)) {
return false;
}
if (!TextUtils.equals(mBluetoothAddress, that.mBluetoothAddress)) {
return false;
}
return true;
}