From 483b1f98bf37bef93370864e6e70646d91cfc3ee Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Tue, 20 Mar 2018 16:15:44 -0700 Subject: [PATCH] Fix renaming for Bluetooth devices when rotating to landscape The bug here is that when renaming a Bluetooth device (either the local adapter or a paired device), if you click on the text edit field of the alert dialog and then rotate the screen, the text shown in the soft input will disappear. Also it's a usability problem that you even needed to click in the first place. This CL fixes both problems - now the soft input will be shown immediately when the dialog comes up, and the content doesn't disappear on rotation. Change-Id: Id29d11c834bf98c01b5c1208159537a8fd36a64f Fixes: 72551780 Test: make -j RunSettingsRoboTests (cherry picked from commit 5a1587526b9a6ddfdb2bde2f6e24815e9fe5b36a) --- .../BluetoothNameDialogFragment.java | 12 ++- .../LocalDeviceNameDialogFragmentTest.java | 78 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragmentTest.java diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java index 134bb9708bf..85abadeddcc 100644 --- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java @@ -31,6 +31,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; @@ -89,8 +90,15 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment }) .setNegativeButton(android.R.string.cancel, null); mAlertDialog = builder.create(); - mAlertDialog.getWindow().setSoftInputMode( - WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + mAlertDialog.setOnShowListener(d -> { + if (mDeviceNameView != null && mDeviceNameView.requestFocus()) { + InputMethodManager imm = (InputMethodManager) getContext().getSystemService( + Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.showSoftInput(mDeviceNameView, InputMethodManager.SHOW_IMPLICIT); + } + } + }); return mAlertDialog; } diff --git a/tests/robotests/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragmentTest.java new file mode 100644 index 00000000000..a8642d5b2ee --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragmentTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2018 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.bluetooth; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AlertDialog; +import android.content.Context; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +import com.android.settings.R; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.bluetooth.LocalBluetoothAdapter; +import com.android.settingslib.bluetooth.LocalBluetoothManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.shadows.ShadowAlertDialog; +import org.robolectric.util.FragmentTestUtil; +import org.robolectric.util.ReflectionHelpers; + +@RunWith(SettingsRobolectricTestRunner.class) +public class LocalDeviceNameDialogFragmentTest { + @Mock + private LocalBluetoothManager mManager; + @Mock + private LocalBluetoothAdapter mAdapter; + @Mock + private InputMethodManager mInputMethodManager; + + private Context mContext; + private LocalDeviceNameDialogFragment mFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + doReturn(mInputMethodManager).when(mContext).getSystemService(Context.INPUT_METHOD_SERVICE); + ReflectionHelpers.setStaticField(LocalBluetoothManager.class, "sInstance", mManager); + when(mManager.getBluetoothAdapter()).thenReturn(mAdapter); + + mFragment = spy(LocalDeviceNameDialogFragment.newInstance()); + when(mFragment.getContext()).thenReturn(mContext); + } + + @Test + public void diaglogTriggersShowSoftInput() { + FragmentTestUtil.startFragment(mFragment); + AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog(); + assertThat(dialog).isNotNull(); + View view = dialog.findViewById(R.id.edittext); + verify(mInputMethodManager).showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); + } +}