From f57e1673758f0a54398d5426314a8fe73a9f96c2 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 12 Jul 2017 10:18:54 -0700 Subject: [PATCH] UI refresh on bluetooth list page - xml layout clean up - add "Device name" preference, tapping will bring up rename dialog - Remove tap target from original device_name pref Change-Id: I6e9764dbb6c51f94be6d6a61d5a6401141407409 Bug: 62890841 Bug: 62891178 Test: robotests --- res/layout/dialog_edittext.xml | 14 +-- res/xml/bluetooth_settings.xml | 24 +++-- ...uetoothDeviceNamePreferenceController.java | 33 ++----- ...toothDeviceRenamePreferenceController.java | 67 +++++++++++++ .../BluetoothNameDialogFragment.java | 4 + .../bluetooth/BluetoothPairingDetail.java | 2 +- .../settings/bluetooth/BluetoothSettings.java | 12 +-- ...othDeviceNamePreferenceControllerTest.java | 31 +------ ...hDeviceRenamePreferenceControllerTest.java | 93 +++++++++++++++++++ 9 files changed, 204 insertions(+), 76 deletions(-) create mode 100644 src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java diff --git a/res/layout/dialog_edittext.xml b/res/layout/dialog_edittext.xml index c534bf19dd0..22729b66ef2 100644 --- a/res/layout/dialog_edittext.xml +++ b/res/layout/dialog_edittext.xml @@ -4,9 +4,9 @@ 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. @@ -14,20 +14,20 @@ limitations under the License. --> - + android:paddingBottom="12dp"> + android:singleLine="true" /> diff --git a/res/xml/bluetooth_settings.xml b/res/xml/bluetooth_settings.xml index 1ab2b16ab33..86d6d01ee31 100644 --- a/res/xml/bluetooth_settings.xml +++ b/res/xml/bluetooth_settings.xml @@ -16,22 +16,28 @@ + android:key="device_name" /> + android:title="@string/bluetooth_paired_device_title" /> - + - + + + + + + + diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java b/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java index dfbda1f22df..c0497f5acc4 100644 --- a/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java +++ b/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java @@ -16,12 +16,12 @@ package com.android.settings.bluetooth; -import android.app.Fragment; import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.text.Spannable; @@ -30,7 +30,6 @@ import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.bluetooth.LocalBluetoothAdapter; @@ -49,15 +48,15 @@ public class BluetoothDeviceNamePreferenceController extends AbstractPreferenceC private static final String TAG = "BluetoothNamePrefCtrl"; public static final String KEY_DEVICE_NAME = "device_name"; - private int mAccentColor; - private Fragment mFragment; + + private final int mAccentColor; + private LocalBluetoothManager mLocalManager; private LocalBluetoothAdapter mLocalAdapter; private Preference mPreference; - public BluetoothDeviceNamePreferenceController(Context context, Fragment fragment, - Lifecycle lifecycle) { - this(context, fragment, (LocalBluetoothAdapter) null); + public BluetoothDeviceNamePreferenceController(Context context, Lifecycle lifecycle) { + this(context, (LocalBluetoothAdapter) null); mLocalManager = Utils.getLocalBtManager(context); if (mLocalManager == null) { @@ -69,17 +68,16 @@ public class BluetoothDeviceNamePreferenceController extends AbstractPreferenceC } @VisibleForTesting - BluetoothDeviceNamePreferenceController(Context context, Fragment fragment, - LocalBluetoothAdapter localAdapter) { + BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter) { super(context); mAccentColor = com.android.settingslib.Utils.getColorAccent(context); - mFragment = fragment; mLocalAdapter = localAdapter; } @Override public void displayPreference(PreferenceScreen screen) { mPreference = screen.findPreference(KEY_DEVICE_NAME); + super.displayPreference(screen); } @Override @@ -108,22 +106,11 @@ public class BluetoothDeviceNamePreferenceController extends AbstractPreferenceC updateDeviceName(preference, mLocalAdapter.getName()); } - @Override - public boolean handlePreferenceTreeClick(Preference preference) { - if (KEY_DEVICE_NAME.equals(preference.getKey())) { - LocalDeviceNameDialogFragment.newInstance() - .show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG); - return true; - } - - return false; - } - /** * Create preference to show bluetooth device name * * @param screen to add the preference in - * @param order to decide position of the preference + * @param order to decide position of the preference * @return bluetooth preference that created in this method */ public Preference createBluetoothDeviceNamePreference(PreferenceScreen screen, int order) { @@ -141,7 +128,7 @@ public class BluetoothDeviceNamePreferenceController extends AbstractPreferenceC * @param preference to set the summary for * @param deviceName bluetooth device name to show in the summary */ - public void updateDeviceName(final Preference preference, final String deviceName) { + protected void updateDeviceName(final Preference preference, final String deviceName) { if (deviceName == null) { // TODO: show error message in preference subtitle return; diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java new file mode 100644 index 00000000000..6f9cf409945 --- /dev/null +++ b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 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 android.app.Fragment; +import android.content.Context; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settingslib.bluetooth.LocalBluetoothAdapter; +import com.android.settingslib.core.lifecycle.Lifecycle; + +public class BluetoothDeviceRenamePreferenceController extends + BluetoothDeviceNamePreferenceController { + + public static final String PREF_KEY = "bt_rename_device"; + + private final Fragment mFragment; + + public BluetoothDeviceRenamePreferenceController(Context context, Fragment fragment, + Lifecycle lifecycle) { + super(context, lifecycle); + mFragment = fragment; + } + + @VisibleForTesting + BluetoothDeviceRenamePreferenceController(Context context, Fragment fragment, + LocalBluetoothAdapter localAdapter) { + super(context, localAdapter); + mFragment = fragment; + } + + @Override + public String getPreferenceKey() { + return PREF_KEY; + } + + @Override + protected void updateDeviceName(final Preference preference, final String deviceName) { + preference.setSummary(deviceName); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (PREF_KEY.equals(preference.getKey())) { + LocalDeviceNameDialogFragment.newInstance() + .show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG); + return true; + } + + return false; + } +} diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java index e415b47c1a8..25413fa6db5 100644 --- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java @@ -24,6 +24,7 @@ import android.content.res.Configuration; import android.os.Bundle; import android.text.Editable; import android.text.InputFilter; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -111,6 +112,9 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment new Utf8ByteLengthFilter(BLUETOOTH_NAME_MAX_LENGTH_BYTES) }); mDeviceNameView.setText(deviceName); // set initial value before adding listener + if (!TextUtils.isEmpty(deviceName)) { + mDeviceNameView.setSelection(deviceName.length()); + } mDeviceNameView.addTextChangedListener(this); mDeviceNameView.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java index 115499a0a00..5cc1060f1ab 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java @@ -186,7 +186,7 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme protected List getPreferenceControllers(Context context) { List controllers = new ArrayList<>(); mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context, - this, getLifecycle()); + getLifecycle()); controllers.add(mDeviceNamePrefController); return controllers; diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index 3c2ab3048db..adfb721da6c 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -23,7 +23,6 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.ContentResolver; import android.content.Context; -import android.content.IntentFilter; import android.content.res.Resources; import android.os.Bundle; import android.provider.Settings; @@ -55,6 +54,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothAdapter; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.FooterPreference; import java.util.ArrayList; @@ -63,7 +63,6 @@ import java.util.List; /** * BluetoothSettings is the Settings screen for Bluetooth configuration and * connection management. - * */ public class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable { private static final String TAG = "BluetoothSettings"; @@ -84,7 +83,6 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I private SwitchBar mSwitchBar; - private final IntentFilter mIntentFilter; private BluetoothDeviceNamePreferenceController mDeviceNamePrefController; @VisibleForTesting BluetoothPairingPreferenceController mPairingPrefController; @@ -95,7 +93,6 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I public BluetoothSettings() { super(DISALLOW_CONFIG_BLUETOOTH); - mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); } @Override @@ -353,14 +350,15 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I @Override protected List getPreferenceControllers(Context context) { - List controllers = new ArrayList<>(); - mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context, - this, getLifecycle()); + final List controllers = new ArrayList<>(); + final Lifecycle lifecycle = getLifecycle(); + mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context, lifecycle); mPairingPrefController = new BluetoothPairingPreferenceController(context, this, (SettingsActivity) getActivity()); controllers.add(mDeviceNamePrefController); controllers.add(mPairingPrefController); controllers.add(new BluetoothFilesPreferenceController(context)); + controllers.add(new BluetoothDeviceRenamePreferenceController(context, this, lifecycle)); return controllers; } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java index 84bdfcf147e..41fe2c2e3ce 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java @@ -17,33 +17,25 @@ package com.android.settings.bluetooth; import static com.google.common.truth.Truth.assertThat; - import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; -import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.bluetooth.LocalBluetoothAdapter; -import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; @@ -56,17 +48,9 @@ public class BluetoothDeviceNamePreferenceControllerTest { private static final int ORDER = 1; private Context mContext; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Fragment mFragment; - @Mock - private Lifecycle mLifecycle; @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock - private FragmentManager mFragmentManager; - @Mock - private FragmentTransaction mFragmentTransaction; - @Mock private PreferenceScreen mPreferenceScreen; private Preference mPreference; @@ -82,7 +66,7 @@ public class BluetoothDeviceNamePreferenceControllerTest { mPreference = new Preference(mContext); mPreference.setKey(BluetoothDeviceNamePreferenceController.KEY_DEVICE_NAME); mController = new BluetoothDeviceNamePreferenceController( - mContext, mFragment, mLocalAdapter); + mContext, mLocalAdapter); } @Test @@ -124,15 +108,4 @@ public class BluetoothDeviceNamePreferenceControllerTest { mController.onStop(); verify(mContext).unregisterReceiver(mController.mReceiver); } - - @Test - public void testHandlePreferenceTreeClick_startDialogFragment() { - when(mFragment.getFragmentManager().beginTransaction()).thenReturn(mFragmentTransaction); - - mController.handlePreferenceTreeClick(mPreference); - - verify(mFragmentTransaction).add(any(), anyString()); - verify(mFragmentTransaction).commit(); - } - } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java new file mode 100644 index 00000000000..f0460960e83 --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 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 static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.bluetooth.LocalBluetoothAdapter; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class BluetoothDeviceRenamePreferenceControllerTest { + + private static final String DEVICE_NAME = "Nightshade"; + + @Mock + private LocalBluetoothAdapter mLocalAdapter; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Fragment mFragment; + @Mock + private FragmentManager mFragmentManager; + @Mock + private FragmentTransaction mFragmentTransaction; + private Context mContext; + private Preference mPreference; + private BluetoothDeviceRenamePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + mPreference = new Preference(mContext); + mPreference.setKey(BluetoothDeviceRenamePreferenceController.PREF_KEY); + + mController = new BluetoothDeviceRenamePreferenceController( + mContext, mFragment, mLocalAdapter); + } + + @Test + public void testUpdateDeviceName_showSummaryWithDeviceName() { + mController.updateDeviceName(mPreference, DEVICE_NAME); + + final CharSequence summary = mPreference.getSummary(); + + assertThat(summary.toString()).isEqualTo(DEVICE_NAME); + } + + @Test + public void testHandlePreferenceTreeClick_startDialogFragment() { + when(mFragment.getFragmentManager().beginTransaction()).thenReturn(mFragmentTransaction); + + mController.handlePreferenceTreeClick(mPreference); + + verify(mFragmentTransaction).add(any(), anyString()); + verify(mFragmentTransaction).commit(); + } +}