[Audiosharing] Avoid dup volume control entries
Test: atest Bug: 402384034 Flag: com.android.settingslib.flags.enable_le_audio_sharing Change-Id: I1c975a39106d50746c692586bf682301dd299f40
This commit is contained in:
@@ -277,7 +277,10 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
|
||||
}
|
||||
}
|
||||
|
||||
private void removePreference(BluetoothDevice device) {
|
||||
/**
|
||||
* Remove the {@link Preference} that represents the {@code device}
|
||||
*/
|
||||
protected void removePreference(BluetoothDevice device) {
|
||||
if (mPreferenceMap.containsKey(device)) {
|
||||
if (mPreferenceMap.get(device) instanceof BluetoothDevicePreference preference) {
|
||||
BluetoothDevice prefDevice = preference.getBluetoothDevice().getDevice();
|
||||
@@ -362,7 +365,7 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
|
||||
return mLocalManager.getCachedDeviceManager().getCachedDevicesCopy().contains(cachedDevice);
|
||||
}
|
||||
|
||||
private boolean isDeviceOfMapInCachedDevicesList(BluetoothDevice inputBluetoothDevice) {
|
||||
protected boolean isDeviceOfMapInCachedDevicesList(BluetoothDevice inputBluetoothDevice) {
|
||||
Collection<CachedBluetoothDevice> cachedDevices =
|
||||
mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
|
||||
if (cachedDevices == null || cachedDevices.isEmpty()) {
|
||||
|
@@ -31,7 +31,6 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
|
||||
public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdater
|
||||
implements Preference.OnPreferenceClickListener {
|
||||
@@ -42,7 +41,6 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat
|
||||
static final String PREF_KEY_PREFIX = "audio_sharing_volume_control_";
|
||||
|
||||
@Nullable private final LocalBluetoothManager mBtManager;
|
||||
@Nullable private final VolumeControlProfile mVolumeControl;
|
||||
|
||||
public AudioSharingDeviceVolumeControlUpdater(
|
||||
Context context,
|
||||
@@ -50,10 +48,6 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat
|
||||
int metricsCategory) {
|
||||
super(context, devicePreferenceCallback, metricsCategory);
|
||||
mBtManager = Utils.getLocalBluetoothManager(context);
|
||||
mVolumeControl =
|
||||
mBtManager == null
|
||||
? null
|
||||
: mBtManager.getProfileManager().getVolumeControlProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,6 +93,40 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPreference() {
|
||||
mPreferenceMap.forEach((key, preference) -> {
|
||||
if (isDeviceOfMapInCachedDevicesList(key)) {
|
||||
((AudioSharingDeviceVolumePreference) preference).onPreferenceAttributesChanged();
|
||||
} else {
|
||||
// Remove staled preference.
|
||||
Log.d(TAG, "removePreference key: " + key.getAnonymizedAddress());
|
||||
removePreference(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removePreference(BluetoothDevice device) {
|
||||
if (mPreferenceMap.containsKey(device)) {
|
||||
if (mPreferenceMap.get(device) instanceof AudioSharingDeviceVolumePreference pref) {
|
||||
BluetoothDevice prefDevice = pref.getCachedDevice().getDevice();
|
||||
// For CSIP device, when it {@link CachedBluetoothDevice}#switchMemberDeviceContent,
|
||||
// it will change its mDevice and lead to the hashcode change for this preference.
|
||||
// This will cause unintended remove preference, see b/394765052
|
||||
if (device.equals(prefDevice) || !mPreferenceMap.containsKey(prefDevice)) {
|
||||
mDevicePreferenceCallback.onDeviceRemoved(pref);
|
||||
} else {
|
||||
Log.w(TAG, "Inconsistent key and preference when removePreference");
|
||||
}
|
||||
mPreferenceMap.remove(device);
|
||||
} else {
|
||||
mDevicePreferenceCallback.onDeviceRemoved(mPreferenceMap.get(device));
|
||||
mPreferenceMap.remove(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPreferenceKeyPrefix() {
|
||||
return PREF_KEY_PREFIX;
|
||||
@@ -121,7 +149,4 @@ public class AudioSharingDeviceVolumeControlUpdater extends BluetoothDeviceUpdat
|
||||
|
||||
@Override
|
||||
protected void launchDeviceDetails(Preference preference) {}
|
||||
|
||||
@Override
|
||||
public void refreshPreference() {}
|
||||
}
|
||||
|
@@ -368,6 +368,7 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
|
||||
mAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
|
||||
mVolumeControl.registerCallback(mExecutor, mVolumeControlCallback);
|
||||
mBluetoothDeviceUpdater.registerCallback();
|
||||
mBluetoothDeviceUpdater.refreshPreference();
|
||||
mContentResolver.registerContentObserver(
|
||||
Settings.Secure.getUriFor(BluetoothUtils.getPrimaryGroupIdUriForBroadcast()),
|
||||
false,
|
||||
|
@@ -104,6 +104,39 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference {
|
||||
handleProgressChange(seekBar.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if ((o == null) || !(o instanceof AudioSharingDeviceVolumePreference)) {
|
||||
return false;
|
||||
}
|
||||
return mCachedDevice.equals(
|
||||
((AudioSharingDeviceVolumePreference) o).mCachedDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mCachedDevice.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("Preference{");
|
||||
builder.append("preference=").append(super.toString());
|
||||
if (mCachedDevice.getDevice() != null) {
|
||||
builder.append(", device=").append(mCachedDevice.getDevice().getAnonymizedAddress());
|
||||
}
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
void onPreferenceAttributesChanged() {
|
||||
var unused = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
String name = mCachedDevice.getName();
|
||||
AudioSharingUtils.postOnMainThread(mContext, () -> setTitle(name));
|
||||
});
|
||||
}
|
||||
|
||||
private void handleProgressChange(int progress) {
|
||||
var unused =
|
||||
ThreadUtils.postOnBackgroundThread(
|
||||
|
@@ -515,9 +515,10 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
mAudioManager.setMode(audioMode);
|
||||
mBluetoothDeviceUpdater =
|
||||
spy(new AvailableMediaBluetoothDeviceUpdater(
|
||||
mContext, mDevicePreferenceCallback, /* metricsCategory= */ 0));
|
||||
mContext, mDevicePreferenceCallback, /* metricsCategory= */ 0));
|
||||
mBluetoothDeviceUpdater.setPrefContext(mContext);
|
||||
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(
|
||||
any(CachedBluetoothDevice.class));
|
||||
}
|
||||
}
|
||||
|
@@ -429,6 +429,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
mDevicePreferenceCallback, /* metricsCategory= */ 0));
|
||||
mBluetoothDeviceUpdater.setPrefContext(mContext);
|
||||
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(
|
||||
any(CachedBluetoothDevice.class));
|
||||
}
|
||||
}
|
||||
|
@@ -106,7 +106,8 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
false, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
|
||||
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
|
||||
doNothing().when(mBluetoothDeviceUpdater).removePreference(
|
||||
any(CachedBluetoothDevice.class));
|
||||
mCachedDevices.add(mCachedBluetoothDevice);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
|
||||
|
@@ -22,7 +22,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -74,13 +73,14 @@ import java.util.List;
|
||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
||||
public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
private static final String TEST_DEVICE_NAME = "test";
|
||||
private static final String TEST_DEVICE_ADDRESS = "XX:XX:XX:XX:XX:11";
|
||||
private static final String TAG = "AudioSharingVolUpdater";
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock private DevicePreferenceCallback mDevicePreferenceCallback;
|
||||
@Mock private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
@Mock private BluetoothDevice mBluetoothDevice;
|
||||
@Mock private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock private BluetoothDevice mDevice;
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
|
||||
@@ -104,11 +104,12 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
List<Long> bisSyncState = new ArrayList<>();
|
||||
bisSyncState.add(1L);
|
||||
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||
doReturn(TEST_DEVICE_NAME).when(mCachedBluetoothDevice).getName();
|
||||
doReturn(mBluetoothDevice).when(mCachedBluetoothDevice).getDevice();
|
||||
doReturn(ImmutableSet.of()).when(mCachedBluetoothDevice).getMemberDevice();
|
||||
when(mDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||
when(mCachedDevice.getName()).thenReturn(TEST_DEVICE_NAME);
|
||||
when(mCachedDevice.getDevice()).thenReturn(mDevice);
|
||||
when(mCachedDevice.getMemberDevice()).thenReturn(ImmutableSet.of());
|
||||
mCachedDevices = new ArrayList<>();
|
||||
mCachedDevices.add(mCachedBluetoothDevice);
|
||||
mCachedDevices.add(mCachedDevice);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
|
||||
doNothing().when(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
|
||||
doNothing().when(mDevicePreferenceCallback).onDeviceRemoved(any(Preference.class));
|
||||
@@ -128,7 +129,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
public void onProfileConnectionStateChanged_leaDeviceConnected_noSharing_removesPref() {
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -137,7 +138,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -145,23 +146,23 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_leaDeviceConnected_noSource_removesPref() {
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(ImmutableList.of());
|
||||
when(mAssistant.getAllSources(mDevice)).thenReturn(ImmutableList.of());
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -169,14 +170,14 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_deviceIsNotInList_removesPref() {
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -186,7 +187,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -194,14 +195,14 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_leaDeviceDisconnected_removesPref() {
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -210,7 +211,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_DISCONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -218,23 +219,23 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_leaDeviceDisconnecting_removesPref() {
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(false);
|
||||
when(mCachedDevice.isConnectedLeAudioDevice()).thenReturn(false);
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -242,7 +243,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -250,7 +251,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
setupPreferenceMapWithDevice();
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -258,17 +259,17 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_hasLeaMemberConnected_hasSource_addsPreference() {
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
setupPreferenceMapWithDevice();
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(false);
|
||||
when(mCachedBluetoothDevice.hasConnectedLeAudioMemberDevice()).thenReturn(true);
|
||||
when(mCachedDevice.isConnectedLeAudioDevice()).thenReturn(false);
|
||||
when(mCachedDevice.hasConnectedLeAudioMemberDevice()).thenReturn(true);
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
@@ -276,7 +277,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
assertThat(((AudioSharingDeviceVolumePreference) captor.getValue()).getCachedDevice())
|
||||
.isEqualTo(mCachedBluetoothDevice);
|
||||
.isEqualTo(mCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -292,7 +293,7 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
@Test
|
||||
public void addPreferenceWithSortType_doNothing() {
|
||||
mDeviceUpdater.addPreference(
|
||||
mCachedBluetoothDevice, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
|
||||
mCachedDevice, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
|
||||
// Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
|
||||
// trigger add preference.
|
||||
verifyNoInteractions(mDevicePreferenceCallback);
|
||||
@@ -308,27 +309,118 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshPreference_doNothing() {
|
||||
public void refreshPreference_havePreference_refresh() {
|
||||
setupPreferenceMapWithDevice();
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedBluetoothDevice,
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
AudioSharingDeviceVolumePreference preference =
|
||||
(AudioSharingDeviceVolumePreference) captor.getValue();
|
||||
|
||||
when(mCachedDevice.getName()).thenReturn("new");
|
||||
mDeviceUpdater.refreshPreference();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertThat(preference.getTitle().toString()).isEqualTo("new");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshPreference_staledPreference_remove() {
|
||||
setupPreferenceMapWithDevice();
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
AudioSharingDeviceVolumePreference preference =
|
||||
(AudioSharingDeviceVolumePreference) captor.getValue();
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
|
||||
mDeviceUpdater.refreshPreference();
|
||||
// Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
|
||||
// refresh preference map
|
||||
verify(mDevicePreferenceCallback, never()).onDeviceRemoved(any(Preference.class));
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshPreference_inconsistentPreference_doNothing() {
|
||||
setupPreferenceMapWithDevice();
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
CachedBluetoothDevice subCachedDevice = mock(CachedBluetoothDevice.class);
|
||||
BluetoothDevice subDevice = mock(BluetoothDevice.class);
|
||||
when(subDevice.getAddress()).thenReturn("XX:XX:XX:XX:XX:22");
|
||||
when(subCachedDevice.getDevice()).thenReturn(subDevice);
|
||||
when(mCachedDevice.getMemberDevice()).thenReturn(ImmutableSet.of(subCachedDevice));
|
||||
when(subCachedDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mAssistant.getAllSources(subDevice)).thenReturn(ImmutableList.of(mState));
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
AudioSharingDeviceVolumePreference preference =
|
||||
(AudioSharingDeviceVolumePreference) captor.getValue();
|
||||
|
||||
// Main device disconnected, CSIP switches the content of main and member.
|
||||
when(mCachedDevice.isConnectedLeAudioDevice()).thenReturn(false);
|
||||
when(mCachedDevice.getDevice()).thenReturn(subDevice);
|
||||
when(subCachedDevice.getDevice()).thenReturn(mDevice);
|
||||
when(mCachedDevice.getMemberDevice()).thenReturn(ImmutableSet.of());
|
||||
when(subCachedDevice.getMemberDevice()).thenReturn(ImmutableSet.of(subCachedDevice));
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||
ImmutableList.of(subCachedDevice));
|
||||
|
||||
// New main device is added, its preference won't be added to the preference group because
|
||||
// it equals to previous preference for the old main device.
|
||||
mDeviceUpdater.onDeviceAdded(subCachedDevice);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
mDeviceUpdater.refreshPreference();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
// The preference should not be removed after refresh the preference group.
|
||||
verify(mDevicePreferenceCallback, never()).onDeviceRemoved(preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshPreference_staledInconsistentPreference_remove() {
|
||||
setupPreferenceMapWithDevice();
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
mDeviceUpdater.onProfileConnectionStateChanged(
|
||||
mCachedDevice,
|
||||
BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.LE_AUDIO);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
|
||||
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
|
||||
AudioSharingDeviceVolumePreference preference =
|
||||
(AudioSharingDeviceVolumePreference) captor.getValue();
|
||||
|
||||
BluetoothDevice subDevice = mock(BluetoothDevice.class);
|
||||
when(subDevice.getAddress()).thenReturn("XX:XX:XX:XX:XX:22");
|
||||
when(mCachedDevice.getDevice()).thenReturn(subDevice);
|
||||
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
|
||||
mDeviceUpdater.refreshPreference();
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(preference);
|
||||
}
|
||||
|
||||
private void setupPreferenceMapWithDevice() {
|
||||
// Add device to preferenceMap
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(ImmutableList.of(mState));
|
||||
when(mAssistant.getAllSources(mDevice)).thenReturn(ImmutableList.of(mState));
|
||||
when(mDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mCachedDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
}
|
||||
}
|
||||
|
@@ -21,16 +21,19 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
@@ -44,12 +47,15 @@ import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LeAudioProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -63,6 +69,8 @@ import org.robolectric.annotation.Config;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
||||
public class AudioSharingDeviceVolumePreferenceTest {
|
||||
private static final String TEST_DEVICE_NAME = "test";
|
||||
private static final String TEST_DEVICE_ADDRESS = "XX:XX:XX:XX:XX:11";
|
||||
private static final int TEST_DEVICE_GROUP_ID = 1;
|
||||
private static final int TEST_VOLUME_VALUE = 255;
|
||||
private static final int TEST_MAX_STREAM_VALUE = 10;
|
||||
@@ -74,6 +82,7 @@ public class AudioSharingDeviceVolumePreferenceTest {
|
||||
@Mock private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
|
||||
@Mock private LeAudioProfile mLeAudioProfile;
|
||||
@Mock private CachedBluetoothDeviceManager mDeviceManager;
|
||||
@Mock private VolumeControlProfile mVolumeControl;
|
||||
@Mock private CachedBluetoothDevice mCachedDevice;
|
||||
@Mock private BluetoothDevice mDevice;
|
||||
@@ -92,13 +101,17 @@ public class AudioSharingDeviceVolumePreferenceTest {
|
||||
when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
|
||||
when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
|
||||
when(mLocalBtProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
|
||||
when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
|
||||
when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
|
||||
.thenReturn(TEST_MAX_STREAM_VALUE);
|
||||
when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
|
||||
.thenReturn(TEST_MIN_STREAM_VALUE);
|
||||
when(mDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||
when(mCachedDevice.getName()).thenReturn(TEST_DEVICE_NAME);
|
||||
when(mCachedDevice.getDevice()).thenReturn(mDevice);
|
||||
when(mCachedDevice.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of(mCachedDevice));
|
||||
when(mSeekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
|
||||
mPreference = new AudioSharingDeviceVolumePreference(mContext, mCachedDevice);
|
||||
}
|
||||
@@ -305,4 +318,39 @@ public class AudioSharingDeviceVolumePreferenceTest {
|
||||
eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME),
|
||||
anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_returnsTrue() {
|
||||
AudioSharingDeviceVolumePreference preference = new AudioSharingDeviceVolumePreference(
|
||||
mContext, mCachedDevice);
|
||||
assertThat(mPreference.equals(preference)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_returnsFalse() {
|
||||
CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
||||
AudioSharingDeviceVolumePreference preference = new AudioSharingDeviceVolumePreference(
|
||||
mContext, cachedDevice);
|
||||
assertThat(mPreference.equals(preference)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toString_correctValue() {
|
||||
mPreference.setTitle(TEST_DEVICE_NAME);
|
||||
StringBuilder builder = new StringBuilder("Preference{");
|
||||
builder.append("preference=").append(TEST_DEVICE_NAME);
|
||||
when(mDevice.getAnonymizedAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||
builder.append(", device=").append(TEST_DEVICE_ADDRESS);
|
||||
builder.append("}");
|
||||
assertThat(mPreference.toString()).isEqualTo(builder.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceAttributesChanged_nameChanged_updatePreference() {
|
||||
when(mCachedDevice.getName()).thenReturn("new");
|
||||
mPreference.onPreferenceAttributesChanged();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo("new");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user