Open the settings page for a specific physical keyboard

1. Check open from a notification
2. Check open from Bluetooth entry
3. If the inputDeviceIdentifier is not null, open the next page
   directly.
4. Add extra to record the class of sender for the future metrics.

Demo: http://screencast/cast/NDU4MTYxOTIzMTg4MzI2NHxiYTQ0ODE5Ny02YQ

Bug: 269212353
Test: manual, atest
[Pass] atest KeyboardSettingsPreferenceControllerTest
[Pass] atest PhysicalKeyboardPreferenceControllerTest

Change-Id: Ie874003260896bbb949806623913e70486e4731d
This commit is contained in:
danielwbhuang
2023-03-24 19:11:53 +08:00
committed by Daniel Huang
parent 9a40a296cc
commit cc749159df
9 changed files with 99 additions and 42 deletions

View File

@@ -30,8 +30,7 @@
<Preference
android:key="physical_keyboard_pref"
android:title="@string/physical_keyboard_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.inputmethod.PhysicalKeyboardFragment"/>
android:summary="@string/summary_placeholder"/>
</PreferenceCategory>
<PreferenceCategory

View File

@@ -175,7 +175,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
}
use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice);
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager);
use(KeyboardSettingsPreferenceController.class).init(mCachedDevice, getActivity());
use(KeyboardSettingsPreferenceController.class).init(mCachedDevice);
final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
context).getBluetoothFeatureProvider();

View File

@@ -16,16 +16,15 @@
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.annotation.VisibleForTesting;
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;
@@ -34,18 +33,14 @@ 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) {
public void init(@NonNull CachedBluetoothDevice cachedDevice) {
mCachedDevice = cachedDevice;
mActivity = activity;
}
@Override
@@ -53,18 +48,26 @@ public class KeyboardSettingsPreferenceController extends BasePreferenceControll
if (!getPreferenceKey().equals(preference.getKey())) {
return false;
}
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);
List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboardList();
for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
if (mCachedDevice.getAddress().equals(hardKeyboardDeviceInfo.mBluetoothAddress)) {
Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
intent.putExtra(
NewKeyboardSettingsUtils.EXTRA_INTENT_FROM,
"com.android.settings.inputmethod.KeyboardSettingsPreferenceController");
intent.putExtra(
Settings.EXTRA_INPUT_DEVICE_IDENTIFIER,
hardKeyboardDeviceInfo.mDeviceIdentifier);
mContext.startActivity(intent);
break;
}
}
return true;
}
@Override
public int getAvailabilityStatus() {
final List<HardKeyboardDeviceInfo> newHardKeyboards =
PhysicalKeyboardFragment.getHardKeyboards(mContext);
List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboardList();
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)
&& !newHardKeyboards.isEmpty()) {
for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
@@ -78,4 +81,9 @@ public class KeyboardSettingsPreferenceController extends BasePreferenceControll
}
return CONDITIONALLY_UNAVAILABLE;
}
@VisibleForTesting
List<HardKeyboardDeviceInfo> getHardKeyboardList() {
return PhysicalKeyboardFragment.getHardKeyboards(mContext);
}
}

View File

@@ -23,6 +23,7 @@ import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -59,10 +60,19 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
public void onActivityCreated(final Bundle icicle) {
super.onActivityCreated(icicle);
Bundle arguments = getArguments();
final String title =
arguments.getString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_DEVICE_NAME);
mInputDeviceIdentifier =
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER);
if (mInputDeviceIdentifier == null) {
Log.e(TAG, "The inputDeviceIdentifier should not be null");
return;
}
InputDevice inputDevice =
NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier);
if (inputDevice == null) {
Log.e(TAG, "inputDevice is null");
return;
}
final String title = inputDevice.getName();
getActivity().setTitle(title);
updateCheckedState();
}

View File

@@ -47,6 +47,7 @@ public class NewKeyboardLayoutPickerContent extends DashboardFragment {
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE);
if (identifier == null
|| NewKeyboardSettingsUtils.getInputDevice(inputManager, identifier) == null) {
getActivity().finish();
return;
}
getActivity().setTitle(title);

View File

@@ -32,7 +32,12 @@ import java.util.List;
*/
public class NewKeyboardSettingsUtils {
static final String EXTRA_KEYBOARD_DEVICE_NAME = "extra_keyboard_device_name";
/**
* Record the class name of the intent sender for metrics.
*/
public static final String EXTRA_INTENT_FROM =
"com.android.settings.inputmethod.EXTRA_INTENT_FROM";
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
static final String EXTRA_USER_ID = "user_id";

View File

@@ -87,7 +87,6 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
@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));
mImm = Preconditions.checkNotNull(activity.getSystemService(InputMethodManager.class));
@@ -104,6 +103,19 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
if (!isModifierKeySettingsEnabled) {
mKeyboardAssistanceCategory.removePreference(findPreference(MODIFIER_KEYS_SETTINGS));
}
InputDeviceIdentifier inputDeviceIdentifier = activity.getIntent().getParcelableExtra(
KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
// TODO (b/271391879): The EXTRA_INTENT_FROM is used for the future metrics.
if (inputDeviceIdentifier != null) {
Bundle arguments = new Bundle();
arguments.putParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER,
inputDeviceIdentifier);
new SubSettingLauncher(getContext())
.setSourceMetricsCategory(getMetricsCategory())
.setDestination(NewKeyboardLayoutEnabledLocalesFragment.class.getName())
.setArguments(arguments)
.launch();
}
}
@Override
@@ -187,14 +199,6 @@ 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);
@@ -247,7 +251,6 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
Bundle arguments = new Bundle();
arguments.putParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER,
inputDeviceIdentifier);
arguments.putString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_DEVICE_NAME, keyboardName);
new SubSettingLauncher(getContext())
.setSourceMetricsCategory(getMetricsCategory())
.setDestination(NewKeyboardLayoutEnabledLocalesFragment.class.getName())

View File

@@ -17,8 +17,10 @@
package com.android.settings.inputmethod;
import android.content.Context;
import android.content.Intent;
import android.hardware.input.InputManager;
import android.icu.text.ListFormatter;
import android.provider.Settings;
import androidx.preference.Preference;
@@ -58,6 +60,19 @@ public class PhysicalKeyboardPreferenceController extends AbstractPreferenceCont
&& mContext.getResources().getBoolean(R.bool.config_show_physical_keyboard_pref);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!getPreferenceKey().equals(preference.getKey())) {
return false;
}
Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
intent.putExtra(
NewKeyboardSettingsUtils.EXTRA_INTENT_FROM,
"com.android.settings.inputmethod.PhysicalKeyboardPreferenceController");
mContext.startActivity(intent);
return true;
}
@Override
public void updateState(Preference preference) {
mPreference = preference;

View File

@@ -18,18 +18,21 @@ package com.android.settings.inputmethod;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.input.InputDeviceIdentifier;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
@@ -37,12 +40,14 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link KeyboardSettingsPreferenceController} */
@RunWith(RobolectricTestRunner.class)
public class KeyboardSettingsPreferenceControllerTest {
@@ -52,32 +57,43 @@ public class KeyboardSettingsPreferenceControllerTest {
private static final String PREFERENCE_KEY = "keyboard_settings";
@Mock
private Activity mActivity;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Captor
private ArgumentCaptor<Intent> mIntentArgumentCaptor;
@Mock
private InputDeviceIdentifier mInputDeviceIdentifier;
private Context mContext;
private KeyboardSettingsPreferenceController mController;
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
mController = new KeyboardSettingsPreferenceController(mContext, PREFERENCE_KEY);
mController.init(mCachedBluetoothDevice, mActivity);
doNothing().when(mContext).startActivity(any());
mController = spy(new KeyboardSettingsPreferenceController(mContext, PREFERENCE_KEY));
mController.init(mCachedBluetoothDevice);
}
@Test
public void handlePreferenceTreeClick_expected() {
Preference mKeyboardPreference = new Preference(mContext);
mKeyboardPreference.setKey(PREFERENCE_KEY);
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
String address = "BT_ADDRESS";
HardKeyboardDeviceInfo deviceInfo =
new HardKeyboardDeviceInfo(
"TEST_DEVICE",
mInputDeviceIdentifier,
"TEST_DEVICE_LABEL",
address);
List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
keyboards.add(deviceInfo);
when(mController.getHardKeyboardList()).thenReturn(keyboards);
when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
mController.handlePreferenceTreeClick(mKeyboardPreference);
verify(mActivity).startActivityForResult(mIntentArgumentCaptor.capture(), eq(0));
Intent expectedIntent = mIntentArgumentCaptor.getValue();
assertThat(expectedIntent.getAction()).isEqualTo(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
verify(mContext).startActivity(captor.capture());
assertThat(captor.getValue().getAction()).isEqualTo(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
}
@Test