diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java index f91c9d81cad..94f0757c961 100644 --- a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java +++ b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java @@ -308,6 +308,12 @@ public class KeyboardLayoutDialogFragment extends InstrumentedDialogFragment public Keyboards loadInBackground() { Keyboards keyboards = new Keyboards(); InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE); + if (mInputDeviceIdentifier == null || NewKeyboardSettingsUtils.getInputDevice( + im, mInputDeviceIdentifier) == null) { + keyboards.keyboardLayouts.add(null); // default layout + keyboards.current = 0; + return keyboards; + } String[] keyboardLayoutDescriptors = im.getEnabledKeyboardLayoutsForInputDevice( mInputDeviceIdentifier); for (String keyboardLayoutDescriptor : keyboardLayoutDescriptors) { diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java index c6a0d755151..10cd4a27931 100644 --- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java +++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java @@ -21,7 +21,6 @@ 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; @@ -37,7 +36,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; - public class KeyboardLayoutPickerController extends BasePreferenceController implements InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop { @@ -68,15 +66,12 @@ public class KeyboardLayoutPickerController extends BasePreferenceController imp @Override public void onStart() { mIm.registerInputDeviceListener(this, null); - - final InputDevice inputDevice = - mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor()); - if (inputDevice == null) { - mParent.getActivity().finish(); + if (mInputDeviceIdentifier == null + || NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) { return; } - mInputDeviceId = inputDevice.getId(); - + mInputDeviceId = + NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier).getId(); updateCheckedState(); } @@ -150,6 +145,9 @@ public class KeyboardLayoutPickerController extends BasePreferenceController imp } private void createPreferenceHierarchy() { + if (mKeyboardLayouts == null) { + return; + } for (KeyboardLayout layout : mKeyboardLayouts) { final SwitchPreference pref = new SwitchPreference(mScreen.getContext()); pref.setTitle(layout.getLabel()); diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java index a13ebc00ffd..8abde7e35b4 100644 --- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java +++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java @@ -19,11 +19,11 @@ 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 com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; - public class KeyboardLayoutPickerFragment extends DashboardFragment { private static final String TAG = "KeyboardLayoutPicker"; @@ -45,10 +45,10 @@ public class KeyboardLayoutPickerFragment extends DashboardFragment { final InputDeviceIdentifier inputDeviceIdentifier = getActivity().getIntent(). getParcelableExtra(EXTRA_INPUT_DEVICE_IDENTIFIER); - if (inputDeviceIdentifier == null) { - getActivity().finish(); + final InputManager im = context.getSystemService(InputManager.class); + if (NewKeyboardSettingsUtils.getInputDevice(im, inputDeviceIdentifier) == null) { + return; } - use(KeyboardLayoutPickerController.class).initialize(this /*parent*/, inputDeviceIdentifier); } diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java index 9311c97e104..2db338254e4 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java @@ -68,6 +68,9 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment } private void updateCheckedState() { + if (NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) { + return; + } PreferenceScreen preferenceScreen = getPreferenceScreen(); preferenceScreen.removeAll(); List infoList = mImm.getEnabledInputMethodListAsUser(mUserId); @@ -174,8 +177,8 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment public void onStart() { super.onStart(); mIm.registerInputDeviceListener(this, null); - final InputDevice inputDevice = - mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor()); + InputDevice inputDevice = + NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier); if (inputDevice == null) { getActivity().finish(); return; diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java index bb452f7a2bd..605095f103b 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java @@ -19,6 +19,7 @@ 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.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; @@ -33,25 +34,24 @@ public class NewKeyboardLayoutPickerContent extends DashboardFragment { @Override public void onAttach(Context context) { super.onAttach(context); - + InputManager inputManager = getContext().getSystemService(InputManager.class); Bundle arguments = getArguments(); final String title = arguments.getString(NewKeyboardSettingsUtils.EXTRA_TITLE); final String layout = arguments.getString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_LAYOUT); final int userId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID); - final InputDeviceIdentifier inputDeviceIdentifier = + final InputDeviceIdentifier identifier = arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER); final InputMethodInfo inputMethodInfo = arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO); final InputMethodSubtype inputMethodSubtype = arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE); - - - if (inputDeviceIdentifier == null) { - getActivity().finish(); + if (identifier == null + || NewKeyboardSettingsUtils.getInputDevice(inputManager, identifier) == null) { + return; } getActivity().setTitle(title); use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/, userId, - inputDeviceIdentifier, inputMethodInfo, inputMethodSubtype, layout); + identifier, inputMethodInfo, inputMethodSubtype, layout); } @Override diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java index eb0a7aa05ff..893ad4cea01 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java @@ -20,7 +20,6 @@ import android.content.Context; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.hardware.input.KeyboardLayout; -import android.view.InputDevice; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; @@ -75,13 +74,12 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController @Override public void onStart() { mIm.registerInputDeviceListener(this, null); - final InputDevice inputDevice = - mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor()); - if (inputDevice == null) { - mParent.getActivity().finish(); + if (mInputDeviceIdentifier == null + || NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) { return; } - mInputDeviceId = inputDevice.getId(); + mInputDeviceId = + NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier).getId(); } @Override @@ -138,6 +136,9 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController } private void createPreferenceHierarchy() { + if (mKeyboardLayouts == null) { + return; + } for (KeyboardLayout layout : mKeyboardLayouts) { final KeyboardLayoutPreference pref; if (mLayout.equals(layout.getLabel())) { diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java index 169b84b5122..88cacd2b046 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java +++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java @@ -27,13 +27,11 @@ import com.android.settings.R; public class NewKeyboardLayoutPickerFragment extends Fragment { - private ViewGroup mFragmentView; - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - mFragmentView = (ViewGroup) inflater.inflate( + ViewGroup fragmentView = (ViewGroup) inflater.inflate( R.layout.keyboard_layout_picker, container, false); getActivity().getSupportFragmentManager() .beginTransaction() @@ -47,6 +45,6 @@ public class NewKeyboardLayoutPickerFragment extends Fragment { .replace(R.id.keyboard_layouts, fragment) .commit(); - return mFragmentView; + return fragmentView; } } diff --git a/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java b/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java index 0bd938e2e44..dda5500bc98 100644 --- a/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java +++ b/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java @@ -17,6 +17,8 @@ package com.android.settings.inputmethod; import android.content.Context; +import android.hardware.input.InputDeviceIdentifier; +import android.hardware.input.InputManager; import android.view.InputDevice; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -102,4 +104,8 @@ public class NewKeyboardSettingsUtils { return mInputMethodSubtype; } } + + static InputDevice getInputDevice(InputManager im, InputDeviceIdentifier identifier) { + return im.getInputDeviceByDescriptor(identifier.getDescriptor()); + } } diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java index 20a634e023d..e9dba57a90e 100644 --- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java +++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java @@ -160,6 +160,10 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment final Context context = getContext(); ThreadUtils.postOnBackgroundThread(() -> { final List newHardKeyboards = getHardKeyboards(context); + if (newHardKeyboards.isEmpty()) { + getActivity().finish(); + return; + } ThreadUtils.postOnMainThread(() -> updateHardKeyboards(newHardKeyboards)); }); } diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java index 367ea80e07d..3dcae09081c 100644 --- a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java +++ b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java @@ -22,6 +22,7 @@ import android.icu.text.ListFormatter; import androidx.preference.Preference; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo; @@ -34,7 +35,6 @@ import com.android.settingslib.core.lifecycle.events.OnResume; import java.util.ArrayList; import java.util.List; - public class PhysicalKeyboardPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause, InputManager.InputDeviceListener { @@ -54,13 +54,14 @@ public class PhysicalKeyboardPreferenceController extends AbstractPreferenceCont @Override public boolean isAvailable() { - return mContext.getResources().getBoolean(R.bool.config_show_physical_keyboard_pref); + return !getKeyboards().isEmpty() + && mContext.getResources().getBoolean(R.bool.config_show_physical_keyboard_pref); } @Override public void updateState(Preference preference) { mPreference = preference; - updateSummary(); + updateEntry(); } @Override @@ -80,33 +81,42 @@ public class PhysicalKeyboardPreferenceController extends AbstractPreferenceCont @Override public void onInputDeviceAdded(int deviceId) { - updateSummary(); + updateEntry(); } @Override public void onInputDeviceRemoved(int deviceId) { - updateSummary(); + updateEntry(); } @Override public void onInputDeviceChanged(int deviceId) { - updateSummary(); + updateEntry(); } - private void updateSummary() { + private void updateEntry() { if (mPreference == null) { return; } - final List keyboards = - PhysicalKeyboardFragment.getHardKeyboards(mContext); + List keyboards = getKeyboards(); if (keyboards.isEmpty()) { - mPreference.setSummary(R.string.keyboard_disconnected); + mPreference.setVisible(false); return; } - final List summaries = new ArrayList<>(); + updateSummary(keyboards); + } + + private void updateSummary(List keyboards) { + mPreference.setVisible(true); + List summaries = new ArrayList<>(); for (HardKeyboardDeviceInfo info : keyboards) { summaries.add(info.mDeviceName); } mPreference.setSummary(ListFormatter.getInstance().format(summaries)); } + + @VisibleForTesting + List getKeyboards() { + return PhysicalKeyboardFragment.getHardKeyboards(mContext); + } } diff --git a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java index d675e8911e5..df052037507 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java @@ -24,12 +24,13 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.view.InputDevice; import androidx.preference.Preference; -import com.android.settings.R; +import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo; import com.android.settings.testutils.shadow.ShadowInputDevice; import org.junit.After; @@ -42,15 +43,24 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import java.util.ArrayList; +import java.util.List; + @RunWith(RobolectricTestRunner.class) public class PhysicalKeyboardPreferenceControllerTest { + private static final String DEVICE_NAME = "deviceName"; + private static final String LAYOUT_LABEL = "deviceLayutLabel"; + private static final String BLUETOOTHADDRESS = "deviceBluetoothAddress"; + @Mock private Context mContext; @Mock private InputManager mIm; @Mock private Preference mPreference; + @Mock + private InputDeviceIdentifier mIdentifier; private PhysicalKeyboardPreferenceController mController; @@ -69,9 +79,18 @@ public class PhysicalKeyboardPreferenceControllerTest { @Test public void testPhysicalKeyboard_byDefault_shouldBeShown() { final Context context = spy(RuntimeEnvironment.application.getApplicationContext()); - mController = new PhysicalKeyboardPreferenceController(context, null); + List keyboards = new ArrayList<>(); + keyboards.add(new HardKeyboardDeviceInfo( + DEVICE_NAME, + mIdentifier, + LAYOUT_LABEL, + BLUETOOTHADDRESS)); + mController = spy(new PhysicalKeyboardPreferenceController(context, null)); + when(mController.getKeyboards()).thenReturn(keyboards); - assertThat(mController.isAvailable()).isTrue(); + boolean result = mController.isAvailable(); + + assertThat(result).isTrue(); } @Test @@ -85,11 +104,11 @@ public class PhysicalKeyboardPreferenceControllerTest { @Test @Config(shadows = ShadowInputDevice.class) - public void updateState_noKeyboard_setDisconnectedSummary() { + public void updateState_noKeyboard_setPreferenceVisibleFalse() { ShadowInputDevice.sDeviceIds = new int[0]; mController.updateState(mPreference); - verify(mPreference).setSummary(R.string.keyboard_disconnected); + verify(mPreference).setVisible(false); } @Test