Bluetooth: Only show devices when their names are resolved
* Add a developer menu option to allow name-less devices to be shown when a Bluetooth developer needs it, but hide it for non-developer users. * Set BluetoothDevicePreference to invisible when CachedBluetoothDevice does not have a name besides MAC address and the above developer option is false. * This affects BluetoothPairingDetail and DevicePickerFragment, but does not affect BluetoothSettings. BluetoothSettings will show all paired devices regardless whether an user friendly name exists. Bug: 34685932 Test: pair Bluetooth device, send file over Bluetooth, unit tests Change-Id: Idd7ad4b1671dfdcf3204efb50eddb6dae1065aa5
This commit is contained in:
@@ -209,6 +209,11 @@
|
||||
android:entries="@array/usb_configuration_titles"
|
||||
android:entryValues="@array/usb_configuration_values" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="bluetooth_show_devices_without_names"
|
||||
android:title="@string/bluetooth_show_devices_without_names"
|
||||
android:summary="@string/bluetooth_show_devices_without_names_summary"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="bluetooth_disable_absolute_volume"
|
||||
android:title="@string/bluetooth_disable_absolute_volume"
|
||||
|
@@ -54,16 +54,17 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
private final UserManager mUserManager;
|
||||
|
||||
private AlertDialog mDisconnectDialog;
|
||||
|
||||
private String contentDescription = null;
|
||||
|
||||
private DeviceListPreferenceFragment mDeviceListPreferenceFragment;
|
||||
/* Talk-back descriptions for various BT icons */
|
||||
Resources mResources;
|
||||
|
||||
public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
|
||||
public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
|
||||
DeviceListPreferenceFragment deviceListPreferenceFragment) {
|
||||
super(context, null);
|
||||
mResources = getContext().getResources();
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mDeviceListPreferenceFragment = deviceListPreferenceFragment;
|
||||
|
||||
if (sDimAlpha == Integer.MIN_VALUE) {
|
||||
TypedValue outValue = new TypedValue();
|
||||
@@ -131,6 +132,11 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
// Used to gray out the item
|
||||
setEnabled(!mCachedDevice.isBusy());
|
||||
|
||||
// Device is only visible in the UI if it has a valid name besides MAC address or when user
|
||||
// allows showing devices without user-friendly name in developer settings
|
||||
setVisible(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()
|
||||
|| mCachedDevice.hasHumanReadableName());
|
||||
|
||||
// This could affect ordering, so notify that
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
|
@@ -140,6 +140,8 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
|
||||
mBluetoothEnabler.resume(getActivity());
|
||||
}
|
||||
super.onStart();
|
||||
// Always show paired devices regardless whether user-friendly name exists
|
||||
mShowDevicesWithoutNames = true;
|
||||
if (isUiRestricted()) {
|
||||
getPreferenceScreen().removeAll();
|
||||
if (!isUiRestrictedByOnlyAdmin()) {
|
||||
|
@@ -19,6 +19,7 @@ package com.android.settings.bluetooth;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
@@ -52,6 +53,10 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
|
||||
private static final String KEY_BT_SCAN = "bt_scan";
|
||||
|
||||
// Copied from DevelopmentSettings.java
|
||||
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
|
||||
"persist.bluetooth.showdeviceswithoutnames";
|
||||
|
||||
private BluetoothDeviceFilter.Filter mFilter;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -68,6 +73,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
|
||||
new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
|
||||
|
||||
boolean mShowDevicesWithoutNames;
|
||||
|
||||
DeviceListPreferenceFragment(String restrictedKey) {
|
||||
super(restrictedKey);
|
||||
mFilter = BluetoothDeviceFilter.ALL_FILTER;
|
||||
@@ -103,6 +110,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mShowDevicesWithoutNames = SystemProperties.getBoolean(
|
||||
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
|
||||
if (mLocalManager == null || isUiRestricted()) return;
|
||||
|
||||
mLocalManager.setForegroundActivity(getActivity());
|
||||
@@ -181,7 +190,7 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
|
||||
|
||||
if (preference == null) {
|
||||
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice);
|
||||
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice, this);
|
||||
preference.setKey(key);
|
||||
mDeviceListGroup.addPreference(preference);
|
||||
} else {
|
||||
@@ -271,4 +280,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
* Return the key of the {@link PreferenceGroup} that contains the bluetooth devices
|
||||
*/
|
||||
public abstract String getDeviceListKey();
|
||||
|
||||
public boolean shouldShowDevicesWithoutNames() {
|
||||
return mShowDevicesWithoutNames;
|
||||
}
|
||||
}
|
||||
|
@@ -199,6 +199,10 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
|
||||
private static final String COLOR_TEMPERATURE_KEY = "color_temperature";
|
||||
|
||||
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_KEY =
|
||||
"bluetooth_show_devices_without_names";
|
||||
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
|
||||
"persist.bluetooth.showdeviceswithoutnames";
|
||||
private static final String BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY =
|
||||
"bluetooth_disable_absolute_volume";
|
||||
private static final String BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_PROPERTY =
|
||||
@@ -282,6 +286,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
private SwitchPreference mWifiAggressiveHandover;
|
||||
private SwitchPreference mMobileDataAlwaysOn;
|
||||
private SwitchPreference mTetheringHardwareOffload;
|
||||
private SwitchPreference mBluetoothShowDevicesWithoutNames;
|
||||
private SwitchPreference mBluetoothDisableAbsVolume;
|
||||
private SwitchPreference mBluetoothEnableInbandRinging;
|
||||
|
||||
@@ -498,6 +503,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
mLogpersist = null;
|
||||
}
|
||||
mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
|
||||
mBluetoothShowDevicesWithoutNames =
|
||||
findAndInitSwitchPref(BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_KEY);
|
||||
mBluetoothDisableAbsVolume = findAndInitSwitchPref(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY);
|
||||
mBluetoothEnableInbandRinging = findAndInitSwitchPref(BLUETOOTH_ENABLE_INBAND_RINGING_KEY);
|
||||
if (!BluetoothHeadset.isInbandRingingSupported(getContext())) {
|
||||
@@ -838,6 +845,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
if (mColorTemperaturePreference != null) {
|
||||
updateColorTemperature();
|
||||
}
|
||||
updateBluetoothShowDevicesWithoutUserFriendlyNameOptions();
|
||||
updateBluetoothDisableAbsVolumeOptions();
|
||||
updateBluetoothEnableInbandRingingOptions();
|
||||
updateBluetoothA2dpConfigurationValues();
|
||||
@@ -1468,6 +1476,17 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
mWifiManager.setAllowScansWithTraffic(mWifiAllowScansWithTraffic.isChecked() ? 1 : 0);
|
||||
}
|
||||
|
||||
private void updateBluetoothShowDevicesWithoutUserFriendlyNameOptions() {
|
||||
updateSwitchPreference(mBluetoothShowDevicesWithoutNames,
|
||||
SystemProperties.getBoolean(
|
||||
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false));
|
||||
}
|
||||
|
||||
private void writeBluetoothShowDevicesWithoutUserFriendlyNameOptions() {
|
||||
SystemProperties.set(BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY,
|
||||
mBluetoothShowDevicesWithoutNames.isChecked() ? "true" : "false");
|
||||
}
|
||||
|
||||
private void updateBluetoothDisableAbsVolumeOptions() {
|
||||
updateSwitchPreference(mBluetoothDisableAbsVolume,
|
||||
SystemProperties.getBoolean(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_PROPERTY, false));
|
||||
@@ -2532,6 +2551,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
writeUSBAudioOptions();
|
||||
} else if (preference == mForceResizable) {
|
||||
writeForceResizableOptions();
|
||||
} else if (preference == mBluetoothShowDevicesWithoutNames) {
|
||||
writeBluetoothShowDevicesWithoutUserFriendlyNameOptions();
|
||||
} else if (preference == mBluetoothDisableAbsVolume) {
|
||||
writeBluetoothDisableAbsVolumeOptions();
|
||||
} else if (preference == mBluetoothEnableInbandRinging) {
|
||||
|
@@ -39,6 +39,8 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -52,6 +54,8 @@ public class BluetoothDevicePreferenceTest {
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
@Mock
|
||||
private DeviceListPreferenceFragment mDeviceListPreferenceFragment;
|
||||
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
@@ -64,7 +68,8 @@ public class BluetoothDevicePreferenceTest {
|
||||
FakeFeatureFactory.setupForTest(mContext);
|
||||
mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
||||
mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice);
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
mDeviceListPreferenceFragment);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -151,4 +156,49 @@ public class BluetoothDevicePreferenceTest {
|
||||
assertThat(mPreference.getIcon()).isEqualTo(
|
||||
mContext.getDrawable(R.drawable.ic_settings_print));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisible_notVisibleThenVisible() {
|
||||
when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(false);
|
||||
final boolean[] humanReadableName = {false};
|
||||
doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice)
|
||||
.hasHumanReadableName();
|
||||
BluetoothDevicePreference preference =
|
||||
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
mDeviceListPreferenceFragment);
|
||||
assertThat(preference.isVisible()).isFalse();
|
||||
humanReadableName[0] = true;
|
||||
preference.onDeviceAttributesChanged();
|
||||
assertThat(preference.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisible_visibleThenNotVisible() {
|
||||
when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(false);
|
||||
final boolean[] humanReadableName = {true};
|
||||
doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice)
|
||||
.hasHumanReadableName();
|
||||
BluetoothDevicePreference preference =
|
||||
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
mDeviceListPreferenceFragment);
|
||||
assertThat(preference.isVisible()).isTrue();
|
||||
humanReadableName[0] = false;
|
||||
preference.onDeviceAttributesChanged();
|
||||
assertThat(preference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisible_alwaysVisibleWhenEnabled() {
|
||||
when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(true);
|
||||
final boolean[] humanReadableName = {true};
|
||||
doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice)
|
||||
.hasHumanReadableName();
|
||||
BluetoothDevicePreference preference =
|
||||
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
mDeviceListPreferenceFragment);
|
||||
assertThat(preference.isVisible()).isTrue();
|
||||
humanReadableName[0] = false;
|
||||
preference.onDeviceAttributesChanged();
|
||||
assertThat(preference.isVisible()).isTrue();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user