Fix rotation bug in Bluetooth pairing PIN dialog
BluetoothPairingDialogFragment has code that makes the OK button on the dialog disabled until the user has entered at least one character into the PIN field. However it didn't properly handle the case where the user had entered some text and then rotated the screen - because it always marked the OK button as disabled during onShow even if it already had some content. This CL fixes that by looking at the text content and only disabling the OK button if the content is empty. Bug: 36514895 Test: make RunSettingsRoboTests Change-Id: I4e8e70089a862e67b20ff614bbaa64fc2b641fd4
This commit is contained in:
@@ -25,6 +25,7 @@ import android.text.Editable;
|
|||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.InputFilter.LengthFilter;
|
import android.text.InputFilter.LengthFilter;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -34,6 +35,7 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
@@ -185,6 +187,19 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
|
|||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to return the text of the pin entry field - this exists primarily to help us
|
||||||
|
* simulate having existing text when the dialog is recreated, for example after a screen
|
||||||
|
* rotation.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
CharSequence getPairingViewText() {
|
||||||
|
if (mPairingView != null) {
|
||||||
|
return mPairingView.getText();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a dialog with UI elements that allow a user to provide input.
|
* Returns a dialog with UI elements that allow a user to provide input.
|
||||||
*/
|
*/
|
||||||
@@ -196,7 +211,9 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
|
|||||||
mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
|
mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
|
||||||
AlertDialog dialog = mBuilder.create();
|
AlertDialog dialog = mBuilder.create();
|
||||||
dialog.setOnShowListener(d -> {
|
dialog.setOnShowListener(d -> {
|
||||||
mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
|
if (TextUtils.isEmpty(getPairingViewText())) {
|
||||||
|
mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
|
||||||
|
}
|
||||||
if (mPairingView != null && mPairingView.requestFocus()) {
|
if (mPairingView != null && mPairingView.requestFocus()) {
|
||||||
InputMethodManager imm = (InputMethodManager)
|
InputMethodManager imm = (InputMethodManager)
|
||||||
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -47,6 +48,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowAlertDialog;
|
||||||
import org.robolectric.shadows.ShadowApplication;
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
import org.robolectric.util.FragmentTestUtil;
|
import org.robolectric.util.FragmentTestUtil;
|
||||||
|
|
||||||
@@ -412,6 +414,39 @@ public class BluetoothPairingDialogTest {
|
|||||||
verify(dialogActivity, times(1)).dismiss();
|
verify(dialogActivity, times(1)).dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rotateDialog_nullPinText_okButtonEnabled() {
|
||||||
|
userEntryDialogExistingTextTest(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rotateDialog_emptyPinText_okButtonEnabled() {
|
||||||
|
userEntryDialogExistingTextTest("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rotateDialog_nonEmptyPinText_okButtonEnabled() {
|
||||||
|
userEntryDialogExistingTextTest("test");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs a test simulating the user entry dialog type in a situation like device rotation, where
|
||||||
|
// the dialog fragment gets created and we already have some existing text entered into the
|
||||||
|
// pin field.
|
||||||
|
private void userEntryDialogExistingTextTest(CharSequence existingText) {
|
||||||
|
when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);
|
||||||
|
when(controller.getDeviceVariantMessageHintId())
|
||||||
|
.thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
|
||||||
|
when(controller.getDeviceVariantMessageId())
|
||||||
|
.thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
|
||||||
|
|
||||||
|
BluetoothPairingDialogFragment fragment = spy(new BluetoothPairingDialogFragment());
|
||||||
|
when(fragment.getPairingViewText()).thenReturn(existingText);
|
||||||
|
setupFragment(fragment);
|
||||||
|
AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
|
||||||
|
boolean expected = !TextUtils.isEmpty(existingText);
|
||||||
|
assertThat(dialog.getButton(Dialog.BUTTON_POSITIVE).isEnabled()).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
private void setupFragment(BluetoothPairingDialogFragment frag) {
|
private void setupFragment(BluetoothPairingDialogFragment frag) {
|
||||||
assertThat(frag.isPairingControllerSet()).isFalse();
|
assertThat(frag.isPairingControllerSet()).isFalse();
|
||||||
frag.setPairingController(controller);
|
frag.setPairingController(controller);
|
||||||
|
Reference in New Issue
Block a user