Merge changes from topic "add-hearing-aid-device-in-audio-switch" into pi-dev

* changes:
  Add hearing aid device in audio switch
  Find active device for add hearing aids device into audio switcher.
  Three methods for adding hearing aids device into audio switcher.
This commit is contained in:
TreeHugger Robot
2018-05-10 03:31:33 +00:00
committed by Android (Google) Code Review
7 changed files with 976 additions and 134 deletions

View File

@@ -16,8 +16,12 @@
package com.android.settings.sound;
import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioSystem.DEVICE_OUT_ALL_A2DP;
import static android.media.AudioSystem.DEVICE_OUT_ALL_SCO;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
import android.bluetooth.BluetoothDevice;
@@ -38,19 +42,22 @@ 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;
import com.android.settings.core.FeatureFlags;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
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;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
import java.util.List;
/**
@@ -65,12 +72,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
private static final int INVALID_INDEX = -1;
protected final List<BluetoothDevice> mConnectedDevices;
protected final AudioManager mAudioManager;
protected final MediaRouter mMediaRouter;
protected final LocalBluetoothProfileManager mProfileManager;
protected int mSelectedIndex;
protected Preference mPreference;
protected List<BluetoothDevice> mConnectedDevices;
private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;
private final LocalBluetoothManager mLocalBluetoothManager;
@@ -89,6 +96,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback();
mReceiver = new WiredHeadsetBroadcastReceiver();
mMediaRouterCallback = new MediaRouterCallback();
mConnectedDevices = new ArrayList<>();
}
/**
@@ -195,12 +203,105 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
}
protected boolean isStreamFromOutputDevice(int streamType, int device) {
return mAudioManager.getDevicesForStream(streamType) == device;
return (device & mAudioManager.getDevicesForStream(streamType)) != 0;
}
/**
* get hands free profile(HFP) connected device
*/
protected List<BluetoothDevice> getConnectedHfpDevices() {
final List<BluetoothDevice> connectedDevices = new ArrayList<>();
final HeadsetProfile hfpProfile = mProfileManager.getHeadsetProfile();
if (hfpProfile == null) {
return connectedDevices;
}
final List<BluetoothDevice> devices = hfpProfile.getConnectedDevices();
for (BluetoothDevice device : devices) {
if (device.isConnected()) {
connectedDevices.add(device);
}
}
return connectedDevices;
}
/**
* get A2dp connected device
*/
protected List<BluetoothDevice> getConnectedA2dpDevices() {
final List<BluetoothDevice> connectedDevices = new ArrayList<>();
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
if (a2dpProfile == null) {
return connectedDevices;
}
final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
for (BluetoothDevice device : devices) {
if (device.isConnected()) {
connectedDevices.add(device);
}
}
return connectedDevices;
}
/**
* get hearing aid profile connected device, exclude other devices with same hiSyncId.
*/
protected List<BluetoothDevice> getConnectedHearingAidDevices() {
final List<BluetoothDevice> connectedDevices = new ArrayList<>();
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
if (hapProfile == null) {
return connectedDevices;
}
final List<Long> devicesHiSyncIds = new ArrayList<>();
final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
for (BluetoothDevice device : devices) {
final long hiSyncId = hapProfile.getHiSyncId(device);
// device with same hiSyncId should not be shown in the UI.
// So do not add it into connectedDevices.
if (!devicesHiSyncIds.contains(hiSyncId) && device.isConnected()) {
devicesHiSyncIds.add(hiSyncId);
connectedDevices.add(device);
}
}
return connectedDevices;
}
/**
* According to different stream and output device, find the active device from
* the corresponding profile. Hearing aid device could stream both STREAM_MUSIC
* and STREAM_VOICE_CALL.
*
* @param streamType the type of audio streams.
* @return the active device. Return null if the active device is current device
* or streamType is not STREAM_MUSIC or STREAM_VOICE_CALL.
*/
protected BluetoothDevice findActiveDevice(int streamType) {
if (streamType != STREAM_MUSIC && streamType != STREAM_VOICE_CALL) {
return null;
}
if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_ALL_A2DP)) {
return mProfileManager.getA2dpProfile().getActiveDevice();
} else if (isStreamFromOutputDevice(STREAM_VOICE_CALL, DEVICE_OUT_ALL_SCO)) {
return mProfileManager.getHeadsetProfile().getActiveDevice();
} else if (isStreamFromOutputDevice(streamType, DEVICE_OUT_HEARING_AID)) {
// The first element is the left active device; the second element is
// the right active device. And they will have same hiSyncId. If either
// or both side is not active, it will be null on that position.
List<BluetoothDevice> activeDevices =
mProfileManager.getHearingAidProfile().getActiveDevices();
for (BluetoothDevice btDevice : activeDevices) {
if (btDevice != null && mConnectedDevices.contains(btDevice)) {
// also need to check mConnectedDevices, because one of
// the device(same hiSyncId) might not be shown in the UI.
return btDevice;
}
}
}
return null;
}
int getDefaultDeviceIndex() {
// Default device is after all connected devices.
return ArrayUtils.size(mConnectedDevices);
return mConnectedDevices.size();
}
void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
@@ -261,7 +362,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
mContext.unregisterReceiver(mReceiver);
}
/** Callback for headset plugged and unplugged events. */
/** Notifications of audio device connection and disconnection events. */
private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback {
@Override
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -17,6 +17,15 @@
package com.android.settings.sound;
import static android.media.AudioManager.DEVICE_OUT_BLUETOOTH_SCO;
import static android.media.AudioManager.STREAM_RING;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioSystem.DEVICE_OUT_ALL_SCO;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.AudioSystem.STREAM_MUSIC;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
@@ -28,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;
@@ -48,7 +59,8 @@ import com.android.settings.testutils.shadow.ShadowMediaRouter;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
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;
@@ -59,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;
@@ -77,19 +88,24 @@ public class AudioOutputSwitchPreferenceControllerTest {
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_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 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 HeadsetProfile mHeadsetProfile;
@Mock
private HearingAidProfile mHearingAidProfile;
private Context mContext;
private PreferenceScreen mScreen;
@@ -99,10 +115,13 @@ public class AudioOutputSwitchPreferenceControllerTest {
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mBluetoothDevice;
private ShadowBluetoothDevice mShadowBluetoothDevice;
private BluetoothDevice mLeftBluetoothHapDevice;
private BluetoothDevice mRightBluetoothHapDevice;
private LocalBluetoothManager mLocalBluetoothManager;
private AudioSwitchPreferenceController mController;
private List<BluetoothDevice> mConnectedDevices;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
private List<BluetoothDevice> mEmptyDevices;
@Before
public void setUp() {
@@ -118,20 +137,27 @@ public class AudioOutputSwitchPreferenceControllerTest {
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
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);
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<>(1);
mConnectedDevices.add(mBluetoothDevice);
mProfileConnectedDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2);
mEmptyDevices = new ArrayList<>(2);
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
when(mScreen.getContext()).thenReturn(mContext);
@@ -179,7 +205,8 @@ public class AudioOutputSwitchPreferenceControllerTest {
@Test
public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() {
mController.mConnectedDevices = mConnectedDevices;
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.onPreferenceChange(mPreference,
mContext.getText(R.string.media_output_default_summary));
@@ -194,7 +221,8 @@ public class AudioOutputSwitchPreferenceControllerTest {
*/
@Test
public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() {
mController.mConnectedDevices = mConnectedDevices;
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1);
@@ -210,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);
List<BluetoothDevice> connectedDevices = new ArrayList<>(2);
connectedDevices.add(mBluetoothDevice);
connectedDevices.add(secondBluetoothDevice);
mController.mConnectedDevices = connectedDevices;
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.mConnectedDevices.add(secondBluetoothDevice);
mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
@@ -223,16 +250,263 @@ 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();
}
/**
* Audio stream output to bluetooth sco headset which is the subset of all sco device.
* isStreamFromOutputDevice should return true.
*/
@Test
public void isStreamFromOutputDevice_outputDeviceIsBtScoHeadset_shouldReturnTrue() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
assertThat(mController.isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_ALL_SCO)).isTrue();
}
/**
* Audio stream is not STREAM_MUSIC or STREAM_VOICE_CALL.
* findActiveDevice should return null.
*/
@Test
public void findActiveDevice_streamIsRing_shouldReturnNull() {
assertThat(mController.findActiveDevice(STREAM_RING)).isNull();
}
/**
* Audio stream is STREAM_MUSIC and output device is A2dp bluetooth device.
* findActiveDevice should return A2dp active device.
*/
@Test
public void findActiveDevice_streamMusicToA2dpDevice_shouldReturnActiveA2dpDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
mHearingAidActiveDevices.clear();
mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
when(mHeadsetProfile.getActiveDevice()).thenReturn(mLeftBluetoothHapDevice);
when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
assertThat(mController.findActiveDevice(STREAM_MUSIC)).isEqualTo(mBluetoothDevice);
}
/**
* Audio stream is STREAM_VOICE_CALL and output device is Hands free profile bluetooth device.
* findActiveDevice should return Hands free profile active device.
*/
@Test
public void findActiveDevice_streamVoiceCallToHfpDevice_shouldReturnActiveHfpDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO);
mHearingAidActiveDevices.clear();
mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
when(mA2dpProfile.getActiveDevice()).thenReturn(mLeftBluetoothHapDevice);
when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(mBluetoothDevice);
}
/**
* Audio stream is STREAM_MUSIC or STREAM_VOICE_CALL and output device is hearing aid profile
* bluetooth device. And left side of HAP device is active.
* findActiveDevice should return hearing aid device active device.
*/
@Test
public void findActiveDevice_streamToHapDeviceLeftActiveDevice_shouldReturnActiveHapDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.mConnectedDevices.add(mLeftBluetoothHapDevice);
mHearingAidActiveDevices.clear();
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(mLeftBluetoothHapDevice);
assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(
mLeftBluetoothHapDevice);
}
/**
* Audio stream is STREAM_MUSIC or STREAM_VOICE_CALL and output device is hearing aid profile
* bluetooth device. And right side of HAP device is active.
* findActiveDevice should return hearing aid device active device.
*/
@Test
public void findActiveDevice_streamToHapDeviceRightActiveDevice_shouldReturnActiveHapDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.mConnectedDevices.add(mRightBluetoothHapDevice);
mHearingAidActiveDevices.clear();
mHearingAidActiveDevices.add(null);
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(mRightBluetoothHapDevice);
assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(
mRightBluetoothHapDevice);
}
/**
* Audio stream is STREAM_MUSIC or STREAM_VOICE_CALL and output device is hearing aid
* profile bluetooth device. And both are active device.
* findActiveDevice should return only return the active device in mConnectedDevices.
*/
@Test
public void findActiveDevice_streamToHapDeviceTwoActiveDevice_shouldReturnActiveHapDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.mConnectedDevices.add(mRightBluetoothHapDevice);
mHearingAidActiveDevices.clear();
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(mRightBluetoothHapDevice);
assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isEqualTo(
mRightBluetoothHapDevice);
}
/**
* Audio stream is STREAM_MUSIC or STREAM_VOICE_CALL and output device is hearing aid
* profile bluetooth device. And none of them are active.
* findActiveDevice should return null.
*/
@Test
public void findActiveDevice_streamToOtherDevice_shouldReturnActiveHapDevice() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
mController.mConnectedDevices.add(mLeftBluetoothHapDevice);
mHearingAidActiveDevices.clear();
when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
assertThat(mController.findActiveDevice(STREAM_MUSIC)).isNull();
assertThat(mController.findActiveDevice(STREAM_VOICE_CALL)).isNull();
}
/**
* Two hearing aid devices with different HisyncId
* getConnectedHearingAidDevices should add both device to list.
*/
@Test
public void getConnectedHearingAidDevices_deviceHisyncIdIsDifferent_shouldAddBothToList() {
mEmptyDevices.clear();
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(mLeftBluetoothHapDevice,
mRightBluetoothHapDevice);
}
/**
* Two hearing aid devices with same HisyncId
* getConnectedHearingAidDevices should only add first device to list.
*/
@Test
public void getConnectedHearingAidDevices_deviceHisyncIdIsSame_shouldAddOneToList() {
mEmptyDevices.clear();
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(mLeftBluetoothHapDevice);
}
/**
* One A2dp device is connected.
* getConnectedA2dpDevices should add this device to list.
*/
@Test
public void getConnectedA2dpDevices_oneConnectedA2dpDevice_shouldAddDeviceToList() {
mEmptyDevices.clear();
mProfileConnectedDevices.clear();
mProfileConnectedDevices.add(mBluetoothDevice);
when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
}
/**
* More than one A2dp devices are connected.
* getConnectedA2dpDevices should add all devices to list.
*/
@Test
public void getConnectedA2dpDevices_moreThanOneConnectedA2dpDevice_shouldAddDeviceToList() {
mEmptyDevices.clear();
mProfileConnectedDevices.clear();
mProfileConnectedDevices.add(mBluetoothDevice);
mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice);
}
/**
* One hands free profile device is connected.
* getConnectedA2dpDevices should add this device to list.
*/
@Test
public void getConnectedHfpDevices_oneConnectedHfpDevice_shouldAddDeviceToList() {
mEmptyDevices.clear();
mProfileConnectedDevices.clear();
mProfileConnectedDevices.add(mBluetoothDevice);
when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
mEmptyDevices.addAll(mController.getConnectedHfpDevices());
assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
}
/**
* More than one hands free profile devices are connected.
* getConnectedA2dpDevices should add all devices to list.
*/
@Test
public void getConnectedHfpDevices_moreThanOneConnectedHfpDevice_shouldAddDeviceToList() {
mEmptyDevices.clear();
mProfileConnectedDevices.clear();
mProfileConnectedDevices.add(mBluetoothDevice);
mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
mEmptyDevices.addAll(mController.getConnectedHfpDevices());
assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice);
}
private class AudioSwitchPreferenceControllerTestable extends
AudioSwitchPreferenceController {
AudioSwitchPreferenceControllerTestable(Context context, String key) {

View File

@@ -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<BluetoothDevice> mConnectedDevices;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> 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<BluetoothDevice> 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);
}
}

View File

@@ -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<BluetoothDevice> mConnectedDevices;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> 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<BluetoothDevice> 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);
}
}

View File

@@ -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<AudioDeviceCallback> 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;
}