diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java index 2e4654c3994..d927121e931 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java @@ -52,8 +52,7 @@ import java.lang.annotation.RetentionPolicy; * BluetoothDevicePreference is the preference type used to display each remote * Bluetooth device in the Bluetooth Settings screen. */ -public final class BluetoothDevicePreference extends GearPreference implements - CachedBluetoothDevice.Callback { +public final class BluetoothDevicePreference extends GearPreference { private static final String TAG = "BluetoothDevicePref"; private static int sDimAlpha = Integer.MIN_VALUE; @@ -77,10 +76,20 @@ public final class BluetoothDevicePreference extends GearPreference implements private AlertDialog mDisconnectDialog; private String contentDescription = null; private boolean mHideSecondTarget = false; + private boolean mIsCallbackRemoved = false; @VisibleForTesting boolean mNeedNotifyHierarchyChanged = false; /* Talk-back descriptions for various BT icons */ Resources mResources; + final BluetoothDevicePreferenceCallback mCallback; + + private class BluetoothDevicePreferenceCallback implements CachedBluetoothDevice.Callback { + + @Override + public void onDeviceAttributesChanged() { + onPreferenceAttributesChanged(); + } + } public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice, boolean showDeviceWithoutNames, @SortType int type) { @@ -96,10 +105,12 @@ public final class BluetoothDevicePreference extends GearPreference implements } mCachedDevice = cachedDevice; + mCallback = new BluetoothDevicePreferenceCallback(); + mCachedDevice.registerCallback(mCallback); mCurrentTime = System.currentTimeMillis(); mType = type; - onDeviceAttributesChanged(); + onPreferenceAttributesChanged(); } public void setNeedNotifyHierarchyChanged(boolean needNotifyHierarchyChanged) { @@ -126,6 +137,10 @@ public final class BluetoothDevicePreference extends GearPreference implements @Override protected void onPrepareForRemoval() { super.onPrepareForRemoval(); + if (!mIsCallbackRemoved) { + mCachedDevice.unregisterCallback(mCallback); + mIsCallbackRemoved = true; + } if (mDisconnectDialog != null) { mDisconnectDialog.dismiss(); mDisconnectDialog = null; @@ -135,13 +150,20 @@ public final class BluetoothDevicePreference extends GearPreference implements @Override public void onAttached() { super.onAttached(); - mCachedDevice.registerCallback(this); + if (mIsCallbackRemoved) { + mCachedDevice.registerCallback(mCallback); + mIsCallbackRemoved = false; + } + onPreferenceAttributesChanged(); } @Override public void onDetached() { super.onDetached(); - mCachedDevice.unregisterCallback(this); + if (!mIsCallbackRemoved) { + mCachedDevice.unregisterCallback(mCallback); + mIsCallbackRemoved = true; + } } public CachedBluetoothDevice getBluetoothDevice() { @@ -152,7 +174,7 @@ public final class BluetoothDevicePreference extends GearPreference implements mHideSecondTarget = hideSecondTarget; } - public void onDeviceAttributesChanged() { + private void onPreferenceAttributesChanged() { /* * The preference framework takes care of making sure the value has * changed before proceeding. It will also call notifyChanged() if diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java index f12e06e336b..c87cc252d99 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java @@ -17,10 +17,12 @@ package com.android.settings.bluetooth; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,7 +37,6 @@ import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -import com.android.settingslib.testutils.DrawableTestHelper; import org.junit.Before; import org.junit.Test; @@ -261,4 +262,19 @@ public class BluetoothDevicePreferenceTest { assertThat(mPreferenceList.get(2).getCachedDevice().getAddress()) .isEqualTo(preference3.getCachedDevice().getAddress()); } + + @Test + public void onAttached_callbackNotRemoved_doNotRegisterCallback() { + mPreference.onAttached(); + + verify(mCachedBluetoothDevice, never()).unregisterCallback(any()); + } + + @Test + public void onAttached_callbackRemoved_registerCallback() { + mPreference.onPrepareForRemoval(); + mPreference.onAttached(); + + verify(mCachedBluetoothDevice, times(2)).registerCallback(any()); + } }