Loading src/com/android/settings/bluetooth/BluetoothPairingDialog.java +24 −13 Original line number Diff line number Diff line Loading @@ -24,16 +24,17 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.annotation.VisibleForTesting; /** * BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple confirmation * for pairing with a remote Bluetooth device. It is an activity that appears as a dialog. */ public final class BluetoothPairingDialog extends Activity { public class BluetoothPairingDialog extends Activity { public static final String FRAGMENT_TAG = "bluetooth.pairing.fragment"; private BluetoothPairingController mBluetoothPairingController; private boolean mReceiverRegistered; private boolean mReceiverRegistered = false; /** * Dismiss the dialog if the bond state changes to bonded or none, Loading Loading @@ -62,23 +63,26 @@ public final class BluetoothPairingDialog extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); boolean fragmentFound = true; BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager() .findFragmentByTag(FRAGMENT_TAG); Intent intent = getIntent(); mBluetoothPairingController = new BluetoothPairingController(intent, this); // check if the fragment exists already // build the dialog fragment boolean fragmentFound = true; // check if the fragment has been preloaded BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); // dismiss the fragment if it is already used if (bluetoothFragment != null && (bluetoothFragment.isPairingControllerSet() || bluetoothFragment.isPairingDialogActivitySet())) { bluetoothFragment.dismiss(); bluetoothFragment = null; } // build a new fragment if it is null if (bluetoothFragment == null) { fragmentFound = false; bluetoothFragment = new BluetoothPairingDialogFragment(); } // set the controller bluetoothFragment.setPairingController(mBluetoothPairingController); bluetoothFragment.setPairingDialogActivity(this); // pass the fragment to the manager when it is created from scratch if (!fragmentFound) { bluetoothFragment.show(getFragmentManager(), FRAGMENT_TAG); Loading @@ -101,8 +105,15 @@ public final class BluetoothPairingDialog extends Activity { } } private void dismiss() { @VisibleForTesting void dismiss() { if (!isFinishing()) { BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager() .findFragmentByTag(FRAGMENT_TAG); if (bluetoothFragment != null) { bluetoothFragment.dismiss(); } finish(); } } Loading src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java +37 −4 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i private AlertDialog.Builder mBuilder; private AlertDialog mDialog; private BluetoothPairingController mPairingController; private BluetoothPairingDialog mPairingDialogActivity; private EditText mPairingView; /** * The interface we expect a listener to implement. Typically this should be done by Loading @@ -61,10 +62,14 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i @Override public Dialog onCreateDialog(Bundle savedInstanceState) { if (mPairingController == null) { if (!isPairingControllerSet()) { throw new IllegalStateException( "Must call setPairingController() before showing dialog"); } if (!isPairingDialogActivitySet()) { throw new IllegalStateException( "Must call setPairingDialogActivity() before showing dialog"); } mBuilder = new AlertDialog.Builder(getActivity()); mDialog = setupDialog(); mDialog.setCanceledOnTouchOutside(false); Loading Loading @@ -97,6 +102,7 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i } else if (which == DialogInterface.BUTTON_NEGATIVE) { mPairingController.onDialogNegativeClick(this); } mPairingDialogActivity.dismiss(); } @Override Loading @@ -119,14 +125,41 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i * controller may not be substituted once it is assigned. Forcibly switching a * controller for a new one will lead to undefined behavior. */ public void setPairingController(BluetoothPairingController pairingController) { if (mPairingController != null) { void setPairingController(BluetoothPairingController pairingController) { if (isPairingControllerSet()) { throw new IllegalStateException("The controller can only be set once. " + "Forcibly replacing it will lead to undefined behavior"); } mPairingController = pairingController; } /** * Checks whether mPairingController is set * @return True when mPairingController is set, False otherwise */ boolean isPairingControllerSet() { return mPairingController != null; } /** * Sets the BluetoothPairingDialog activity that started this fragment * @param pairingDialogActivity The pairing dialog activty that started this fragment */ void setPairingDialogActivity(BluetoothPairingDialog pairingDialogActivity) { if (isPairingDialogActivitySet()) { throw new IllegalStateException("The pairing dialog activity can only be set once"); } mPairingDialogActivity = pairingDialogActivity; } /** * Checks whether mPairingDialogActivity is set * @return True when mPairingDialogActivity is set, False otherwise */ boolean isPairingDialogActivitySet() { return mPairingDialogActivity != null; } /** * Creates the appropriate type of dialog and returns it. */ Loading src/com/android/settings/bluetooth/BluetoothPairingRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ public final class BluetoothPairingRequest extends BroadcastReceiver { if (powerManager.isInteractive() && shouldShowDialog) { // Since the screen is on and the BT-related activity is in the foreground, // just open the dialog context.startActivity(pairingIntent); context.startActivityAsUser(pairingIntent, UserHandle.CURRENT); } else { // Put up a notification that leads to the dialog intent.setClass(context, BluetoothPairingService.class); Loading tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -54,9 +54,13 @@ public class BluetoothPairingDialogTest { @Mock private BluetoothPairingController controller; @Mock private BluetoothPairingDialog dialogActivity; @Before public void setUp() { MockitoAnnotations.initMocks(this); doNothing().when(dialogActivity).dismiss(); } @Test Loading Loading @@ -214,6 +218,17 @@ public class BluetoothPairingDialogTest { fail("Setting the controller multiple times should throw an exception."); } @Test(expected = IllegalStateException.class) public void dialogDoesNotAllowSwappingActivity() { // instantiate a fragment BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment(); frag.setPairingDialogActivity(dialogActivity); // this should throw an error frag.setPairingDialogActivity(dialogActivity); fail("Setting the dialog activity multiple times should throw an exception."); } @Test public void dialogPositiveButtonDisabledWhenUserInputInvalid() { // set the correct dialog type Loading Loading @@ -342,11 +357,52 @@ public class BluetoothPairingDialogTest { .contains(device); } @Test public void pairingDialogDismissedOnPositiveClick() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); // we don't care what this does, just that it is called doNothing().when(controller).onDialogPositiveClick(any()); // build the fragment BluetoothPairingDialogFragment frag = makeFragment(); // click the button and verify that the controller hook was called frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_POSITIVE); verify(controller, times(1)).onDialogPositiveClick(any()); verify(dialogActivity, times(1)).dismiss(); } @Test public void pairingDialogDismissedOnNegativeClick() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); // we don't care what this does, just that it is called doNothing().when(controller).onDialogNegativeClick(any()); // build the fragment BluetoothPairingDialogFragment frag = makeFragment(); // click the button and verify that the controller hook was called frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_NEGATIVE); verify(controller, times(1)).onDialogNegativeClick(any()); verify(dialogActivity, times(1)).dismiss(); } private BluetoothPairingDialogFragment makeFragment() { BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment(); assertThat(frag.isPairingControllerSet()).isFalse(); frag.setPairingController(controller); assertThat(frag.isPairingDialogActivitySet()).isFalse(); frag.setPairingDialogActivity(dialogActivity); FragmentTestUtil.startFragment(frag); assertThat(frag.getmDialog()).isNotNull(); assertThat(frag.isPairingControllerSet()).isTrue(); assertThat(frag.isPairingDialogActivitySet()).isTrue(); return frag; } } Loading
src/com/android/settings/bluetooth/BluetoothPairingDialog.java +24 −13 Original line number Diff line number Diff line Loading @@ -24,16 +24,17 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.annotation.VisibleForTesting; /** * BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple confirmation * for pairing with a remote Bluetooth device. It is an activity that appears as a dialog. */ public final class BluetoothPairingDialog extends Activity { public class BluetoothPairingDialog extends Activity { public static final String FRAGMENT_TAG = "bluetooth.pairing.fragment"; private BluetoothPairingController mBluetoothPairingController; private boolean mReceiverRegistered; private boolean mReceiverRegistered = false; /** * Dismiss the dialog if the bond state changes to bonded or none, Loading Loading @@ -62,23 +63,26 @@ public final class BluetoothPairingDialog extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); boolean fragmentFound = true; BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager() .findFragmentByTag(FRAGMENT_TAG); Intent intent = getIntent(); mBluetoothPairingController = new BluetoothPairingController(intent, this); // check if the fragment exists already // build the dialog fragment boolean fragmentFound = true; // check if the fragment has been preloaded BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); // dismiss the fragment if it is already used if (bluetoothFragment != null && (bluetoothFragment.isPairingControllerSet() || bluetoothFragment.isPairingDialogActivitySet())) { bluetoothFragment.dismiss(); bluetoothFragment = null; } // build a new fragment if it is null if (bluetoothFragment == null) { fragmentFound = false; bluetoothFragment = new BluetoothPairingDialogFragment(); } // set the controller bluetoothFragment.setPairingController(mBluetoothPairingController); bluetoothFragment.setPairingDialogActivity(this); // pass the fragment to the manager when it is created from scratch if (!fragmentFound) { bluetoothFragment.show(getFragmentManager(), FRAGMENT_TAG); Loading @@ -101,8 +105,15 @@ public final class BluetoothPairingDialog extends Activity { } } private void dismiss() { @VisibleForTesting void dismiss() { if (!isFinishing()) { BluetoothPairingDialogFragment bluetoothFragment = (BluetoothPairingDialogFragment) getFragmentManager() .findFragmentByTag(FRAGMENT_TAG); if (bluetoothFragment != null) { bluetoothFragment.dismiss(); } finish(); } } Loading
src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java +37 −4 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i private AlertDialog.Builder mBuilder; private AlertDialog mDialog; private BluetoothPairingController mPairingController; private BluetoothPairingDialog mPairingDialogActivity; private EditText mPairingView; /** * The interface we expect a listener to implement. Typically this should be done by Loading @@ -61,10 +62,14 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i @Override public Dialog onCreateDialog(Bundle savedInstanceState) { if (mPairingController == null) { if (!isPairingControllerSet()) { throw new IllegalStateException( "Must call setPairingController() before showing dialog"); } if (!isPairingDialogActivitySet()) { throw new IllegalStateException( "Must call setPairingDialogActivity() before showing dialog"); } mBuilder = new AlertDialog.Builder(getActivity()); mDialog = setupDialog(); mDialog.setCanceledOnTouchOutside(false); Loading Loading @@ -97,6 +102,7 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i } else if (which == DialogInterface.BUTTON_NEGATIVE) { mPairingController.onDialogNegativeClick(this); } mPairingDialogActivity.dismiss(); } @Override Loading @@ -119,14 +125,41 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i * controller may not be substituted once it is assigned. Forcibly switching a * controller for a new one will lead to undefined behavior. */ public void setPairingController(BluetoothPairingController pairingController) { if (mPairingController != null) { void setPairingController(BluetoothPairingController pairingController) { if (isPairingControllerSet()) { throw new IllegalStateException("The controller can only be set once. " + "Forcibly replacing it will lead to undefined behavior"); } mPairingController = pairingController; } /** * Checks whether mPairingController is set * @return True when mPairingController is set, False otherwise */ boolean isPairingControllerSet() { return mPairingController != null; } /** * Sets the BluetoothPairingDialog activity that started this fragment * @param pairingDialogActivity The pairing dialog activty that started this fragment */ void setPairingDialogActivity(BluetoothPairingDialog pairingDialogActivity) { if (isPairingDialogActivitySet()) { throw new IllegalStateException("The pairing dialog activity can only be set once"); } mPairingDialogActivity = pairingDialogActivity; } /** * Checks whether mPairingDialogActivity is set * @return True when mPairingDialogActivity is set, False otherwise */ boolean isPairingDialogActivitySet() { return mPairingDialogActivity != null; } /** * Creates the appropriate type of dialog and returns it. */ Loading
src/com/android/settings/bluetooth/BluetoothPairingRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ public final class BluetoothPairingRequest extends BroadcastReceiver { if (powerManager.isInteractive() && shouldShowDialog) { // Since the screen is on and the BT-related activity is in the foreground, // just open the dialog context.startActivity(pairingIntent); context.startActivityAsUser(pairingIntent, UserHandle.CURRENT); } else { // Put up a notification that leads to the dialog intent.setClass(context, BluetoothPairingService.class); Loading
tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -54,9 +54,13 @@ public class BluetoothPairingDialogTest { @Mock private BluetoothPairingController controller; @Mock private BluetoothPairingDialog dialogActivity; @Before public void setUp() { MockitoAnnotations.initMocks(this); doNothing().when(dialogActivity).dismiss(); } @Test Loading Loading @@ -214,6 +218,17 @@ public class BluetoothPairingDialogTest { fail("Setting the controller multiple times should throw an exception."); } @Test(expected = IllegalStateException.class) public void dialogDoesNotAllowSwappingActivity() { // instantiate a fragment BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment(); frag.setPairingDialogActivity(dialogActivity); // this should throw an error frag.setPairingDialogActivity(dialogActivity); fail("Setting the dialog activity multiple times should throw an exception."); } @Test public void dialogPositiveButtonDisabledWhenUserInputInvalid() { // set the correct dialog type Loading Loading @@ -342,11 +357,52 @@ public class BluetoothPairingDialogTest { .contains(device); } @Test public void pairingDialogDismissedOnPositiveClick() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); // we don't care what this does, just that it is called doNothing().when(controller).onDialogPositiveClick(any()); // build the fragment BluetoothPairingDialogFragment frag = makeFragment(); // click the button and verify that the controller hook was called frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_POSITIVE); verify(controller, times(1)).onDialogPositiveClick(any()); verify(dialogActivity, times(1)).dismiss(); } @Test public void pairingDialogDismissedOnNegativeClick() { // set the dialog variant to confirmation/consent when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); // we don't care what this does, just that it is called doNothing().when(controller).onDialogNegativeClick(any()); // build the fragment BluetoothPairingDialogFragment frag = makeFragment(); // click the button and verify that the controller hook was called frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_NEGATIVE); verify(controller, times(1)).onDialogNegativeClick(any()); verify(dialogActivity, times(1)).dismiss(); } private BluetoothPairingDialogFragment makeFragment() { BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment(); assertThat(frag.isPairingControllerSet()).isFalse(); frag.setPairingController(controller); assertThat(frag.isPairingDialogActivitySet()).isFalse(); frag.setPairingDialogActivity(dialogActivity); FragmentTestUtil.startFragment(frag); assertThat(frag.getmDialog()).isNotNull(); assertThat(frag.isPairingControllerSet()).isTrue(); assertThat(frag.isPairingDialogActivitySet()).isTrue(); return frag; } }