From 44de3a076d8903078c96e6b38564a16832996310 Mon Sep 17 00:00:00 2001 From: ryanywlin Date: Wed, 2 May 2018 15:15:37 +0800 Subject: [PATCH] Add Bluetooth callback for device connection state changed With the new Multi-A2DP/HFP support, need to add profile connection state changed callback for every BT device connect/disconnect to profile. Bug: 76447449 Test: make RunSettingsLibRoboTests ROBOTEST_FILTER=LocalBluetoothProfileManagerTest -j28 Test: make RunSettingsLibRoboTests ROBOTEST_FILTER=BluetoothEventManagerTest -j28 Change-Id: Iaaec369e8d10f9b1270491632fb5c91de1e28571 --- .../settingslib/bluetooth/A2dpProfile.java | 5 + .../bluetooth/A2dpSinkProfile.java | 5 + .../bluetooth/BluetoothCallback.java | 3 + .../bluetooth/BluetoothEventManager.java | 9 + .../settingslib/bluetooth/HeadsetProfile.java | 5 + .../bluetooth/HearingAidProfile.java | 5 + .../bluetooth/HfpClientProfile.java | 5 + .../bluetooth/HidDeviceProfile.java | 5 + .../settingslib/bluetooth/HidProfile.java | 5 + .../bluetooth/LocalBluetoothProfile.java | 2 + .../LocalBluetoothProfileManager.java | 2 + .../bluetooth/MapClientProfile.java | 5 + .../settingslib/bluetooth/MapProfile.java | 5 + .../settingslib/bluetooth/OppProfile.java | 5 + .../settingslib/bluetooth/PanProfile.java | 5 + .../bluetooth/PbapClientProfile.java | 5 + .../bluetooth/PbapServerProfile.java | 5 + .../settingslib/bluetooth/SapProfile.java | 5 + .../bluetooth/BluetoothEventManagerTest.java | 21 +++ .../LocalBluetoothProfileManagerTest.java | 173 +++++++++++++++++- 20 files changed, 274 insertions(+), 6 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 6b9902425bcb0..24037a6ba5b4b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -94,6 +94,11 @@ public class A2dpProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.A2DP; + } + A2dpProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java index a1c8de566578e..ac5f5373d8ec1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java @@ -85,6 +85,11 @@ final class A2dpSinkProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.A2DP_SINK; + } + A2dpSinkProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java index bab59f1f1c32c..c7f8c205ec6d0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java @@ -30,4 +30,7 @@ public interface BluetoothCallback { void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state); void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile); void onAudioModeChanged(); + default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, + int state, int bluetoothProfile) { + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index e7d7ab39b6c45..4e9e566b0d879 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -497,4 +497,13 @@ public class BluetoothEventManager { } } } + + void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state, + int bluetoothProfile) { + synchronized (mCallbacks) { + for (BluetoothCallback callback : mCallbacks) { + callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); + } + } + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java index ad813368fbd06..f7518cd63c5c0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java @@ -92,6 +92,11 @@ public class HeadsetProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.HEADSET; + } + HeadsetProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java index da2ae7f8a3207..a0dfb5d151778 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java @@ -93,6 +93,11 @@ public class HearingAidProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.HEARING_AID; + } + HearingAidProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java index 169aac9eb60ff..d0819098deb1e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java @@ -92,6 +92,11 @@ final class HfpClientProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.HEADSET_CLIENT; + } + HfpClientProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java index 941964a57eb44..45ec4a1e554dc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java @@ -97,6 +97,11 @@ public class HidDeviceProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.HID_DEVICE; + } + @Override public boolean isConnectable() { return true; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java index 93c4017fdaf86..93e5621793996 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java @@ -80,6 +80,11 @@ public class HidProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.HID_HOST; + } + HidProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java index abcb989802e9c..0447f378fca18 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java @@ -49,6 +49,8 @@ public interface LocalBluetoothProfile { boolean isProfileReady(); + int getProfileId(); + /** Display order for device profile settings. */ int getOrdinal(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 0715d6927d2ae..62f8724870e3c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -375,6 +375,8 @@ public class LocalBluetoothProfileManager { } } + mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState, + mProfile.getProfileId()); cachedDevice.onProfileStateChanged(mProfile, newState); cachedDevice.refresh(); } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java index 6efa4687d9134..ad0d8ba7ebab2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java @@ -94,6 +94,11 @@ public final class MapClientProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.MAP_CLIENT; + } + MapClientProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java index 0b45f5137026f..aa7a7af582a75 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java @@ -93,6 +93,11 @@ public class MapProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.MAP; + } + MapProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java index 31e675c2355bd..e5c0b147f97b5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java @@ -67,6 +67,11 @@ final class OppProfile implements LocalBluetoothProfile { return true; } + @Override + public int getProfileId() { + return BluetoothProfile.OPP; + } + public String toString() { return NAME; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java index e077a6763755e..b18b19b1e2445 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java @@ -69,6 +69,11 @@ public class PanProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.PAN; + } + PanProfile(Context context, LocalBluetoothAdapter adapter) { mLocalAdapter = adapter; mLocalAdapter.getProfileProxy(context, new PanServiceListener(), diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java index 28137ff64fb5b..b735c23e966fd 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java @@ -100,6 +100,11 @@ public final class PbapClientProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.PBAP_CLIENT; + } + PbapClientProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java index 58465f299578c..e9d8cb5a4b2bb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java @@ -71,6 +71,11 @@ public class PbapServerProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.PBAP; + } + PbapServerProfile(Context context) { BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener()); } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java index 25c53e693a56c..93e6be6559f6d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java @@ -91,6 +91,11 @@ final class SapProfile implements LocalBluetoothProfile { return mIsProfileReady; } + @Override + public int getProfileId() { + return BluetoothProfile.SAP; + } + SapProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java index d1e37f6e945b4..466980c38e8ec 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java @@ -15,13 +15,17 @@ */ package com.android.settingslib.bluetooth; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,6 +43,8 @@ public class BluetoothEventManagerTest { private CachedBluetoothDeviceManager mCachedDeviceManager; @Mock private BluetoothCallback mBluetoothCallback; + @Mock + private CachedBluetoothDevice mCachedBluetoothDevice; private Context mContext; private Intent mIntent; @@ -78,4 +84,19 @@ public class BluetoothEventManagerTest { verify(mBluetoothCallback).onAudioModeChanged(); } + + /** + * dispatchProfileConnectionStateChanged should dispatch to onProfileConnectionStateChanged + * callback. + */ + @Test + public void dispatchProfileConnectionStateChanged_registerCallback_shouldDispatchCallback() { + mBluetoothEventManager.registerCallback(mBluetoothCallback); + + mBluetoothEventManager.dispatchProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); + + verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java index 88c7a556d51e7..d342bc8784771 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java @@ -18,12 +18,23 @@ package com.android.settingslib.bluetooth; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHearingAid; +import android.bluetooth.BluetoothPan; +import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; +import android.content.Intent; import android.os.ParcelUuid; import java.util.ArrayList; @@ -41,18 +52,29 @@ import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) @Config(resourceDir = "../../res") public class LocalBluetoothProfileManagerTest { - @Mock private CachedBluetoothDeviceManager mDeviceManager; - @Mock private BluetoothEventManager mEventManager; - @Mock private LocalBluetoothAdapter mAdapter; - @Mock private BluetoothDevice mDevice; + @Mock + private CachedBluetoothDeviceManager mDeviceManager; + @Mock + private BluetoothEventManager mEventManager; + @Mock + private LocalBluetoothAdapter mAdapter; + @Mock + private BluetoothDevice mDevice; + @Mock + private CachedBluetoothDevice mCachedBluetoothDevice; + private Context mContext; private LocalBluetoothProfileManager mProfileManager; + private Intent mIntent; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); + mEventManager = spy(new BluetoothEventManager(mAdapter, + mDeviceManager, mContext)); when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); + when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice); } /** @@ -74,7 +96,7 @@ public class LocalBluetoothProfileManagerTest { public void updateLocalProfiles_addA2dpToLocalProfiles() { mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager); - when(mAdapter.getUuids()).thenReturn(new ParcelUuid[] {BluetoothUuid.AudioSource}); + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource}); assertThat(mProfileManager.getA2dpProfile()).isNull(); assertThat(mProfileManager.getHeadsetProfile()).isNull(); @@ -104,4 +126,143 @@ public class LocalBluetoothProfileManagerTest { assertThat(profiles.contains(mProfileManager.getHidProfile())).isTrue(); assertThat(removedProfiles.contains(mProfileManager.getHidProfile())).isFalse(); } + + /** + * Verify BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to + * profile connection state changed callback + */ + @Test + public void stateChangedHandler_receiveA2dpConnectionStateChanged_shouldDispatchCallback() { + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource}); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mEventManager).dispatchProfileConnectionStateChanged( + mCachedBluetoothDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); + } + + /** + * Verify BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to + * profile connection state changed callback + */ + @Test + public void stateChangedHandler_receiveHeadsetConnectionStateChanged_shouldDispatchCallback() { + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.Handsfree_AG}); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEADSET); + } + + /** + * Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to + * profile connection state changed callback + */ + @Test + public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() { + ArrayList supportProfiles = new ArrayList<>(); + supportProfiles.add(BluetoothProfile.HEARING_AID); + when(mAdapter.getSupportedProfiles()).thenReturn(supportProfiles); + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.HearingAid}); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID); + } + + /** + * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuid will dispatch to + * profile connection state changed callback + */ + @Test + public void stateChangedHandler_receivePanConnectionStateChanged_shouldNotDispatchCallback() { + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource}); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mEventManager).dispatchProfileConnectionStateChanged( + any(CachedBluetoothDevice.class), anyInt(), anyInt()); + } + + /** + * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent without uuids will not dispatch to + * handler and refresh CachedBluetoothDevice + */ + @Test + public void stateChangedHandler_receivePanConnectionStateChangedWithoutUuid_shouldNotRefresh() { + when(mAdapter.getUuids()).thenReturn(null); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mCachedBluetoothDevice).refresh(); + } + + /** + * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to + * handler and refresh CachedBluetoothDevice + */ + @Test + public void stateChangedHandler_receivePanConnectionStateChangedWithUuids_shouldRefresh() { + when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource}); + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + // Refer to BluetoothControllerImpl, it will call setReceiverHandler after + // LocalBluetoothProfileManager created. + mEventManager.setReceiverHandler(null); + mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mCachedBluetoothDevice).refresh(); + } }