Merge "[Settings] Avoid NPE if BT device is changed by framework." into udc-dev
diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
index 666a738..4679eb2 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -57,7 +57,9 @@
import java.io.IOException;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@@ -92,6 +94,7 @@
@VisibleForTesting
final Map<String, Bitmap> mIconCache;
private CachedBluetoothDevice mCachedDevice;
+ private Set<BluetoothDevice> mBluetoothDevices;
@VisibleForTesting
BluetoothAdapter mBluetoothAdapter;
@VisibleForTesting
@@ -141,23 +144,13 @@
if (!isAvailable()) {
return;
}
- mIsRegisterCallback = true;
- mCachedDevice.registerCallback(this);
- mBluetoothAdapter.addOnMetadataChangedListener(mCachedDevice.getDevice(),
- mContext.getMainExecutor(), mMetadataListener);
-
+ registerBluetoothDevice();
refresh();
}
@Override
public void onStop() {
- if (!mIsRegisterCallback) {
- return;
- }
- mCachedDevice.unregisterCallback(this);
- mBluetoothAdapter.removeOnMetadataChangedListener(mCachedDevice.getDevice(),
- mMetadataListener);
- mIsRegisterCallback = false;
+ unRegisterBluetoothDevice();
}
@Override
@@ -175,6 +168,40 @@
mCachedDevice = cachedBluetoothDevice;
}
+ private void registerBluetoothDevice() {
+ if (mBluetoothDevices == null) {
+ mBluetoothDevices = new HashSet<>();
+ }
+ mBluetoothDevices.clear();
+ if (mCachedDevice.getDevice() != null) {
+ mBluetoothDevices.add(mCachedDevice.getDevice());
+ }
+ mCachedDevice.getMemberDevice().forEach(cbd -> {
+ if (cbd != null) {
+ mBluetoothDevices.add(cbd.getDevice());
+ }
+ });
+ if (mBluetoothDevices.isEmpty()) {
+ Log.d(TAG, "No BT devcie to register.");
+ return;
+ }
+ mCachedDevice.registerCallback(this);
+ mBluetoothDevices.forEach(bd ->
+ mBluetoothAdapter.addOnMetadataChangedListener(bd,
+ mContext.getMainExecutor(), mMetadataListener));
+ }
+
+ private void unRegisterBluetoothDevice() {
+ if (mBluetoothDevices == null || mBluetoothDevices.isEmpty()) {
+ Log.d(TAG, "No BT devcie to unregister.");
+ return;
+ }
+ mCachedDevice.unregisterCallback(this);
+ mBluetoothDevices.forEach(bd -> mBluetoothAdapter.removeOnMetadataChangedListener(bd,
+ mMetadataListener));
+ mBluetoothDevices.clear();
+ }
+
@VisibleForTesting
void refresh() {
if (mLayoutPreference != null && mCachedDevice != null) {
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
index e334af5..2c9fb99 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
@@ -56,6 +56,9 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.HashSet;
+import java.util.Set;
+
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
public class AdvancedBluetoothDetailsHeaderControllerTest {
@@ -380,40 +383,68 @@
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
+ Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
+ when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
mController.onStart();
+ verify(mCachedDevice).registerCallback(mController);
verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
mContext.getMainExecutor(), mController.mMetadataListener);
}
@Test
- public void onStop_isRegisterCallback_unregisterCallback() {
- mController.mIsRegisterCallback = true;
-
- mController.onStop();
-
- verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
- mController.mMetadataListener);
- }
-
- @Test
- public void onStart_notAvailable_registerCallback() {
+ public void onStart_notAvailable_notNeedToRegisterCallback() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
mController.onStart();
+ verify(mCachedDevice, never()).registerCallback(mController);
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
mContext.getMainExecutor(), mController.mMetadataListener);
}
@Test
- public void onStop_notRegisterCallback_unregisterCallback() {
- mController.mIsRegisterCallback = false;
+ public void onStart_isAvailableButNoBluetoothDevice_notNeedToRegisterCallback() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+ .thenReturn("true".getBytes());
+ when(mCachedDevice.getDevice()).thenReturn(null);
+ Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
+ when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
+
+ mController.onStart();
+
+ verify(mCachedDevice, never()).registerCallback(mController);
+ verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
+ mContext.getMainExecutor(), mController.mMetadataListener);
+ }
+
+ @Test
+ public void onStop_availableAndHasBluetoothDevice_unregisterCallback() {
+ onStart_isAvailable_registerCallback();
mController.onStop();
+ verify(mCachedDevice).unregisterCallback(mController);
+ verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
+ mController.mMetadataListener);
+ }
+
+ @Test
+ public void onStop_noBluetoothDevice_noNeedToUnregisterCallback() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+ .thenReturn("true".getBytes());
+ when(mCachedDevice.getDevice()).thenReturn(null);
+
+ mController.onStart();
+ mController.onStop();
+
+ verify(mCachedDevice, never()).unregisterCallback(mController);
verify(mBluetoothAdapter, never()).removeOnMetadataChangedListener(mBluetoothDevice,
mController.mMetadataListener);
}