Make sure PIN edit control is focused

When doing Bluetooth pairing and the dialog reqesting a PIN comes up, we
want the PIN field to be focused and the keyboard to be shown. This fixes
a regression from N.

Bug: 62857671
Test: make RunSettingsRoboTests
Change-Id: I00dabfda737b6ac61b50518e11f21e5f9a5a1be1
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 059278d..0c4e25b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2016,6 +2016,7 @@
 
         <activity android:name=".bluetooth.BluetoothPairingDialog"
                   android:excludeFromRecents="true"
+                  android:windowSoftInputMode="stateVisible|adjustResize"
                   android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar">
             <intent-filter android:priority="1">
                 <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index 7b8fc6c..f95ce46 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -17,6 +17,7 @@
 
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
@@ -27,10 +28,12 @@
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.EditText;
 import android.widget.TextView;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -192,7 +195,16 @@
         mBuilder.setPositiveButton(getString(android.R.string.ok), this);
         mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
         AlertDialog dialog = mBuilder.create();
-        dialog.setOnShowListener(d -> mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false));
+        dialog.setOnShowListener(d -> {
+            mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
+            if (mPairingView != null && mPairingView.requestFocus()) {
+                InputMethodManager imm = (InputMethodManager)
+                        getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                if (imm != null) {
+                    imm.showSoftInput(mPairingView, InputMethodManager.SHOW_IMPLICIT);
+                }
+            }
+        });
         return dialog;
     }
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
index 243f1db..7a6ae79 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
@@ -15,17 +15,31 @@
  */
 package com.android.settings.bluetooth;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.AlertDialog;
 import android.content.Context;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.view.View;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.CheckBox;
 import android.widget.TextView;
 
 import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -36,16 +50,9 @@
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.FragmentTestUtil;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows=ShadowEventLogWriter.class)
 public class BluetoothPairingDialogTest {
 
     private static final String FILLER = "text that goes in a view";
@@ -130,12 +137,24 @@
         when(controller.getDeviceVariantMessageHintId())
                 .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
 
+        Context context = spy(ShadowApplication.getInstance().getApplicationContext());
+        InputMethodManager imm = mock(InputMethodManager.class);
+        doReturn(imm).when(context).getSystemService(Context.INPUT_METHOD_SERVICE);
+
         // build the fragment
-        BluetoothPairingDialogFragment frag = makeFragment();
+        BluetoothPairingDialogFragment frag = spy(new BluetoothPairingDialogFragment());
+        when(frag.getContext()).thenReturn(context);
+        setupFragment(frag);
+        AlertDialog alertDialog = frag.getmDialog();
 
         // check that the pin/passkey input field is visible to the user
-        View view = frag.getmDialog().findViewById(R.id.text);
+        View view = alertDialog.findViewById(R.id.text);
         assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
+
+        // check that showSoftInput was called to make input method appear when the dialog was shown
+        assertThat(view.isFocused()).isTrue();
+        assertThat(imm.isActive());
+        verify(imm).showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
     }
 
     @Test
@@ -393,8 +412,7 @@
         verify(dialogActivity, times(1)).dismiss();
     }
 
-    private BluetoothPairingDialogFragment makeFragment() {
-        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();
+    private void setupFragment(BluetoothPairingDialogFragment frag) {
         assertThat(frag.isPairingControllerSet()).isFalse();
         frag.setPairingController(controller);
         assertThat(frag.isPairingDialogActivitySet()).isFalse();
@@ -403,6 +421,11 @@
         assertThat(frag.getmDialog()).isNotNull();
         assertThat(frag.isPairingControllerSet()).isTrue();
         assertThat(frag.isPairingDialogActivitySet()).isTrue();
+    }
+
+    private BluetoothPairingDialogFragment makeFragment() {
+        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();
+        setupFragment(frag);
         return frag;
     }
 }