diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java index 260b4a81f49..74c39b6f8c2 100644 --- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java @@ -34,6 +34,7 @@ import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import com.android.settings.R; @@ -43,8 +44,14 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment; * Dialog fragment for renaming a Bluetooth device. */ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment - implements TextWatcher { - private AlertDialog mAlertDialog; + implements TextWatcher, TextView.OnEditorActionListener { + + // Key to save the edited name and edit status for restoring after rotation + private static final String KEY_NAME = "device_name"; + private static final String KEY_NAME_EDITED = "device_name_edited"; + + @VisibleForTesting + AlertDialog mAlertDialog; private Button mOkButton; EditText mDeviceNameView; @@ -55,10 +62,6 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment // This flag is set when the user edits the name (preserved on rotation) private boolean mDeviceNameEdited; - // Key to save the edited name and edit status for restoring after rotation - private static final String KEY_NAME = "device_name"; - private static final String KEY_NAME_EDITED = "device_name_edited"; - /** * @return the title to use for the dialog. */ @@ -123,21 +126,23 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment } mDeviceNameView.addTextChangedListener(this); com.android.settings.Utils.setEditTextCursorPosition(mDeviceNameView); - mDeviceNameView.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_DONE) { - setDeviceName(v.getText().toString()); - mAlertDialog.dismiss(); - return true; // action handled - } else { - return false; // not handled - } - } - }); + mDeviceNameView.setOnEditorActionListener(this); return view; } + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + setDeviceName(v.getText().toString()); + if (mAlertDialog != null && mAlertDialog.isShowing()) { + mAlertDialog.dismiss(); + } + return true; // action handled + } else { + return false; // not handled + } + } + @Override public void onDestroy() { super.onDestroy(); diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothNameDialogFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothNameDialogFragmentTest.java new file mode 100644 index 00000000000..350ec9e3e6b --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothNameDialogFragmentTest.java @@ -0,0 +1,82 @@ +/* + * 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 android.view.inputmethod.EditorInfo; +import android.widget.TextView; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class BluetoothNameDialogFragmentTest { + + private TestBluetoothNameDialogFragment mBluetoothNameDialogFragment; + private TextView mTextView; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mBluetoothNameDialogFragment = new TestBluetoothNameDialogFragment(); + mTextView = new TextView(RuntimeEnvironment.application); + } + + @Test + public void onEditorAction_dialogNull_shouldNotCrash() { + mBluetoothNameDialogFragment.mAlertDialog = null; + + // Should not crash + assertThat( + mBluetoothNameDialogFragment.onEditorAction(mTextView, EditorInfo.IME_ACTION_DONE, + null)).isTrue(); + } + + + /** + * Test fragment for {@link BluetoothNameDialogFragment} to test common methods + */ + public static class TestBluetoothNameDialogFragment extends BluetoothNameDialogFragment { + + @Override + protected int getDialogTitle() { + return 0; + } + + @Override + protected String getDeviceName() { + return null; + } + + @Override + protected void setDeviceName(String deviceName) { + + } + + @Override + public int getMetricsCategory() { + return 0; + } + } + +}