Fix bluetooth settings force close

This CL include following change:

- Add null check of cacedBluetoothDevice, cachedBluetooth could be null
  if the input BluetoothDevice can't found in
  CachedBluetoothDeviceManager.
- Move addPreference() and removePreference() to update() method,
  because update() will be called to update UI when recevice Bluetooth
  device change event.
- Add test case to test CachedBluetoothDevice null check.

Bug: 149068434
Test: make -j42 RunSettingsRoboTests
Change-Id: I90016bf1175925821b0d9b634c62cf796289a734
This commit is contained in:
hughchen
2020-02-07 17:48:39 +08:00
parent 978b19ec63
commit 1b3f570a67
2 changed files with 106 additions and 10 deletions

View File

@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.connecteddevice.DevicePreferenceCallback;
@@ -38,24 +39,25 @@ public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
private static final String PREF_KEY = "saved_bt"; private static final String PREF_KEY = "saved_bt";
@VisibleForTesting
BluetoothAdapter mBluetoothAdapter;
public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment, public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback) { DevicePreferenceCallback devicePreferenceCallback) {
super(context, fragment, devicePreferenceCallback); super(context, fragment, devicePreferenceCallback);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
} }
@Override @Override
public void forceUpdate() { public void forceUpdate() {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) { if (mBluetoothAdapter.isEnabled()) {
final CachedBluetoothDeviceManager cachedManager = final CachedBluetoothDeviceManager cachedManager =
mLocalManager.getCachedDeviceManager(); mLocalManager.getCachedDeviceManager();
for (BluetoothDevice device for (BluetoothDevice device : mBluetoothAdapter.getMostRecentlyConnectedDevices()) {
: BluetoothAdapter.getDefaultAdapter().getMostRecentlyConnectedDevices()) {
final CachedBluetoothDevice cachedDevice = cachedManager.findDevice(device); final CachedBluetoothDevice cachedDevice = cachedManager.findDevice(device);
if (isFilterMatched(cachedDevice)) { if (cachedDevice != null) {
// Add the preference if it is new one update(cachedDevice);
addPreference(cachedDevice, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
} else {
removePreference(cachedDevice);
} }
} }
} else { } else {
@@ -63,6 +65,16 @@ public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
} }
} }
@Override
public void update(CachedBluetoothDevice cachedDevice) {
if (isFilterMatched(cachedDevice)) {
// Add the preference if it is new one
addPreference(cachedDevice, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
} else {
removePreference(cachedDevice);
}
}
@Override @Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) { public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
final BluetoothDevice device = cachedDevice.getDevice(); final BluetoothDevice device = cachedDevice.getDevice();

View File

@@ -18,10 +18,12 @@ package com.android.settings.bluetooth;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.content.Context; import android.content.Context;
@@ -30,6 +32,8 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -40,6 +44,10 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class}) @Config(shadows = {ShadowBluetoothAdapter.class})
public class SavedBluetoothDeviceUpdaterTest { public class SavedBluetoothDeviceUpdaterTest {
@@ -54,6 +62,12 @@ public class SavedBluetoothDeviceUpdaterTest {
private CachedBluetoothDevice mCachedBluetoothDevice; private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock @Mock
private BluetoothDevice mBluetoothDevice; private BluetoothDevice mBluetoothDevice;
@Mock
private BluetoothAdapter mBluetoothAdapter;
@Mock
private CachedBluetoothDeviceManager mDeviceManager;
@Mock
private LocalBluetoothManager mBluetoothManager;
private Context mContext; private Context mContext;
private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater; private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -72,6 +86,8 @@ public class SavedBluetoothDeviceUpdaterTest {
mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext, mDashboardFragment, mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext, mDashboardFragment,
mDevicePreferenceCallback)); mDevicePreferenceCallback));
mBluetoothDeviceUpdater.setPrefContext(mContext); mBluetoothDeviceUpdater.setPrefContext(mContext);
mBluetoothDeviceUpdater.mBluetoothAdapter = mBluetoothAdapter;
mBluetoothDeviceUpdater.mLocalManager = mBluetoothManager;
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
false, BluetoothDevicePreference.SortType.TYPE_DEFAULT); false, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
@@ -85,7 +101,8 @@ public class SavedBluetoothDeviceUpdaterTest {
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
} }
@Test @Test
@@ -115,7 +132,8 @@ public class SavedBluetoothDeviceUpdaterTest {
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP); BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP);
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
} }
@Test @Test
@@ -124,4 +142,70 @@ public class SavedBluetoothDeviceUpdaterTest {
verify(mCachedBluetoothDevice).connect(); verify(mCachedBluetoothDevice).connect();
} }
@Test
public void forceUpdate_findCachedBluetoothDeviceIsMatched_addPreference() {
final List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
bluetoothDevices.add(mBluetoothDevice);
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices);
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(false);
mBluetoothDeviceUpdater.forceUpdate();
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
}
@Test
public void forceUpdate_findCachedBluetoothDeviceNotMatched_removePreference() {
final List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
bluetoothDevices.add(mBluetoothDevice);
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices);
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(true);
mBluetoothDeviceUpdater.forceUpdate();
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
}
@Test
public void forceUpdate_notFindCachedBluetoothDevice_doNothing() {
final List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
bluetoothDevices.add(mBluetoothDevice);
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices);
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(null);
mBluetoothDeviceUpdater.forceUpdate();
verify(mBluetoothDeviceUpdater, never()).removePreference(mCachedBluetoothDevice);
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
}
@Test
public void forceUpdate_bluetoothAdapterNotEnable_removeAllDevicesFromPreference() {
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
cachedDevices.add(mCachedBluetoothDevice);
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
when(mBluetoothAdapter.isEnabled()).thenReturn(false);
mBluetoothDeviceUpdater.forceUpdate();
verify(mBluetoothDeviceUpdater).removeAllDevicesFromPreference();
}
} }