diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml index 81a04538430..57bee1f353c 100644 --- a/res/xml/sound_settings.xml +++ b/res/xml/sound_settings.xml @@ -41,7 +41,7 @@ settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/> - - onPreferenceDataChanged(listPreference)); - mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey(); use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference -> onPreferenceDataChanged(listPreference)); mHfpOutputControllerKey = diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index f77dfcafc7e..0da0f2142d5 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -32,7 +32,6 @@ import android.media.MediaRouter; import android.media.MediaRouter.Callback; import android.os.Handler; import android.os.Looper; -import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; @@ -40,7 +39,6 @@ import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.settings.R; import com.android.settings.bluetooth.Utils; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.FeatureFlags; @@ -63,15 +61,11 @@ import java.util.concurrent.FutureTask; /** * Abstract class for audio switcher controller to notify subclass * updating the current status of switcher entry. Subclasses must overwrite - * {@link #setActiveBluetoothDevice(BluetoothDevice)} to set the - * active device for corresponding profile. */ public abstract class AudioSwitchPreferenceController extends BasePreferenceController - implements Preference.OnPreferenceChangeListener, BluetoothCallback, - LifecycleObserver, OnStart, OnStop { + implements BluetoothCallback, LifecycleObserver, OnStart, OnStop { private static final String TAG = "AudioSwitchPrefCtrl"; - private static final int INVALID_INDEX = -1; protected final List mConnectedDevices; protected final AudioManager mAudioManager; @@ -128,35 +122,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final String address = (String) newValue; - if (!(preference instanceof ListPreference)) { - return false; - } - - final ListPreference listPreference = (ListPreference) preference; - if (TextUtils.equals(address, mContext.getText(R.string.media_output_default_summary))) { - // Switch to default device which address is device name - mSelectedIndex = getDefaultDeviceIndex(); - setActiveBluetoothDevice(null); - listPreference.setSummary(mContext.getText(R.string.media_output_default_summary)); - } else { - // Switch to BT device which address is hardware address - final int connectedDeviceIndex = getConnectedDeviceIndex(address); - if (connectedDeviceIndex == INVALID_INDEX) { - return false; - } - final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex); - mSelectedIndex = connectedDeviceIndex; - setActiveBluetoothDevice(btDevice); - listPreference.setSummary(btDevice.getAliasName()); - } - return true; - } - - public abstract void setActiveBluetoothDevice(BluetoothDevice device); - @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); @@ -184,6 +149,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont unregister(); } + @Override + public void onBluetoothStateChanged(int bluetoothState) { + // To handle the case that Bluetooth on and no connected devices + updateState(mPreference); + } + @Override public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { updateState(mPreference); @@ -236,21 +207,15 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont } /** - * get A2dp connected device + * get A2dp devices on all states + * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) */ - protected List getConnectedA2dpDevices() { - final List connectedDevices = new ArrayList<>(); + protected List getConnectableA2dpDevices() { final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); if (a2dpProfile == null) { - return connectedDevices; + return new ArrayList<>(); } - final List devices = a2dpProfile.getConnectedDevices(); - for (BluetoothDevice device : devices) { - if (device.isConnected()) { - connectedDevices.add(device); - } - } - return connectedDevices; + return a2dpProfile.getConnectableDevices(); } /** @@ -276,6 +241,31 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont return connectedDevices; } + /** + * get hearing aid profile devices on all states + * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) + * exclude other devices with same hiSyncId. + */ + protected List getConnectableHearingAidDevices() { + final List connectedDevices = new ArrayList<>(); + final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); + if (hapProfile == null) { + return connectedDevices; + } + final List devicesHiSyncIds = new ArrayList<>(); + final List devices = hapProfile.getConnectableDevices(); + 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)) { + devicesHiSyncIds.add(hiSyncId); + connectedDevices.add(device); + } + } + return connectedDevices; + } + /** * Find active hearing aid device */ @@ -306,52 +296,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont */ public abstract BluetoothDevice findActiveDevice(); - int getDefaultDeviceIndex() { - // Default device is after all connected devices. - return mConnectedDevices.size(); - } - - void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues, - BluetoothDevice activeDevice) { - // default to current device - mSelectedIndex = getDefaultDeviceIndex(); - // default device is after all connected devices. - mediaOutputs[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary); - // use default device name as address - mediaValues[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary); - for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { - final BluetoothDevice btDevice = mConnectedDevices.get(i); - mediaOutputs[i] = btDevice.getAliasName(); - mediaValues[i] = btDevice.getAddress(); - if (btDevice.equals(activeDevice)) { - // select the active connected device. - mSelectedIndex = i; - } - } - } - - void setPreference(CharSequence[] mediaOutputs, CharSequence[] mediaValues, - Preference preference) { - final ListPreference listPreference = (ListPreference) preference; - listPreference.setEntries(mediaOutputs); - listPreference.setEntryValues(mediaValues); - listPreference.setValueIndex(mSelectedIndex); - listPreference.setSummary(mediaOutputs[mSelectedIndex]); - mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference); - } - - private int getConnectedDeviceIndex(String hardwareAddress) { - if (mConnectedDevices != null) { - for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { - final BluetoothDevice btDevice = mConnectedDevices.get(i); - if (TextUtils.equals(btDevice.getAddress(), hardwareAddress)) { - return i; - } - } - } - return INVALID_INDEX; - } - private void register() { mLocalBluetoothManager.getEventManager().registerCallback(this); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java index a02c0b28b13..91574777963 100644 --- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java +++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java @@ -20,7 +20,9 @@ import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID; import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.text.TextUtils; +import androidx.preference.ListPreference; import androidx.preference.Preference; import com.android.settings.R; @@ -32,13 +34,55 @@ import com.android.settingslib.bluetooth.HearingAidProfile; * This class allows switching between HFP-connected & HAP-connected BT devices * while in on-call state. */ -public class HandsFreeProfileOutputPreferenceController extends - AudioSwitchPreferenceController { +public class HandsFreeProfileOutputPreferenceController extends AudioSwitchPreferenceController + implements Preference.OnPreferenceChangeListener { + + private static final int INVALID_INDEX = -1; public HandsFreeProfileOutputPreferenceController(Context context, String key) { super(context, key); } + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final String address = (String) newValue; + if (!(preference instanceof ListPreference)) { + return false; + } + + final CharSequence defaultSummary = mContext.getText(R.string.media_output_default_summary); + final ListPreference listPreference = (ListPreference) preference; + if (TextUtils.equals(address, defaultSummary)) { + // Switch to default device which address is device name + mSelectedIndex = getDefaultDeviceIndex(); + setActiveBluetoothDevice(null); + listPreference.setSummary(defaultSummary); + } else { + // Switch to BT device which address is hardware address + final int connectedDeviceIndex = getConnectedDeviceIndex(address); + if (connectedDeviceIndex == INVALID_INDEX) { + return false; + } + final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex); + mSelectedIndex = connectedDeviceIndex; + setActiveBluetoothDevice(btDevice); + listPreference.setSummary(btDevice.getAliasName()); + } + return true; + } + + private int getConnectedDeviceIndex(String hardwareAddress) { + if (mConnectedDevices != null) { + for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { + final BluetoothDevice btDevice = mConnectedDevices.get(i); + if (TextUtils.equals(btDevice.getAddress(), hardwareAddress)) { + return i; + } + } + } + return INVALID_INDEX; + } + @Override public void updateState(Preference preference) { if (preference == null) { @@ -83,7 +127,41 @@ public class HandsFreeProfileOutputPreferenceController extends setPreference(mediaOutputs, mediaValues, preference); } - @Override + int getDefaultDeviceIndex() { + // Default device is after all connected devices. + return mConnectedDevices.size(); + } + + void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues, + BluetoothDevice activeDevice) { + // default to current device + mSelectedIndex = getDefaultDeviceIndex(); + // default device is after all connected devices. + final CharSequence defaultSummary = mContext.getText(R.string.media_output_default_summary); + mediaOutputs[mSelectedIndex] = defaultSummary; + // use default device name as address + mediaValues[mSelectedIndex] = defaultSummary; + for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { + final BluetoothDevice btDevice = mConnectedDevices.get(i); + mediaOutputs[i] = btDevice.getAliasName(); + mediaValues[i] = btDevice.getAddress(); + if (btDevice.equals(activeDevice)) { + // select the active connected device. + mSelectedIndex = i; + } + } + } + + void setPreference(CharSequence[] mediaOutputs, CharSequence[] mediaValues, + Preference preference) { + final ListPreference listPreference = (ListPreference) preference; + listPreference.setEntries(mediaOutputs); + listPreference.setEntryValues(mediaValues); + listPreference.setValueIndex(mSelectedIndex); + listPreference.setSummary(mediaOutputs[mSelectedIndex]); + mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference); + } + public void setActiveBluetoothDevice(BluetoothDevice device) { if (!Utils.isAudioModeOngoingCall(mContext)) { return; diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java index ce476adf289..47810f7db3b 100644 --- a/src/com/android/settings/sound/MediaOutputPreferenceController.java +++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java @@ -16,13 +16,14 @@ 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 android.bluetooth.BluetoothDevice; import android.content.Context; +import android.content.Intent; import android.media.AudioManager; +import android.text.TextUtils; import androidx.preference.Preference; @@ -30,12 +31,16 @@ import com.android.settings.R; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.A2dpProfile; import com.android.settingslib.bluetooth.HearingAidProfile; +import com.android.settingslib.media.MediaOutputSliceConstants; + +import java.util.List; /** - * 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 + * This class allows launching MediaOutputSlice to switch output device. + * Preference would hide only when + * - Bluetooth = OFF + * - Bluetooth = ON and Connected Devices = 0 and Previously Connected = 0 + * - Media stream captured by remote device * - During a call. */ public class MediaOutputPreferenceController extends AudioSwitchPreferenceController { @@ -66,40 +71,22 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro return; } - mConnectedDevices.clear(); - // Otherwise, list all of the A2DP connected device and display the active device. - if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { - mConnectedDevices.addAll(getConnectedA2dpDevices()); - mConnectedDevices.addAll(getConnectedHearingAidDevices()); - } - - final int numDevices = mConnectedDevices.size(); - mPreference.setVisible((numDevices == 0) ? false : true); - CharSequence[] mediaOutputs = new CharSequence[numDevices + 1]; - CharSequence[] mediaValues = new CharSequence[numDevices + 1]; - - // Setup devices entries, select active connected device - setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice()); - - // Display connected devices, default device and show the active device - setPreference(mediaOutputs, mediaValues, preference); - } - - @Override - public void setActiveBluetoothDevice(BluetoothDevice 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); - } else if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) { - hapProfile.setActiveDevice(device); - } else if (a2dpProfile != null) { - a2dpProfile.setActiveDevice(device); + boolean deviceConnectable = false; + BluetoothDevice activeDevice = null; + // Show preference if there is connected or previously connected device + // Find active device and set its name as the preference's summary + List connectableA2dpDevices = getConnectableA2dpDevices(); + List connectableHADevices = getConnectableHearingAidDevices(); + if (mAudioManager.getMode() == AudioManager.MODE_NORMAL + && ((connectableA2dpDevices != null && !connectableA2dpDevices.isEmpty()) + || (connectableHADevices != null && !connectableHADevices.isEmpty()))) { + deviceConnectable = true; + activeDevice = findActiveDevice(); } + mPreference.setVisible(deviceConnectable); + mPreference.setSummary((activeDevice == null) ? + mContext.getText(R.string.media_output_default_summary) : + activeDevice.getAliasName()); } @Override @@ -112,4 +99,34 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro } return activeDevice; } + + /** + * Find active hearing aid device + */ + @Override + protected BluetoothDevice findActiveHearingAidDevice() { + final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); + + if (hearingAidProfile != null) { + List activeDevices = hearingAidProfile.getActiveDevices(); + for (BluetoothDevice btDevice : activeDevices) { + if (btDevice != null) { + return btDevice; + } + } + } + return null; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { + final Intent intent = new Intent() + .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + return true; + } + return false; + } } diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java index 54a79f4dfe3..5b7c8631901 100644 --- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java @@ -238,63 +238,6 @@ public class AudioOutputSwitchPreferenceControllerTest { verify(mLocalBluetoothManager).setForegroundActivity(null); } - @Test - public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() { - mController.mConnectedDevices.clear(); - mController.mConnectedDevices.add(mBluetoothDevice); - - mController.onPreferenceChange(mPreference, - mContext.getText(R.string.media_output_default_summary)); - - assertThat(mPreference.getSummary()).isEqualTo( - mContext.getText(R.string.media_output_default_summary)); - } - - /** - * One Bluetooth devices are available, and select the device. - * Preference summary should be device name. - */ - @Test - public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() { - mController.mConnectedDevices.clear(); - mController.mConnectedDevices.add(mBluetoothDevice); - - mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1); - - assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); - } - - /** - * More than one Bluetooth devices are available, and select second device. - * Preference summary should be second device name. - */ - @Test - public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() { - ShadowBluetoothDevice shadowBluetoothDevice; - BluetoothDevice secondBluetoothDevice; - secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2); - shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice); - shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2); - mController.mConnectedDevices.clear(); - mController.mConnectedDevices.add(mBluetoothDevice); - mController.mConnectedDevices.add(secondBluetoothDevice); - - mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2); - - assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2); - } - - /** - * mConnectedDevices is empty. - * onPreferenceChange should return false. - */ - @Test - public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() { - 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. @@ -415,39 +358,6 @@ public class AudioOutputSwitchPreferenceControllerTest { 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. @@ -487,10 +397,6 @@ public class AudioOutputSwitchPreferenceControllerTest { super(context, key); } - @Override - public void setActiveBluetoothDevice(BluetoothDevice device) { - } - @Override public BluetoothDevice findActiveDevice() { return null; diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java index 401014572cd..0eada6062c8 100644 --- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java @@ -57,6 +57,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowBluetoothDevice; @@ -107,7 +108,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest { private BluetoothDevice mLeftBluetoothHapDevice; private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; - private AudioSwitchPreferenceController mController; + private HandsFreeProfileOutputPreferenceController mController; private List mProfileConnectedDevices; private List mHearingAidActiveDevices; @@ -478,4 +479,61 @@ public class HandsFreeProfileOutputPreferenceControllerTest { assertThat(mController.findActiveDevice()).isNull(); } + + /** + * One Bluetooth devices are available, and select the device. + * Preference summary should be device name. + */ + @Test + public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() { + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + + mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1); + + assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); + } + + /** + * More than one Bluetooth devices are available, and select second device. + * Preference summary should be second device name. + */ + @Test + public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() { + ShadowBluetoothDevice shadowBluetoothDevice; + BluetoothDevice secondBluetoothDevice; + secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2); + shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice); + shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2); + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + mController.mConnectedDevices.add(secondBluetoothDevice); + + mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2); + + assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2); + } + + /** + * mConnectedDevices is empty. + * onPreferenceChange should return false. + */ + @Test + public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() { + mController.mConnectedDevices.clear(); + + assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse(); + } + + @Test + public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() { + mController.mConnectedDevices.clear(); + mController.mConnectedDevices.add(mBluetoothDevice); + + mController.onPreferenceChange(mPreference, + mContext.getText(R.string.media_output_default_summary)); + + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getText(R.string.media_output_default_summary)); + } } diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java index 8c7faefd5c7..7fcd3d2986d 100644 --- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java @@ -17,16 +17,15 @@ package com.android.settings.sound; import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; +import static android.media.AudioSystem.DEVICE_OUT_EARPIECE; import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID; import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 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.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,9 +33,10 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.Context; +import android.content.Intent; import android.media.AudioManager; -import androidx.preference.ListPreference; +import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -49,11 +49,13 @@ import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.HearingAidProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.media.MediaOutputSliceConstants; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -80,8 +82,6 @@ public class MediaOutputPreferenceControllerTest { 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; @@ -98,7 +98,7 @@ public class MediaOutputPreferenceControllerTest { private Context mContext; private PreferenceScreen mScreen; - private ListPreference mPreference; + private Preference mPreference; private AudioManager mAudioManager; private ShadowAudioManager mShadowAudioManager; private BluetoothManager mBluetoothManager; @@ -108,8 +108,8 @@ public class MediaOutputPreferenceControllerTest { private BluetoothDevice mLeftBluetoothHapDevice; private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; - private AudioSwitchPreferenceController mController; - private List mProfileConnectedDevices; + private MediaOutputPreferenceController mController; + private List mProfileConnectableDevices; private List mHearingAidActiveDevices; @Before @@ -149,8 +149,8 @@ public class MediaOutputPreferenceControllerTest { mController = new MediaOutputPreferenceController(mContext, TEST_KEY); mScreen = spy(new PreferenceScreen(mContext, null)); - mPreference = new ListPreference(mContext); - mProfileConnectedDevices = new ArrayList<>(); + mPreference = new Preference(mContext); + mProfileConnectableDevices = new ArrayList<>(); mHearingAidActiveDevices = new ArrayList<>(2); when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); @@ -166,61 +166,140 @@ public class MediaOutputPreferenceControllerTest { ShadowBluetoothUtils.reset(); } + /** - * In normal mode, bluetooth device with HisyncId. - * HearingAidProfile should set active device to this device. + * A2DP Bluetooth device(s) are not connected nor previously connected + * Preference should be invisible */ @Test - public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() { + public void updateState_withoutConnectableBtDevice_preferenceInvisible() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mAudioManager.setMode(AudioManager.MODE_NORMAL); - when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); + mProfileConnectableDevices.clear(); + when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + mPreference.setVisible(true); - mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice); - - verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice); - verify(mA2dpProfile, never()).setActiveDevice(mLeftBluetoothHapDevice); + assertThat(mPreference.isVisible()).isTrue(); + mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isFalse(); } /** - * In normal mode, bluetooth device without HisyncId. - * A2dpProfile should set active device to this device. + * A2DP Bluetooth device(s) are connectable, no matter active or inactive + * Preference should be visible */ @Test - public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() { + public void updateState_withConnectableBtDevice_preferenceVisible() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mAudioManager.setMode(AudioManager.MODE_NORMAL); + mProfileConnectableDevices.clear(); + mProfileConnectableDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + assertThat(mPreference.isVisible()).isFalse(); - mController.setActiveBluetoothDevice(mBluetoothDevice); + // Without Active Bluetooth Device + mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isTrue(); - verify(mA2dpProfile).setActiveDevice(mBluetoothDevice); - verify(mHearingAidProfile, never()).setActiveDevice(mBluetoothDevice); + // With Active Bluetooth Device + when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); + mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isTrue(); } /** - * In normal mode, set active device to "this device". - * A2dpProfile should set to null. - * HearingAidProfile should set to null. + * A2DP Bluetooth device(s) are connectable, but no device is set as activated + * Preference summary should be "This device" */ @Test - public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() { + public void updateState_withConnectableBtDevice_withoutActiveBtDevice_setDefaultSummary() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mAudioManager.setMode(AudioManager.MODE_NORMAL); + mProfileConnectableDevices.clear(); + mProfileConnectableDevices.add(mBluetoothDevice); + mProfileConnectableDevices.add(mSecondBluetoothDevice); + when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + when(mA2dpProfile.getActiveDevice()).thenReturn(null); - mController.setActiveBluetoothDevice(null); - - verify(mA2dpProfile).setActiveDevice(null); - verify(mHearingAidProfile).setActiveDevice(null); + assertThat(mPreference.getSummary()).isNull(); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getText(R.string.media_output_default_summary)); } /** - * During a call - * A2dpProfile should not set active device. + * A2DP Bluetooth device(s) are connected and active + * Preference summary should be device's name */ @Test - public void setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile() { - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); + public void updateState_withActiveBtDevice_setActivatedDeviceName() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + mProfileConnectableDevices.clear(); + mProfileConnectableDevices.add(mBluetoothDevice); + mProfileConnectableDevices.add(mSecondBluetoothDevice); + when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); - mController.setActiveBluetoothDevice(mBluetoothDevice); + assertThat(mPreference.getSummary()).isNull(); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); + } - verify(mA2dpProfile, times(0)).setActiveDevice(any(BluetoothDevice.class)); + + /** + * Hearing Aid device(s) are connectable, no matter active or inactive + * Preference should be visible + */ + @Test + public void updateState_withConnectableHADevice_preferenceVisible() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); + assertThat(mPreference.isVisible()).isFalse(); + + // Without Active Hearing Aid Device + mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isTrue(); + + // With Active Hearing Aid Device + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + mController.updateState(mPreference); + assertThat(mPreference.isVisible()).isTrue(); + } + + /** + * Hearing Aid device(s) are connected and active + * Preference summary should be device's name + */ + @Test + public void updateState_withActiveHADevice_setActivatedDeviceName() { + mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + mHearingAidActiveDevices.clear(); + mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); + when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); + + assertThat(mPreference.getSummary()).isNull(); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()).isEqualTo(TEST_HAP_DEVICE_NAME_1); + + } + + @Test + public void click_launch_outputSwitcherSlice() { + final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); + mController.handlePreferenceTreeClick(mPreference); + verify(mContext, never()).startActivity(intentCaptor.capture()); + + mPreference.setKey(TEST_KEY); + mController.handlePreferenceTreeClick(mPreference); + verify(mContext).startActivity(intentCaptor.capture()); + assertThat(intentCaptor.getValue().getAction()) + .isEqualTo(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT); } /** @@ -253,24 +332,6 @@ public class MediaOutputPreferenceControllerTest { mContext.getText(R.string.media_out_summary_ongoing_call_state)); } - /** - * No available A2dp BT devices: - * Preference should be invisible - * Preference summary should be "This device" - */ - @Test - public void updateState_noAvailableA2dpBtDevices_shouldDisableAndSetDefaultSummary() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - List emptyDeviceList = new ArrayList<>(); - when(mA2dpProfile.getConnectedDevices()).thenReturn(emptyDeviceList); - - mController.updateState(mPreference); - - assertThat(mPreference.isVisible()).isFalse(); - String defaultString = mContext.getString(R.string.media_output_default_summary); - assertThat(mPreference.getSummary()).isEqualTo(defaultString); - } - /** * Media stream is captured by something else (cast device): * Preference should be invisible @@ -287,235 +348,6 @@ public class MediaOutputPreferenceControllerTest { assertThat(mPreference.getSummary()).isEqualTo(defaultString); } - /** - * One A2DP Bluetooth device is available and active. - * Preference should be visible - * Preference summary should be the activated device name - */ - @Test - public void updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); - mProfileConnectedDevices.clear(); - mProfileConnectedDevices.add(mBluetoothDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); - when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); - - mController.updateState(mPreference); - - assertThat(mPreference.isVisible()).isTrue(); - assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); - } - - /** - * More than one A2DP 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_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - 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(TEST_DEVICE_NAME_2); - } - - /** - * A2DP Bluetooth device(s) are available, but wired headset is plugged in and activated - * Preference should be visible - * Preference summary should be "This device" - */ - @Test - public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectedDevices.clear(); - mProfileConnectedDevices.add(mBluetoothDevice); - when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); - when(mA2dpProfile.getActiveDevice()).thenReturn(null); - - mController.updateState(mPreference); - - assertThat(mPreference.isVisible()).isTrue(); - assertThat(mPreference.getSummary()).isEqualTo( - mContext.getString(R.string.media_output_default_summary)); - } - - - /** - * A2DP Bluetooth device(s) are available, but current device speaker is activated - * Preference should be visible - * Preference summary should be "This device" - */ - @Test - public void updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectedDevices.clear(); - mProfileConnectedDevices.add(mBluetoothDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); - when(mA2dpProfile.getActiveDevice()).thenReturn(null); - - mController.updateState(mPreference); - - assertThat(mPreference.isVisible()).isTrue(); - 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() { - mAudioManager.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() { - mAudioManager.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() { - mAudioManager.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() { - mAudioManager.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() { - mAudioManager.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); - } - @Test public void findActiveDevice_onlyA2dpDeviceActive_returnA2dpDevice() { when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null);