OSDN Git Service

Fix rotation bug in Bluetooth pairing PIN dialog
authorAntony Sargent <asargent@google.com>
Tue, 15 Aug 2017 16:31:31 +0000 (09:31 -0700)
committerAntony Sargent <asargent@google.com>
Wed, 16 Aug 2017 22:19:47 +0000 (15:19 -0700)
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

src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java

index f95ce46..1aac0ff 100644 (file)
@@ -25,6 +25,7 @@ import android.text.Editable;
 import android.text.InputFilter;
 import android.text.InputFilter.LengthFilter;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
@@ -34,6 +35,7 @@ import android.widget.CheckBox;
 import android.widget.EditText;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -186,6 +188,19 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
     }
 
     /**
+     * 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.
      */
     private AlertDialog createUserEntryDialog() {
@@ -196,7 +211,9 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
         mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
         AlertDialog dialog = mBuilder.create();
         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()) {
                 InputMethodManager imm = (InputMethodManager)
                         getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
index 7a6ae79..fba11de 100644 (file)
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.Context;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -47,6 +48,7 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.FragmentTestUtil;
 
@@ -412,6 +414,39 @@ public class BluetoothPairingDialogTest {
         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) {
         assertThat(frag.isPairingControllerSet()).isFalse();
         frag.setPairingController(controller);