From 8276d966e9c39c70d6a84c724ef36bf26f298025 Mon Sep 17 00:00:00 2001 From: ryanywlin Date: Sat, 28 Apr 2018 07:26:46 +0800 Subject: [PATCH] Add hearing aid device in audio switch - Add connected hearing aid device to MediaOutputPreferenceController and HandsFreeProfileOutputPreferenceController - Set active device to different profile depend on HisyncId Bug: 78142719 Test: make RunSettingsRoboTests ROBOTEST_FILTER="MediaOutputPreferenceControllerTest" -j28 Test: make RunSettingsRoboTests ROBOTEST_FILTER="HandsFreeProfileOutputPreferenceControllerTest" -j28 Test: make RunSettingsRoboTests ROBOTEST_FILTER="AudioOutputSwitchPreferenceControllerTest" -j28 Change-Id: Ib8fe4f06f8564572dffdce6fcc3f29578bf91bd9 --- .../AudioSwitchPreferenceController.java | 13 +- ...FreeProfileOutputPreferenceController.java | 37 ++- .../MediaOutputPreferenceController.java | 37 ++- ...oOutputSwitchPreferenceControllerTest.java | 180 +++++------ ...ProfileOutputPreferenceControllerTest.java | 292 +++++++++++++++-- .../MediaOutputPreferenceControllerTest.java | 303 +++++++++++++++--- .../testutils/shadow/ShadowAudioManager.java | 8 +- 7 files changed, 664 insertions(+), 206 deletions(-) diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index ea7e8fed768..81479c9e872 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -42,7 +42,6 @@ import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.util.FeatureFlagUtils; -import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.bluetooth.Utils; import com.android.settings.core.BasePreferenceController; @@ -73,12 +72,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont private static final int INVALID_INDEX = -1; + protected final List mConnectedDevices; protected final AudioManager mAudioManager; protected final MediaRouter mMediaRouter; protected final LocalBluetoothProfileManager mProfileManager; protected int mSelectedIndex; protected Preference mPreference; - protected List mConnectedDevices; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; private final LocalBluetoothManager mLocalBluetoothManager; @@ -97,6 +96,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mReceiver = new WiredHeadsetBroadcastReceiver(); mMediaRouterCallback = new MediaRouterCallback(); + mConnectedDevices = new ArrayList<>(); } /** @@ -206,13 +206,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont return (device & mAudioManager.getDevicesForStream(streamType)) != 0; } - protected boolean isOngoingCallStatus() { - final int audioMode = mAudioManager.getMode(); - return audioMode == AudioManager.MODE_RINGTONE - || audioMode == AudioManager.MODE_IN_CALL - || audioMode == AudioManager.MODE_IN_COMMUNICATION; - } - /** * get hands free profile(HFP) connected device */ @@ -308,7 +301,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont int getDefaultDeviceIndex() { // Default device is after all connected devices. - return ArrayUtils.size(mConnectedDevices); + return mConnectedDevices.size(); } void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues, diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java index 6907a4a2aa3..20399133129 100644 --- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java +++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.sound; +import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID; import static android.media.AudioManager.STREAM_VOICE_CALL; import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; @@ -25,12 +26,12 @@ import android.bluetooth.BluetoothDevice; import android.content.Context; import android.support.v7.preference.Preference; -import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settingslib.bluetooth.HeadsetProfile; +import com.android.settingslib.bluetooth.HearingAidProfile; /** - * This class allows switching between HFP-connected BT devices + * This class allows switching between HFP-connected & HAP-connected BT devices * while in on-call state. */ public class HandsFreeProfileOutputPreferenceController extends @@ -57,16 +58,11 @@ public class HandsFreeProfileOutputPreferenceController extends // Ongoing call status, list all the connected devices support hands free profile. // Select current active device. // Disable switch entry if there is no connected device. - mConnectedDevices = null; - BluetoothDevice activeDevice = null; + mConnectedDevices.clear(); + mConnectedDevices.addAll(getConnectedHfpDevices()); + mConnectedDevices.addAll(getConnectedHearingAidDevices()); - final HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile(); - if (headsetProfile != null) { - mConnectedDevices = headsetProfile.getConnectedDevices(); - activeDevice = headsetProfile.getActiveDevice(); - } - - final int numDevices = ArrayUtils.size(mConnectedDevices); + final int numDevices = mConnectedDevices.size(); if (numDevices == 0) { // No connected devices, disable switch entry. mPreference.setVisible(false); @@ -79,7 +75,7 @@ public class HandsFreeProfileOutputPreferenceController extends CharSequence[] mediaValues = new CharSequence[numDevices + 1]; // Setup devices entries, select active connected device - setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice); + setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice(STREAM_VOICE_CALL)); if (isStreamFromOutputDevice(STREAM_VOICE_CALL, DEVICE_OUT_USB_HEADSET)) { // If wired headset is plugged in and active, select to default device. @@ -92,8 +88,21 @@ public class HandsFreeProfileOutputPreferenceController extends @Override public void setActiveBluetoothDevice(BluetoothDevice device) { - if (Utils.isAudioModeOngoingCall(mContext)) { - mProfileManager.getHeadsetProfile().setActiveDevice(device); + if (!Utils.isAudioModeOngoingCall(mContext)) { + return; + } + final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); + final HeadsetProfile hfpProfile = mProfileManager.getHeadsetProfile(); + if (hapProfile != null && hfpProfile != null && device == null) { + hfpProfile.setActiveDevice(null); + hapProfile.setActiveDevice(null); + return; + } + if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) { + hapProfile.setActiveDevice(device); + } + if (hfpProfile != null) { + hfpProfile.setActiveDevice(device); } } } diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java index d0677a7e488..79f3c9d9549 100644 --- a/src/com/android/settings/sound/MediaOutputPreferenceController.java +++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.sound; +import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID; import static android.media.AudioManager.STREAM_MUSIC; import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; @@ -27,13 +28,12 @@ import android.content.Context; import android.media.AudioManager; import android.support.v7.preference.Preference; -import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settingslib.bluetooth.A2dpProfile; - +import com.android.settingslib.bluetooth.HearingAidProfile; /** - * This class which allows switching between a2dp-connected BT devices. + * This class which allows switching between A2dp-connected & HAP-connected BT devices. * A few conditions will disable this switcher: * - No available BT device(s) * - Media stream captured by cast device @@ -67,18 +67,14 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro return; } + mConnectedDevices.clear(); // Otherwise, list all of the A2DP connected device and display the active device. - mConnectedDevices = null; - BluetoothDevice activeDevice = null; if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { - final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); - if (a2dpProfile != null) { - mConnectedDevices = a2dpProfile.getConnectedDevices(); - activeDevice = a2dpProfile.getActiveDevice(); - } + mConnectedDevices.addAll(getConnectedA2dpDevices()); + mConnectedDevices.addAll(getConnectedHearingAidDevices()); } - final int numDevices = ArrayUtils.size(mConnectedDevices); + final int numDevices = mConnectedDevices.size(); if (numDevices == 0) { // Disable switch entry if there is no connected devices. mPreference.setVisible(false); @@ -91,7 +87,7 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro CharSequence[] mediaValues = new CharSequence[numDevices + 1]; // Setup devices entries, select active connected device - setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice); + setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice(STREAM_MUSIC)); if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_USB_HEADSET)) { // If wired headset is plugged in and active, select to default device. @@ -104,8 +100,21 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro @Override public void setActiveBluetoothDevice(BluetoothDevice device) { - if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { - mProfileManager.getA2dpProfile().setActiveDevice(device); + if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) { + return; + } + final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); + final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); + if (hapProfile != null && a2dpProfile != null && device == null) { + hapProfile.setActiveDevice(null); + a2dpProfile.setActiveDevice(null); + return; + } + if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) { + hapProfile.setActiveDevice(device); + } + if (a2dpProfile != null) { + a2dpProfile.setActiveDevice(device); } } } diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java index 61b9180eb33..272fd20cb35 100644 --- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java @@ -37,6 +37,8 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; @@ -69,7 +71,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowBluetoothDevice; @@ -114,11 +115,11 @@ public class AudioOutputSwitchPreferenceControllerTest { private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private BluetoothDevice mBluetoothDevice; - private BluetoothDevice mBluetoothHapDevice; - private BluetoothDevice mSecondBluetoothHapDevice; + private BluetoothDevice mLeftBluetoothHapDevice; + private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; private AudioSwitchPreferenceController mController; - private List mConnectedDevices; + private List mProfileConnectedDevices; private List mHearingAidActiveDevices; private List mEmptyDevices; @@ -146,15 +147,15 @@ public class AudioOutputSwitchPreferenceControllerTest { when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); when(mBluetoothDevice.isConnected()).thenReturn(true); - mBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); - when(mBluetoothHapDevice.isConnected()).thenReturn(true); - mSecondBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); - when(mSecondBluetoothHapDevice.isConnected()).thenReturn(true); + mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); + when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); + mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); + when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); mController = new AudioSwitchPreferenceControllerTestable(mContext, TEST_KEY); mScreen = spy(new PreferenceScreen(mContext, null)); mPreference = new ListPreference(mContext); - mConnectedDevices = new ArrayList<>(2); + mProfileConnectedDevices = new ArrayList<>(); mHearingAidActiveDevices = new ArrayList<>(2); mEmptyDevices = new ArrayList<>(2); @@ -204,9 +205,8 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() { - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mController.mConnectedDevices = mConnectedDevices; + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); mController.onPreferenceChange(mPreference, mContext.getText(R.string.media_output_default_summary)); @@ -221,9 +221,8 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() { - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mController.mConnectedDevices = mConnectedDevices; + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1); @@ -239,12 +238,11 @@ public class AudioOutputSwitchPreferenceControllerTest { ShadowBluetoothDevice shadowBluetoothDevice; BluetoothDevice secondBluetoothDevice; secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2); - shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice); + shadowBluetoothDevice = shadowOf(secondBluetoothDevice); shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(secondBluetoothDevice); - mController.mConnectedDevices = mConnectedDevices; + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(secondBluetoothDevice); mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2); @@ -252,12 +250,12 @@ public class AudioOutputSwitchPreferenceControllerTest { } /** - * mConnectedDevices is Null. + * mConnectedDevices is empty. * onPreferenceChange should return false. */ @Test public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() { - mController.mConnectedDevices = null; + mController.mConnectedDevices.clear(); assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse(); } @@ -268,7 +266,7 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void isStreamFromOutputDevice_outputDeviceIsBtScoHeadset_shouldReturnTrue() { - mShadowAudioManager.setStream(DEVICE_OUT_BLUETOOTH_SCO_HEADSET); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO_HEADSET); assertThat(mController.isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_ALL_SCO)).isTrue(); } @@ -288,10 +286,10 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamMusicToA2dpDevice_shouldReturnActiveA2dpDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_BLUETOOTH_A2DP); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mHearingAidActiveDevices.clear(); - mHearingAidActiveDevices.add(mBluetoothHapDevice); - when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothHapDevice); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + when(mHeadsetProfile.getActiveDevice()).thenReturn(mLeftBluetoothHapDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); @@ -304,11 +302,11 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamVoiceCallToHfpDevice_shouldReturnActiveHfpDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_BLUETOOTH_SCO); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO); mHearingAidActiveDevices.clear(); - mHearingAidActiveDevices.add(mBluetoothHapDevice); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); - when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothHapDevice); + when(mA2dpProfile.getActiveDevice()).thenReturn(mLeftBluetoothHapDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(mBluetoothDevice); @@ -321,19 +319,20 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamToHapDeviceLeftActiveDevice_shouldReturnActiveHapDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_HEARING_AID); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(mLeftBluetoothHapDevice); mHearingAidActiveDevices.clear(); - mHearingAidActiveDevices.add(mBluetoothHapDevice); - mController.mConnectedDevices = mConnectedDevices; + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(null); when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); - assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mBluetoothHapDevice); - assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(mBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mLeftBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo( + mLeftBluetoothHapDevice); } /** @@ -343,20 +342,21 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamToHapDeviceRightActiveDevice_shouldReturnActiveHapDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_HEARING_AID); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(mRightBluetoothHapDevice); mHearingAidActiveDevices.clear(); mHearingAidActiveDevices.add(null); - mHearingAidActiveDevices.add(mBluetoothHapDevice); - mController.mConnectedDevices = mConnectedDevices; + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); - assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mBluetoothHapDevice); - assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(mBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mRightBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo( + mRightBluetoothHapDevice); } /** @@ -366,20 +366,20 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamToHapDeviceTwoActiveDevice_shouldReturnActiveHapDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_HEARING_AID); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(mRightBluetoothHapDevice); mHearingAidActiveDevices.clear(); - mHearingAidActiveDevices.add(mSecondBluetoothHapDevice); - mHearingAidActiveDevices.add(mBluetoothHapDevice); - mController.mConnectedDevices = mConnectedDevices; + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); - assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mBluetoothHapDevice); - assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(mBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mRightBluetoothHapDevice); + assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo( + mRightBluetoothHapDevice); } /** @@ -389,12 +389,11 @@ public class AudioOutputSwitchPreferenceControllerTest { */ @Test public void findActiveDevice_streamToOtherDevice_shouldReturnActiveHapDevice() { - mShadowAudioManager.setStream(DEVICE_OUT_HEARING_AID); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(mLeftBluetoothHapDevice); mHearingAidActiveDevices.clear(); - mController.mConnectedDevices = mConnectedDevices; when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); @@ -410,17 +409,17 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedHearingAidDevices_deviceHisyncIdIsDifferent_shouldAddBothToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothHapDevice); - mConnectedDevices.add(mSecondBluetoothHapDevice); - when(mHearingAidProfile.getConnectedDevices()).thenReturn(mConnectedDevices); - when(mHearingAidProfile.getHiSyncId(mBluetoothHapDevice)).thenReturn(HISYNCID1); - when(mHearingAidProfile.getHiSyncId(mSecondBluetoothHapDevice)).thenReturn( - HISYNCID2); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); mEmptyDevices.addAll(mController.getConnectedHearingAidDevices()); - assertThat(mEmptyDevices).containsExactly(mBluetoothHapDevice, mSecondBluetoothHapDevice); + assertThat(mEmptyDevices).containsExactly(mLeftBluetoothHapDevice, + mRightBluetoothHapDevice); } /** @@ -430,17 +429,16 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedHearingAidDevices_deviceHisyncIdIsSame_shouldAddOneToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothHapDevice); - mConnectedDevices.add(mSecondBluetoothHapDevice); - when(mHearingAidProfile.getConnectedDevices()).thenReturn(mConnectedDevices); - when(mHearingAidProfile.getHiSyncId(mBluetoothHapDevice)).thenReturn(HISYNCID1); - when(mHearingAidProfile.getHiSyncId(mSecondBluetoothHapDevice)).thenReturn( - HISYNCID1); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); mEmptyDevices.addAll(mController.getConnectedHearingAidDevices()); - assertThat(mEmptyDevices).containsExactly(mBluetoothHapDevice); + assertThat(mEmptyDevices).containsExactly(mLeftBluetoothHapDevice); } /** @@ -450,9 +448,9 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedA2dpDevices_oneConnectedA2dpDevice_shouldAddDeviceToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); mEmptyDevices.addAll(mController.getConnectedA2dpDevices()); @@ -466,14 +464,14 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedA2dpDevices_moreThanOneConnectedA2dpDevice_shouldAddDeviceToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); mEmptyDevices.addAll(mController.getConnectedA2dpDevices()); - assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mBluetoothHapDevice); + assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice); } /** @@ -483,9 +481,9 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedHfpDevices_oneConnectedHfpDevice_shouldAddDeviceToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); mEmptyDevices.addAll(mController.getConnectedHfpDevices()); @@ -499,14 +497,14 @@ public class AudioOutputSwitchPreferenceControllerTest { @Test public void getConnectedHfpDevices_moreThanOneConnectedHfpDevice_shouldAddDeviceToList() { mEmptyDevices.clear(); - mConnectedDevices.clear(); - mConnectedDevices.add(mBluetoothDevice); - mConnectedDevices.add(mBluetoothHapDevice); - when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); mEmptyDevices.addAll(mController.getConnectedHfpDevices()); - assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mBluetoothHapDevice); + assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice); } private class AudioSwitchPreferenceControllerTestable extends diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java index 0692c9c6ccf..db09eab2d51 100644 --- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java @@ -17,12 +17,16 @@ package com.android.settings.sound; +import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; +import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID; import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -41,8 +45,8 @@ import com.android.settings.testutils.shadow.ShadowAudioManager; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settings.testutils.shadow.ShadowMediaRouter; import com.android.settingslib.bluetooth.BluetoothEventManager; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.HeadsetProfile; +import com.android.settingslib.bluetooth.HearingAidProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; @@ -53,7 +57,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowBluetoothDevice; @@ -69,21 +72,27 @@ import java.util.List; ) public class HandsFreeProfileOutputPreferenceControllerTest { private static final String TEST_KEY = "Test_Key"; - private static final String TEST_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1"; - private static final String TEST_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2"; - private static final String TEST_DEVICE_ADDRESS_1 = "00:07:80:78:A4:69"; - private static final String TEST_DEVICE_ADDRESS_2 = "00:00:00:00:00:00"; + private static final String TEST_DEVICE_NAME_1 = "Test_HFP_BT_Device_NAME_1"; + private static final String TEST_DEVICE_NAME_2 = "Test_HFP_BT_Device_NAME_2"; + private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1"; + private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2"; + private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1"; + private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2"; + private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3"; + private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4"; + private final static long HISYNCID1 = 10; + private final static long HISYNCID2 = 11; @Mock private LocalBluetoothManager mLocalManager; @Mock private BluetoothEventManager mBluetoothEventManager; @Mock - private CachedBluetoothDevice mCachedBluetoothDevice; - @Mock private LocalBluetoothProfileManager mLocalBluetoothProfileManager; @Mock private HeadsetProfile mHeadsetProfile; + @Mock + private HearingAidProfile mHearingAidProfile; private Context mContext; private PreferenceScreen mScreen; @@ -93,10 +102,13 @@ public class HandsFreeProfileOutputPreferenceControllerTest { private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private BluetoothDevice mBluetoothDevice; - private ShadowBluetoothDevice mShadowBluetoothDevice; + private BluetoothDevice mSecondBluetoothDevice; + private BluetoothDevice mLeftBluetoothHapDevice; + private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; private AudioSwitchPreferenceController mController; - private List mConnectedDevices; + private List mProfileConnectedDevices; + private List mHearingAidActiveDevices; @Before public void setUp() { @@ -112,19 +124,32 @@ public class HandsFreeProfileOutputPreferenceControllerTest { when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); + when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); mBluetoothManager = new BluetoothManager(mContext); mBluetoothAdapter = mBluetoothManager.getAdapter(); - mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1); - mShadowBluetoothDevice = Shadows.shadowOf(mBluetoothDevice); - mShadowBluetoothDevice.setName(TEST_DEVICE_NAME_1); - when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + + mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1)); + when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); + when(mBluetoothDevice.isConnected()).thenReturn(true); + + mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); + when(mSecondBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_2); + when(mSecondBluetoothDevice.isConnected()).thenReturn(true); + + mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); + when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1); + when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); + + mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4)); + when(mRightBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_2); + when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); mController = new HandsFreeProfileOutputPreferenceController(mContext, TEST_KEY); mScreen = spy(new PreferenceScreen(mContext, null)); mPreference = new ListPreference(mContext); - mConnectedDevices = new ArrayList<>(1); - mConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices = new ArrayList<>(); + mHearingAidActiveDevices = new ArrayList<>(2); when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mScreen.getContext()).thenReturn(mContext); @@ -140,8 +165,26 @@ public class HandsFreeProfileOutputPreferenceControllerTest { ShadowBluetoothUtils.reset(); } + /** + * During a call, bluetooth device with HisyncId. + * HearingAidProfile should set active device to this device. + */ @Test - public void setActiveBluetoothDevice_duringACalling_shouldSetBtDeviceActive() { + public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice); + + verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice); + } + + /** + * During a call, Bluetooth device without HisyncId. + * HeadsetProfile should set active device to this device. + */ + @Test + public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() { mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); mController.setActiveBluetoothDevice(mBluetoothDevice); @@ -149,23 +192,60 @@ public class HandsFreeProfileOutputPreferenceControllerTest { verify(mHeadsetProfile).setActiveDevice(mBluetoothDevice); } + /** + * During a call, set active device to "this device". + * HeadsetProfile should set to null. + * HearingAidProfile should set to null. + */ + @Test + public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + + mController.setActiveBluetoothDevice(null); + + verify(mHeadsetProfile).setActiveDevice(null); + verify(mHearingAidProfile).setActiveDevice(null); + } + + /** + * In normal mode + * HeadsetProfile should not set active device. + */ + @Test + public void setActiveBluetoothDevice_inNormalMode_shouldNotSetActiveDeviceToHeadsetProfile() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + + mController.setActiveBluetoothDevice(mBluetoothDevice); + + verify(mHeadsetProfile, times(0)).setActiveDevice(any(BluetoothDevice.class)); + } + + /** + * Default status + * Preference should be invisible + * Summary should be default summary + */ @Test public void updateState_shouldSetSummary() { mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_output_default_summary)); } /** - * One Headset Bluetooth device is available and activated + * One Hands Free Profile Bluetooth device is available and activated * Preference should be visible - * Preference summary should be activate device name + * Preference summary should be the activated device name */ @Test public void updateState_oneHeadsetsAvailableAndActivated_shouldSetDeviceName() { mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); mController.updateState(mPreference); @@ -175,29 +255,25 @@ public class HandsFreeProfileOutputPreferenceControllerTest { } /** - * More than one Headset Bluetooth devices are available, and second device is active. + * More than one Hands Free Profile Bluetooth devices are available, and second + * device is active. * Preference should be visible - * Preference summary should be activate device name + * Preference summary should be the activated device name */ @Test - public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() { - ShadowBluetoothDevice shadowBluetoothDevice; + public void updateState_moreThanOneHfpBtDevicesAreAvailable_shouldSetActivatedDeviceName() { mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - BluetoothDevice secondBluetoothDevice; - secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2); - shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice); - shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO); List connectedDevices = new ArrayList<>(2); connectedDevices.add(mBluetoothDevice); - connectedDevices.add(secondBluetoothDevice); - + connectedDevices.add(mSecondBluetoothDevice); when(mHeadsetProfile.getConnectedDevices()).thenReturn(connectedDevices); - when(mHeadsetProfile.getActiveDevice()).thenReturn(secondBluetoothDevice); + when(mHeadsetProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice); mController.updateState(mPreference); assertThat(mPreference.isVisible()).isTrue(); - assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName()); + assertThat(mPreference.getSummary()).isEqualTo(mSecondBluetoothDevice.getName()); } /** @@ -209,8 +285,10 @@ public class HandsFreeProfileOutputPreferenceControllerTest { @Test public void updateState_withAvailableDevicesWiredHeadsetActivated_shouldSetDefaultSummary() { mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - mShadowAudioManager.setStream(DEVICE_OUT_USB_HEADSET); - when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_USB_HEADSET); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mHeadsetProfile.getActiveDevice()).thenReturn( mBluetoothDevice); // BT device is still activated in this case @@ -238,4 +316,150 @@ public class HandsFreeProfileOutputPreferenceControllerTest { assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_output_default_summary)); } + + /** + * One hearing aid profile Bluetooth device is available and active. + * Preference should be visible + * Preference summary should be the activated device name + */ + @Test + public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); + } + + /** + * More than one hearing aid profile Bluetooth devices are available, and second + * device is active. + * Preference should be visible + * Preference summary should be the activated device name + */ + @Test + public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + } + + /** + * Both hearing aid profile and hands free profile Bluetooth devices are available, and + * two hearing aid profile devices with same HisyncId. Both of HAP device are active, + * "left" side HAP device is added first. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should not contain second HAP device with same HisyncId + */ + @Test + public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + //with same HisyncId, only the first one will remain in UI. + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); + assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue(); + assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse(); + } + + /** + * Both hearing aid profile and hands free profile Bluetooth devices are available, and + * two hearing aid profile devices with same HisyncId. Both of HAP device are active, + * "right" side HAP device is added first. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should not contain second HAP device with same HisyncId + */ + @Test + public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + //with same HisyncId, only the first one will remain in UI. + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue(); + assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + } + + /** + * Both hearing aid profile and hands free profile Bluetooth devices are available, and + * two hearing aid profile devices with different HisyncId. One of HAP device is active. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should contain both HAP device with different HisyncId + */ + @Test + public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(null); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice, + mLeftBluetoothHapDevice, mRightBluetoothHapDevice); + } } diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java index b62e6b388d9..b777239760a 100644 --- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java @@ -17,13 +17,17 @@ package com.android.settings.sound; +import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; +import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID; import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -43,7 +47,7 @@ import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settings.testutils.shadow.ShadowMediaRouter; import com.android.settingslib.bluetooth.A2dpProfile; import com.android.settingslib.bluetooth.BluetoothEventManager; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.HearingAidProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; @@ -54,7 +58,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowBluetoothDevice; @@ -72,19 +75,25 @@ public class MediaOutputPreferenceControllerTest { private static final String TEST_KEY = "Test_Key"; private static final String TEST_DEVICE_NAME_1 = "Test_A2DP_BT_Device_NAME_1"; private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_BT_Device_NAME_2"; - private static final String TEST_DEVICE_ADDRESS_1 = "00:07:80:78:A4:69"; - private static final String TEST_DEVICE_ADDRESS_2 = "00:00:00:00:00:00"; + private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1"; + private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2"; + private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1"; + private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2"; + private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3"; + private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4"; + private final static long HISYNCID1 = 10; + private final static long HISYNCID2 = 11; @Mock private LocalBluetoothManager mLocalManager; @Mock private BluetoothEventManager mBluetoothEventManager; @Mock - private CachedBluetoothDevice mCachedBluetoothDevice; - @Mock private LocalBluetoothProfileManager mLocalBluetoothProfileManager; @Mock private A2dpProfile mA2dpProfile; + @Mock + private HearingAidProfile mHearingAidProfile; private Context mContext; private PreferenceScreen mScreen; @@ -94,10 +103,13 @@ public class MediaOutputPreferenceControllerTest { private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private BluetoothDevice mBluetoothDevice; - private ShadowBluetoothDevice mShadowBluetoothDevice; + private BluetoothDevice mSecondBluetoothDevice; + private BluetoothDevice mLeftBluetoothHapDevice; + private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; private AudioSwitchPreferenceController mController; - private List mConnectedDevices; + private List mProfileConnectedDevices; + private List mHearingAidActiveDevices; @Before public void setUp() { @@ -113,19 +125,32 @@ public class MediaOutputPreferenceControllerTest { when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); + when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); mBluetoothManager = new BluetoothManager(mContext); mBluetoothAdapter = mBluetoothManager.getAdapter(); - mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1); - mShadowBluetoothDevice = Shadows.shadowOf(mBluetoothDevice); - mShadowBluetoothDevice.setName(TEST_DEVICE_NAME_1); - when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + + mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1)); + when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); + when(mBluetoothDevice.isConnected()).thenReturn(true); + + mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); + when(mSecondBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_2); + when(mSecondBluetoothDevice.isConnected()).thenReturn(true); + + mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); + when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1); + when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); + + mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4)); + when(mRightBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_2); + when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); mController = new MediaOutputPreferenceController(mContext, TEST_KEY); mScreen = spy(new PreferenceScreen(mContext, null)); mPreference = new ListPreference(mContext); - mConnectedDevices = new ArrayList<>(1); - mConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices = new ArrayList<>(); + mHearingAidActiveDevices = new ArrayList<>(2); when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mScreen.getContext()).thenReturn(mContext); @@ -141,8 +166,26 @@ public class MediaOutputPreferenceControllerTest { ShadowBluetoothUtils.reset(); } + /** + * In normal mode, bluetooth device with HisyncId. + * HearingAidProfile should set active device to this device. + */ @Test - public void setActiveBluetoothDevice_withoutRingAndCall_shouldSetBtDeviceActive() { + public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice); + + verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice); + } + + /** + * In normal mode, bluetooth device without HisyncId. + * A2dpProfile should set active device to this device. + */ + @Test + public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() { mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); mController.setActiveBluetoothDevice(mBluetoothDevice); @@ -150,16 +193,50 @@ public class MediaOutputPreferenceControllerTest { verify(mA2dpProfile).setActiveDevice(mBluetoothDevice); } + /** + * In normal mode, set active device to "this device". + * A2dpProfile should set to null. + * HearingAidProfile should set to null. + */ + @Test + public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + + mController.setActiveBluetoothDevice(null); + + verify(mA2dpProfile).setActiveDevice(null); + verify(mHearingAidProfile).setActiveDevice(null); + } + + /** + * During a call + * A2dpProfile should not set active device. + */ + @Test + public void setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + + mController.setActiveBluetoothDevice(mBluetoothDevice); + + verify(mA2dpProfile, times(0)).setActiveDevice(any(BluetoothDevice.class)); + } + + /** + * Default status + * Preference should be invisible + * Summary should be default summary + */ @Test public void updateState_shouldSetSummary() { mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_output_default_summary)); } /** - * On going call state: + * During a call * Preference should be invisible * Default string should be "Unavailable during calls" */ @@ -199,7 +276,7 @@ public class MediaOutputPreferenceControllerTest { */ @Test public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() { - mShadowAudioManager.setStream(DEVICE_OUT_REMOTE_SUBMIX); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_REMOTE_SUBMIX); mController.updateState(mPreference); @@ -211,12 +288,15 @@ public class MediaOutputPreferenceControllerTest { /** * One A2DP Bluetooth device is available and active. * Preference should be visible - * Preference summary should be activate device name + * Preference summary should be the activated device name */ @Test public void updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName() { mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); mController.updateState(mPreference); @@ -228,27 +308,22 @@ public class MediaOutputPreferenceControllerTest { /** * More than one A2DP Bluetooth devices are available, and second device is active. * Preference should be visible - * Preference summary should be activate device name + * Preference summary should be the activated device name */ @Test public void updateState_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName() { - ShadowBluetoothDevice shadowBluetoothDevice; mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); - BluetoothDevice secondBluetoothDevice; - secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2); - shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice); - shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2); - List connectedDevices = new ArrayList<>(2); - connectedDevices.add(mBluetoothDevice); - connectedDevices.add(secondBluetoothDevice); - - when(mA2dpProfile.getConnectedDevices()).thenReturn(connectedDevices); - when(mA2dpProfile.getActiveDevice()).thenReturn(secondBluetoothDevice); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mSecondBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mA2dpProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice); mController.updateState(mPreference); assertThat(mPreference.isVisible()).isTrue(); - assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName()); + assertThat(mPreference.getSummary()).isEqualTo(mSecondBluetoothDevice.getName()); } /** @@ -259,16 +334,18 @@ public class MediaOutputPreferenceControllerTest { @Test public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() { mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); - mShadowAudioManager.setStream(DEVICE_OUT_USB_HEADSET); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_USB_HEADSET); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mA2dpProfile.getActiveDevice()).thenReturn( mBluetoothDevice); // BT device is still activated in this case mController.updateState(mPreference); assertThat(mPreference.isVisible()).isTrue(); - String defaultString = mContext.getString(R.string.media_output_default_summary); - assertThat(mPreference.getSummary()).isEqualTo(defaultString); + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getString(R.string.media_output_default_summary)); } @@ -280,13 +357,161 @@ public class MediaOutputPreferenceControllerTest { @Test public void updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary() { mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mA2dpProfile.getActiveDevice()).thenReturn(null); mController.updateState(mPreference); assertThat(mPreference.isVisible()).isTrue(); - String defaultString = mContext.getString(R.string.media_output_default_summary); - assertThat(mPreference.getSummary()).isEqualTo(defaultString); + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getString(R.string.media_output_default_summary)); + } + + /** + * One hearing aid profile Bluetooth device is available and active. + * Preference should be visible + * Preference summary should be the activated device name + */ + @Test + public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); + } + + /** + * More than one hearing aid profile Bluetooth devices are available, and second + * device is active. + * Preference should be visible + * Preference summary should be the activated device name + */ + @Test + public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + } + + /** + * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid + * profile devices with same HisyncId are active. Both of HAP device are active, + * "left" side HAP device is added first. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should not contain second HAP device with same HisyncId + */ + @Test + public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + //with same HisyncId, first one will remain in UI. + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); + assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue(); + assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse(); + } + + /** + * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid + * profile devices with same HisyncId. Both of HAP device are active, + * "right" side HAP device is added first. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should not contain second HAP device with same HisyncId + */ + @Test + public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + //with same HisyncId, first one will remain in UI. + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue(); + assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse(); + } + + /** + * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid + * profile devices with different HisyncId. One of HAP device is active. + * Preference should be visible + * Preference summary should be the activated device name + * ConnectedDevice should contain both HAP device with different HisyncId + */ + @Test + public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mLeftBluetoothHapDevice); + mProfileConnectedDevices.add(mRightBluetoothHapDevice); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(null); + mHearingAidActiveDevices.add(mRightBluetoothHapDevice); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); + + mController.updateState(mPreference); + + assertThat(mPreference.isVisible()).isTrue(); + assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); + assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice, + mLeftBluetoothHapDevice, mRightBluetoothHapDevice); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java index 0de2156ce38..88a0fb649b5 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java @@ -41,7 +41,7 @@ import java.util.ArrayList; @Implements(value = AudioManager.class, inheritImplementationMethods = true) public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManager { private int mRingerMode; - private int mStream; + private int mDeviceCodes; private boolean mMusicActiveRemotely = false; private ArrayList mDeviceCallbacks = new ArrayList(); @@ -79,8 +79,8 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag return mMusicActiveRemotely; } - public void setStream(int stream) { - mStream = stream; + public void setOutputDevice(int deviceCodes) { + mDeviceCodes = deviceCodes; } @Implementation @@ -94,7 +94,7 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag case STREAM_NOTIFICATION: case STREAM_DTMF: case STREAM_ACCESSIBILITY: - return mStream; + return mDeviceCodes; default: return 0; }