Loading src/com/android/settings/bluetooth/BluetoothDevicePreference.java +53 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.bluetooth; import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.DialogInterface; Loading Loading @@ -48,6 +49,8 @@ import com.android.settingslib.utils.ThreadUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashSet; import java.util.Set; import java.util.concurrent.RejectedExecutionException; /** Loading @@ -71,6 +74,10 @@ public final class BluetoothDevicePreference extends GearPreference { private final CachedBluetoothDevice mCachedDevice; private final UserManager mUserManager; private Set<BluetoothDevice> mBluetoothDevices; @VisibleForTesting BluetoothAdapter mBluetoothAdapter; private final boolean mShowDevicesWithoutNames; private final long mCurrentTime; private final int mType; Loading @@ -78,12 +85,23 @@ public final class BluetoothDevicePreference extends GearPreference { private AlertDialog mDisconnectDialog; private String contentDescription = null; private boolean mHideSecondTarget = false; private boolean mIsCallbackRemoved = false; private boolean mIsCallbackRemoved = true; @VisibleForTesting boolean mNeedNotifyHierarchyChanged = false; /* Talk-back descriptions for various BT icons */ Resources mResources; final BluetoothDevicePreferenceCallback mCallback; @VisibleForTesting final BluetoothAdapter.OnMetadataChangedListener mMetadataListener = new BluetoothAdapter.OnMetadataChangedListener() { @Override public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { Log.d(TAG, String.format("Metadata updated in Device %s: %d = %s.", device.getAnonymizedAddress(), key, value == null ? null : new String(value))); onPreferenceAttributesChanged(); } }; private class BluetoothDevicePreferenceCallback implements CachedBluetoothDevice.Callback { Loading @@ -98,6 +116,7 @@ public final class BluetoothDevicePreference extends GearPreference { super(context, null); mResources = getContext().getResources(); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mShowDevicesWithoutNames = showDeviceWithoutNames; if (sDimAlpha == Integer.MIN_VALUE) { Loading @@ -108,7 +127,6 @@ public final class BluetoothDevicePreference extends GearPreference { mCachedDevice = cachedDevice; mCallback = new BluetoothDevicePreferenceCallback(); mCachedDevice.registerCallback(mCallback); mCurrentTime = System.currentTimeMillis(); mType = type; Loading Loading @@ -141,6 +159,7 @@ public final class BluetoothDevicePreference extends GearPreference { super.onPrepareForRemoval(); if (!mIsCallbackRemoved) { mCachedDevice.unregisterCallback(mCallback); unregisterMetadataChangedListener(); mIsCallbackRemoved = true; } if (mDisconnectDialog != null) { Loading @@ -154,6 +173,7 @@ public final class BluetoothDevicePreference extends GearPreference { super.onAttached(); if (mIsCallbackRemoved) { mCachedDevice.registerCallback(mCallback); registerMetadataChangedListener(); mIsCallbackRemoved = false; } onPreferenceAttributesChanged(); Loading @@ -164,10 +184,41 @@ public final class BluetoothDevicePreference extends GearPreference { super.onDetached(); if (!mIsCallbackRemoved) { mCachedDevice.unregisterCallback(mCallback); unregisterMetadataChangedListener(); mIsCallbackRemoved = true; } } private void registerMetadataChangedListener() { if (mBluetoothDevices == null) { mBluetoothDevices = new HashSet<>(); } mBluetoothDevices.clear(); if (mCachedDevice.getDevice() != null) { mBluetoothDevices.add(mCachedDevice.getDevice()); } for (CachedBluetoothDevice cbd : mCachedDevice.getMemberDevice()) { mBluetoothDevices.add(cbd.getDevice()); } if (mBluetoothDevices.isEmpty()) { Log.d(TAG, "No BT device to register."); return; } mBluetoothDevices.forEach(bd -> mBluetoothAdapter.addOnMetadataChangedListener(bd, getContext().getMainExecutor(), mMetadataListener)); } private void unregisterMetadataChangedListener() { if (mBluetoothDevices == null || mBluetoothDevices.isEmpty()) { Log.d(TAG, "No BT device to unregister."); return; } mBluetoothDevices.forEach( bd -> mBluetoothAdapter.removeOnMetadataChangedListener(bd, mMetadataListener)); mBluetoothDevices.clear(); } public CachedBluetoothDevice getBluetoothDevice() { return mCachedDevice; } Loading tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java +27 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.graphics.drawable.Drawable; Loading Loading @@ -77,7 +78,17 @@ public class BluetoothDevicePreferenceTest { @Mock private CachedBluetoothDevice mCachedDevice3; @Mock private BluetoothDevice mBluetoothDevice; @Mock private BluetoothDevice mBluetoothDevice1; @Mock private BluetoothDevice mBluetoothDevice2; @Mock private BluetoothDevice mBluetoothDevice3; @Mock private Drawable mDrawable; @Mock private BluetoothAdapter mBluetoothAdapter; private FakeFeatureFactory mFakeFeatureFactory; private MetricsFeatureProvider mMetricsFeatureProvider; Loading @@ -94,17 +105,22 @@ public class BluetoothDevicePreferenceTest { when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS); when(mCachedBluetoothDevice.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); when(mCachedDevice1.getAddress()).thenReturn(MAC_ADDRESS_2); when(mCachedDevice1.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1); when(mCachedDevice2.getAddress()).thenReturn(MAC_ADDRESS_3); when(mCachedDevice2.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice2.getDevice()).thenReturn(mBluetoothDevice2); when(mCachedDevice3.getAddress()).thenReturn(MAC_ADDRESS_4); when(mCachedDevice3.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice3.getDevice()).thenReturn(mBluetoothDevice3); mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT); mPreference.mBluetoothAdapter = mBluetoothAdapter; } @Test Loading Loading @@ -279,15 +295,25 @@ public class BluetoothDevicePreferenceTest { @Test public void onAttached_callbackNotRemoved_doNotRegisterCallback() { mPreference.onAttached(); // After the onAttached(), the callback is registered. verify(mCachedBluetoothDevice, never()).unregisterCallback(any()); // If it goes to the onAttached() again, then it do not register again, since the // callback is not removed. mPreference.onAttached(); verify(mCachedBluetoothDevice, times(1)).registerCallback(any()); verify(mBluetoothAdapter, times(1)).addOnMetadataChangedListener(any(), any(), any()); } @Test public void onAttached_callbackRemoved_registerCallback() { mPreference.onAttached(); mPreference.onPrepareForRemoval(); mPreference.onAttached(); verify(mCachedBluetoothDevice, times(1)).unregisterCallback(any()); verify(mCachedBluetoothDevice, times(2)).registerCallback(any()); verify(mBluetoothAdapter, times(2)).addOnMetadataChangedListener(any(), any(), any()); } } Loading
src/com/android/settings/bluetooth/BluetoothDevicePreference.java +53 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.bluetooth; import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.DialogInterface; Loading Loading @@ -48,6 +49,8 @@ import com.android.settingslib.utils.ThreadUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashSet; import java.util.Set; import java.util.concurrent.RejectedExecutionException; /** Loading @@ -71,6 +74,10 @@ public final class BluetoothDevicePreference extends GearPreference { private final CachedBluetoothDevice mCachedDevice; private final UserManager mUserManager; private Set<BluetoothDevice> mBluetoothDevices; @VisibleForTesting BluetoothAdapter mBluetoothAdapter; private final boolean mShowDevicesWithoutNames; private final long mCurrentTime; private final int mType; Loading @@ -78,12 +85,23 @@ public final class BluetoothDevicePreference extends GearPreference { private AlertDialog mDisconnectDialog; private String contentDescription = null; private boolean mHideSecondTarget = false; private boolean mIsCallbackRemoved = false; private boolean mIsCallbackRemoved = true; @VisibleForTesting boolean mNeedNotifyHierarchyChanged = false; /* Talk-back descriptions for various BT icons */ Resources mResources; final BluetoothDevicePreferenceCallback mCallback; @VisibleForTesting final BluetoothAdapter.OnMetadataChangedListener mMetadataListener = new BluetoothAdapter.OnMetadataChangedListener() { @Override public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { Log.d(TAG, String.format("Metadata updated in Device %s: %d = %s.", device.getAnonymizedAddress(), key, value == null ? null : new String(value))); onPreferenceAttributesChanged(); } }; private class BluetoothDevicePreferenceCallback implements CachedBluetoothDevice.Callback { Loading @@ -98,6 +116,7 @@ public final class BluetoothDevicePreference extends GearPreference { super(context, null); mResources = getContext().getResources(); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mShowDevicesWithoutNames = showDeviceWithoutNames; if (sDimAlpha == Integer.MIN_VALUE) { Loading @@ -108,7 +127,6 @@ public final class BluetoothDevicePreference extends GearPreference { mCachedDevice = cachedDevice; mCallback = new BluetoothDevicePreferenceCallback(); mCachedDevice.registerCallback(mCallback); mCurrentTime = System.currentTimeMillis(); mType = type; Loading Loading @@ -141,6 +159,7 @@ public final class BluetoothDevicePreference extends GearPreference { super.onPrepareForRemoval(); if (!mIsCallbackRemoved) { mCachedDevice.unregisterCallback(mCallback); unregisterMetadataChangedListener(); mIsCallbackRemoved = true; } if (mDisconnectDialog != null) { Loading @@ -154,6 +173,7 @@ public final class BluetoothDevicePreference extends GearPreference { super.onAttached(); if (mIsCallbackRemoved) { mCachedDevice.registerCallback(mCallback); registerMetadataChangedListener(); mIsCallbackRemoved = false; } onPreferenceAttributesChanged(); Loading @@ -164,10 +184,41 @@ public final class BluetoothDevicePreference extends GearPreference { super.onDetached(); if (!mIsCallbackRemoved) { mCachedDevice.unregisterCallback(mCallback); unregisterMetadataChangedListener(); mIsCallbackRemoved = true; } } private void registerMetadataChangedListener() { if (mBluetoothDevices == null) { mBluetoothDevices = new HashSet<>(); } mBluetoothDevices.clear(); if (mCachedDevice.getDevice() != null) { mBluetoothDevices.add(mCachedDevice.getDevice()); } for (CachedBluetoothDevice cbd : mCachedDevice.getMemberDevice()) { mBluetoothDevices.add(cbd.getDevice()); } if (mBluetoothDevices.isEmpty()) { Log.d(TAG, "No BT device to register."); return; } mBluetoothDevices.forEach(bd -> mBluetoothAdapter.addOnMetadataChangedListener(bd, getContext().getMainExecutor(), mMetadataListener)); } private void unregisterMetadataChangedListener() { if (mBluetoothDevices == null || mBluetoothDevices.isEmpty()) { Log.d(TAG, "No BT device to unregister."); return; } mBluetoothDevices.forEach( bd -> mBluetoothAdapter.removeOnMetadataChangedListener(bd, mMetadataListener)); mBluetoothDevices.clear(); } public CachedBluetoothDevice getBluetoothDevice() { return mCachedDevice; } Loading
tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java +27 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.graphics.drawable.Drawable; Loading Loading @@ -77,7 +78,17 @@ public class BluetoothDevicePreferenceTest { @Mock private CachedBluetoothDevice mCachedDevice3; @Mock private BluetoothDevice mBluetoothDevice; @Mock private BluetoothDevice mBluetoothDevice1; @Mock private BluetoothDevice mBluetoothDevice2; @Mock private BluetoothDevice mBluetoothDevice3; @Mock private Drawable mDrawable; @Mock private BluetoothAdapter mBluetoothAdapter; private FakeFeatureFactory mFakeFeatureFactory; private MetricsFeatureProvider mMetricsFeatureProvider; Loading @@ -94,17 +105,22 @@ public class BluetoothDevicePreferenceTest { when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS); when(mCachedBluetoothDevice.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); when(mCachedDevice1.getAddress()).thenReturn(MAC_ADDRESS_2); when(mCachedDevice1.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1); when(mCachedDevice2.getAddress()).thenReturn(MAC_ADDRESS_3); when(mCachedDevice2.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice2.getDevice()).thenReturn(mBluetoothDevice2); when(mCachedDevice3.getAddress()).thenReturn(MAC_ADDRESS_4); when(mCachedDevice3.getDrawableWithDescription()) .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION)); when(mCachedDevice3.getDevice()).thenReturn(mBluetoothDevice3); mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT); mPreference.mBluetoothAdapter = mBluetoothAdapter; } @Test Loading Loading @@ -279,15 +295,25 @@ public class BluetoothDevicePreferenceTest { @Test public void onAttached_callbackNotRemoved_doNotRegisterCallback() { mPreference.onAttached(); // After the onAttached(), the callback is registered. verify(mCachedBluetoothDevice, never()).unregisterCallback(any()); // If it goes to the onAttached() again, then it do not register again, since the // callback is not removed. mPreference.onAttached(); verify(mCachedBluetoothDevice, times(1)).registerCallback(any()); verify(mBluetoothAdapter, times(1)).addOnMetadataChangedListener(any(), any(), any()); } @Test public void onAttached_callbackRemoved_registerCallback() { mPreference.onAttached(); mPreference.onPrepareForRemoval(); mPreference.onAttached(); verify(mCachedBluetoothDevice, times(1)).unregisterCallback(any()); verify(mCachedBluetoothDevice, times(2)).registerCallback(any()); verify(mBluetoothAdapter, times(2)).addOnMetadataChangedListener(any(), any(), any()); } }