[Audiosharing] Increase audio sharing test coverage

Bug: 345686602
Test: atest
Change-Id: Iec196fc884c3b7ddd580eb8dd13b445d59e3b1b7
This commit is contained in:
Yiyi Shen
2024-06-13 18:29:23 +08:00
parent 44de7e98d3
commit 2c6b9bb364
14 changed files with 577 additions and 101 deletions

View File

@@ -72,7 +72,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
private static final String PREF_KEY = "calls_and_alarms"; private static final String PREF_KEY = "calls_and_alarms";
@VisibleForTesting @VisibleForTesting
protected enum ChangeCallAudioType { enum ChangeCallAudioType {
UNKNOWN, UNKNOWN,
CONNECTED_EARLIER, CONNECTED_EARLIER,
CONNECTED_LATER CONNECTED_LATER
@@ -90,7 +90,9 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>(); Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>(); private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
@VisibleForTesting
final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() { new BluetoothLeBroadcastAssistant.Callback() {
@Override @Override
public void onSearchStarted(int reason) {} public void onSearchStarted(int reason) {}
@@ -276,7 +278,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
/** Test only: set callback registration status in tests. */ /** Test only: set callback registration status in tests. */
@VisibleForTesting @VisibleForTesting
public void setCallbacksRegistered(boolean registered) { void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered); mCallbacksRegistered.set(registered);
} }
@@ -385,7 +387,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
} }
@VisibleForTesting @VisibleForTesting
protected void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) { void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) {
var unused = var unused =
ThreadUtils.postOnBackgroundThread( ThreadUtils.postOnBackgroundThread(
() -> { () -> {

View File

@@ -87,7 +87,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
@Nullable private AudioSharingDialogHandler mDialogHandler; @Nullable private AudioSharingDialogHandler mDialogHandler;
private AtomicBoolean mIntentHandled = new AtomicBoolean(false); private AtomicBoolean mIntentHandled = new AtomicBoolean(false);
private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback = @VisibleForTesting
BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() { new BluetoothLeBroadcastAssistant.Callback() {
@Override @Override
public void onSearchStarted(int reason) {} public void onSearchStarted(int reason) {}
@@ -368,23 +369,23 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
} }
@VisibleForTesting @VisibleForTesting
public void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) { void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
mBluetoothDeviceUpdater = bluetoothDeviceUpdater; mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
} }
@VisibleForTesting @VisibleForTesting
public void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) { void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
mDialogHandler = dialogHandler; mDialogHandler = dialogHandler;
} }
@VisibleForTesting @VisibleForTesting
public void setHostFragment(@Nullable DashboardFragment fragment) { void setHostFragment(@Nullable DashboardFragment fragment) {
mFragment = fragment; mFragment = fragment;
} }
/** Test only: set intent handle state for test. */ /** Test only: set intent handle state for test. */
@VisibleForTesting @VisibleForTesting
public void setIntentHandled(boolean handled) { void setIntentHandled(boolean handled) {
mIntentHandled.set(handled); mIntentHandled.set(handled);
} }

View File

@@ -79,12 +79,9 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
private Map<Integer, Integer> mValueMap = new HashMap<Integer, Integer>(); private Map<Integer, Integer> mValueMap = new HashMap<Integer, Integer>();
private AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
private BluetoothVolumeControl.Callback mVolumeControlCallback = @VisibleForTesting
BluetoothVolumeControl.Callback mVolumeControlCallback =
new BluetoothVolumeControl.Callback() { new BluetoothVolumeControl.Callback() {
@Override
public void onVolumeOffsetChanged(
@NonNull BluetoothDevice device, int volumeOffset) {}
@Override @Override
public void onDeviceVolumeChanged( public void onDeviceVolumeChanged(
@NonNull BluetoothDevice device, @NonNull BluetoothDevice device,
@@ -117,7 +114,8 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
} }
}; };
private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback = @VisibleForTesting
BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() { new BluetoothLeBroadcastAssistant.Callback() {
@Override @Override
public void onSearchStarted(int reason) {} public void onSearchStarted(int reason) {}
@@ -323,26 +321,26 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
} }
@VisibleForTesting @VisibleForTesting
public void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) { void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) {
mBluetoothDeviceUpdater = updater; mBluetoothDeviceUpdater = updater;
} }
/** Test only: set callback registration status in tests. */ /** Test only: set callback registration status in tests. */
@VisibleForTesting @VisibleForTesting
public void setCallbacksRegistered(boolean registered) { void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered); mCallbacksRegistered.set(registered);
} }
/** Test only: set volume map in tests. */ /** Test only: set volume map in tests. */
@VisibleForTesting @VisibleForTesting
public void setVolumeMap(@Nullable Map<Integer, Integer> map) { void setVolumeMap(@Nullable Map<Integer, Integer> map) {
mValueMap.clear(); mValueMap.clear();
mValueMap.putAll(map); mValueMap.putAll(map);
} }
/** Test only: set value for private preferenceGroup in tests. */ /** Test only: set value for private preferenceGroup in tests. */
@VisibleForTesting @VisibleForTesting
public void setPreferenceGroup(@Nullable PreferenceGroup group) { void setPreferenceGroup(@Nullable PreferenceGroup group) {
mPreferenceGroup = group; mPreferenceGroup = group;
mPreference = group; mPreference = group;
} }

View File

@@ -345,4 +345,6 @@ public class AudioSharingDialogFactory {
return dialog; return dialog;
} }
} }
private AudioSharingDialogFactory() {}
} }

View File

@@ -28,6 +28,7 @@ import android.util.Pair;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@@ -61,7 +62,8 @@ public class AudioSharingDialogHandler {
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private List<BluetoothDevice> mTargetSinks = new ArrayList<>(); private List<BluetoothDevice> mTargetSinks = new ArrayList<>();
private final BluetoothLeBroadcast.Callback mBroadcastCallback = @VisibleForTesting
final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() { new BluetoothLeBroadcast.Callback() {
@Override @Override
public void onBroadcastStarted(int reason, int broadcastId) { public void onBroadcastStarted(int reason, int broadcastId) {

View File

@@ -145,9 +145,17 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag
return sNewDevice; return sNewDevice;
} }
/** Test only: get the {@link DialogEventListener} passed to the dialog. */
@VisibleForTesting
@Nullable
DialogEventListener getListener() {
return sListener;
}
/** Test only: get the event data passed to the dialog. */ /** Test only: get the event data passed to the dialog. */
@VisibleForTesting @VisibleForTesting
protected @NonNull Pair<Integer, Object>[] getEventData() { @NonNull
Pair<Integer, Object>[] getEventData() {
return sEventData; return sEventData;
} }

View File

@@ -110,9 +110,17 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment {
return sNewDevice; return sNewDevice;
} }
/** Test only: get the {@link DialogEventListener} passed to the dialog. */
@VisibleForTesting
@Nullable
DialogEventListener getListener() {
return sListener;
}
/** Test only: get the event data passed to the dialog. */ /** Test only: get the event data passed to the dialog. */
@VisibleForTesting @VisibleForTesting
protected @NonNull Pair<Integer, Object>[] getEventData() { @NonNull
Pair<Integer, Object>[] getEventData() {
return sEventData; return sEventData;
} }

View File

@@ -117,7 +117,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
}; };
@VisibleForTesting @VisibleForTesting
protected final BluetoothLeBroadcast.Callback mBroadcastCallback = final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() { new BluetoothLeBroadcast.Callback() {
@Override @Override
public void onBroadcastStarted(int reason, int broadcastId) { public void onBroadcastStarted(int reason, int broadcastId) {
@@ -392,7 +392,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
/** Test only: set callback registration status in tests. */ /** Test only: set callback registration status in tests. */
@VisibleForTesting @VisibleForTesting
public void setCallbacksRegistered(boolean registered) { void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered); mCallbacksRegistered.set(registered);
} }

View File

@@ -25,7 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
@@ -35,6 +35,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
@@ -130,6 +131,7 @@ public class AudioSharingCallAudioPreferenceControllerTest {
@Mock private CachedBluetoothDevice mCachedDevice2; @Mock private CachedBluetoothDevice mCachedDevice2;
@Mock private CachedBluetoothDevice mCachedDevice3; @Mock private CachedBluetoothDevice mCachedDevice3;
@Mock private BluetoothLeBroadcastReceiveState mState; @Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private ContentResolver mContentResolver; @Mock private ContentResolver mContentResolver;
private AudioSharingCallAudioPreferenceController mController; private AudioSharingCallAudioPreferenceController mController;
@Spy private ContentObserver mContentObserver; @Spy private ContentObserver mContentObserver;
@@ -183,13 +185,13 @@ public class AudioSharingCallAudioPreferenceControllerTest {
public void onStart_flagOff_doNothing() { public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mBtEventManager, times(0)).registerCallback(mController); verify(mBtEventManager, never()).registerCallback(mController);
verify(mContentResolver, times(0)) verify(mContentResolver, never())
.registerContentObserver( .registerContentObserver(
Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID), Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
false, false,
mContentObserver); mContentObserver);
verify(mAssistant, times(0)) verify(mAssistant, never())
.registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class)); .registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class));
} }
@@ -212,9 +214,9 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(true); mController.setCallbacksRegistered(true);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mBtEventManager, times(0)).unregisterCallback(mController); verify(mBtEventManager, never()).unregisterCallback(mController);
verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver); verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
} }
@@ -223,9 +225,9 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(false); mController.setCallbacksRegistered(false);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mBtEventManager, times(0)).unregisterCallback(mController); verify(mBtEventManager, never()).unregisterCallback(mController);
verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver); verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
} }
@@ -500,4 +502,80 @@ public class AudioSharingCallAudioPreferenceControllerTest {
AudioSharingCallAudioPreferenceController.ChangeCallAudioType.UNKNOWN AudioSharingCallAudioPreferenceController.ChangeCallAudioType.UNKNOWN
.ordinal()); .ordinal());
} }
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_updateSummary() {
when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
Settings.Secure.putInt(
mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
when(mBroadcast.isEnabled(any())).thenReturn(true);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(ImmutableList.of());
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString()).isEmpty();
// onReceiveStateChanged will update summary
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(ImmutableList.of(mDevice1));
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString())
.isEqualTo(
mContext.getString(
R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
}
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
Settings.Secure.putInt(
mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
when(mBroadcast.isEnabled(any())).thenReturn(true);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(ImmutableList.of());
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString()).isEmpty();
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(ImmutableList.of(mDevice1));
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoved(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModified(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModifyFailed(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceFound(mSource);
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
// Above callbacks won't update summary.
assertThat(mPreference.getSummary().toString()).isEmpty();
}
} }

View File

@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -35,6 +36,8 @@ import static org.robolectric.Shadows.shadowOf;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
@@ -85,6 +88,8 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow; import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@@ -113,6 +118,8 @@ public class AudioSharingDevicePreferenceControllerTest {
@Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothLeBroadcast mBroadcast;
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant; @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private VolumeControlProfile mVolumeControl; @Mock private VolumeControlProfile mVolumeControl;
@Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private PreferenceScreen mScreen; @Mock private PreferenceScreen mScreen;
@Mock private AudioSharingDialogHandler mDialogHandler; @Mock private AudioSharingDialogHandler mDialogHandler;
@Mock private DashboardFragment mFragment; @Mock private DashboardFragment mFragment;
@@ -177,13 +184,13 @@ public class AudioSharingDevicePreferenceControllerTest {
public void onStart_flagOff_doNothing() { public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mEventManager, times(0)).registerCallback(any(BluetoothCallback.class)); verify(mEventManager, never()).registerCallback(any(BluetoothCallback.class));
verify(mDialogHandler, times(0)).registerCallbacks(any(Executor.class)); verify(mDialogHandler, never()).registerCallbacks(any(Executor.class));
verify(mAssistant, times(0)) verify(mAssistant, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class)); any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBluetoothDeviceUpdater, times(0)).registerCallback(); verify(mBluetoothDeviceUpdater, never()).registerCallback();
verify(mBluetoothDeviceUpdater, times(0)).refreshPreference(); verify(mBluetoothDeviceUpdater, never()).refreshPreference();
} }
@Test @Test
@@ -203,11 +210,11 @@ public class AudioSharingDevicePreferenceControllerTest {
public void onStop_flagOff_doNothing() { public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mEventManager, times(0)).unregisterCallback(any(BluetoothCallback.class)); verify(mEventManager, never()).unregisterCallback(any(BluetoothCallback.class));
verify(mDialogHandler, times(0)).unregisterCallbacks(); verify(mDialogHandler, never()).unregisterCallbacks();
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBluetoothDeviceUpdater, times(0)).unregisterCallback(); verify(mBluetoothDeviceUpdater, never()).unregisterCallback();
} }
@Test @Test
@@ -227,7 +234,7 @@ public class AudioSharingDevicePreferenceControllerTest {
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse(); assertThat(mPreferenceGroup.isVisible()).isFalse();
assertThat(mAudioSharingPreference.isVisible()).isFalse(); assertThat(mAudioSharingPreference.isVisible()).isFalse();
verify(mBluetoothDeviceUpdater, times(0)).forceUpdate(); verify(mBluetoothDeviceUpdater, never()).forceUpdate();
} }
@Test @Test
@@ -401,8 +408,8 @@ public class AudioSharingDevicePreferenceControllerTest {
doReturn(intent).when(mActivity).getIntent(); doReturn(intent).when(mActivity).getIntent();
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class)); verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
verify(mDialogHandler, times(0)) verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean()); .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
} }
@@ -418,8 +425,8 @@ public class AudioSharingDevicePreferenceControllerTest {
when(mDevice.isConnected()).thenReturn(false); when(mDevice.isConnected()).thenReturn(false);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class)); verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
verify(mDialogHandler, times(0)) verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean()); .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
} }
@@ -436,8 +443,8 @@ public class AudioSharingDevicePreferenceControllerTest {
mController.setIntentHandled(true); mController.setIntentHandled(true);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class)); verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
verify(mDialogHandler, times(0)) verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean()); .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
} }
@@ -484,4 +491,56 @@ public class AudioSharingDevicePreferenceControllerTest {
verify(mDialogHandler).handleDeviceConnected(mCachedDevice, true); verify(mDialogHandler).handleDeviceConnected(mCachedDevice, true);
} }
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
// onReceiveStateChanged with unconnected state will do nothing
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice, /* sourceId= */ 1, mState);
shadowOf(Looper.getMainLooper()).idle();
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
verify(mDialogHandler, never()).closeOpeningDialogsForLeaDevice(mCachedDevice);
// onReceiveStateChanged with connected state will update group preference and handle
// stale dialogs
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice, /* sourceId= */ 1, mState);
shadowOf(Looper.getMainLooper()).idle();
verify(mBluetoothDeviceUpdater).forceUpdate();
verify(mDialogHandler).closeOpeningDialogsForLeaDevice(mCachedDevice);
// onSourceRemoved will update group preference
mController.mBroadcastAssistantCallback.onSourceRemoved(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
verify(mBluetoothDeviceUpdater, times(2)).forceUpdate();
}
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModified(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModifyFailed(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceFound(mSource);
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
// Above callbacks won't update group preference
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
}
} }

View File

@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
@@ -41,6 +42,7 @@ import android.widget.SeekBar;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.BluetoothDevicePreference;
import com.android.settings.bluetooth.Utils; import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
@@ -80,6 +82,9 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
private static final String TEST_SETTINGS_KEY = private static final String TEST_SETTINGS_KEY =
"bluetooth_le_broadcast_fallback_active_group_id"; "bluetooth_le_broadcast_fallback_active_group_id";
private static final int TEST_DEVICE_GROUP_ID = 1; 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;
private static final int TEST_MIN_STREAM_VALUE = 0;
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -249,10 +254,11 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
(AudioSharingDeviceVolumePreference) captor.getValue(); (AudioSharingDeviceVolumePreference) captor.getValue();
SeekBar seekBar = mock(SeekBar.class); SeekBar seekBar = mock(SeekBar.class);
when(seekBar.getProgress()).thenReturn(255); when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
preference.onStopTrackingTouch(seekBar); preference.onStopTrackingTouch(seekBar);
verify(mVolumeControl).setDeviceVolume(mBluetoothDevice, 255, true); verify(mVolumeControl)
.setDeviceVolume(mBluetoothDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
verifyNoInteractions(mAudioManager); verifyNoInteractions(mAudioManager);
verify(mFeatureFactory.metricsFeatureProvider) verify(mFeatureFactory.metricsFeatureProvider)
.action( .action(
@@ -273,14 +279,17 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
Settings.Secure.putInt( Settings.Secure.putInt(
mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID); mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID);
when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(10); when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)).thenReturn(0); .thenReturn(TEST_MAX_STREAM_VALUE);
when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
.thenReturn(TEST_MIN_STREAM_VALUE);
SeekBar seekBar = mock(SeekBar.class); SeekBar seekBar = mock(SeekBar.class);
when(seekBar.getProgress()).thenReturn(255); when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
preference.onStopTrackingTouch(seekBar); preference.onStopTrackingTouch(seekBar);
verifyNoInteractions(mVolumeControl); verifyNoInteractions(mVolumeControl);
verify(mAudioManager).setStreamVolume(AudioManager.STREAM_MUSIC, 10, 0); verify(mAudioManager)
.setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
verify(mFeatureFactory.metricsFeatureProvider) verify(mFeatureFactory.metricsFeatureProvider)
.action( .action(
mContext, mContext,
@@ -288,6 +297,22 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
/* isPrimary= */ true); /* isPrimary= */ true);
} }
@Test
public void testOnSeekBarChangeListener_doNothing() {
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
setupPreferenceMapWithDevice();
verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
AudioSharingDeviceVolumePreference preference =
(AudioSharingDeviceVolumePreference) captor.getValue();
SeekBar seekBar = mock(SeekBar.class);
preference.onProgressChanged(seekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
verifyNoInteractions(mAudioManager);
verifyNoInteractions(mVolumeControl);
}
@Test @Test
public void getLogTag_returnsCorrectTag() { public void getLogTag_returnsCorrectTag() {
assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG); assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG);
@@ -298,6 +323,35 @@ public class AudioSharingDeviceVolumeControlUpdaterTest {
assertThat(mDeviceUpdater.getPreferenceKey()).isEqualTo(PREF_KEY); assertThat(mDeviceUpdater.getPreferenceKey()).isEqualTo(PREF_KEY);
} }
@Test
public void addPreferenceWithSortType_doNothing() {
mDeviceUpdater.addPreference(
mCachedBluetoothDevice, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
// Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
// trigger add preference.
verifyNoInteractions(mDevicePreferenceCallback);
}
@Test
public void launchDeviceDetails_doNothing() {
Preference preference = mock(Preference.class);
mDeviceUpdater.launchDeviceDetails(preference);
// Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
// launch device details
verifyNoInteractions(preference);
}
@Test
public void refreshPreference_doNothing() {
setupPreferenceMapWithDevice();
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));
}
private void setupPreferenceMapWithDevice() { private void setupPreferenceMapWithDevice() {
// Add device to preferenceMap // Add device to preferenceMap
when(mBroadcast.isEnabled(null)).thenReturn(true); when(mBroadcast.isEnabled(null)).thenReturn(true);

View File

@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -34,6 +35,8 @@ import static org.robolectric.Shadows.shadowOf;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothVolumeControl; import android.bluetooth.BluetoothVolumeControl;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -81,6 +84,8 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow; import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@@ -114,6 +119,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
@Mock private LocalBluetoothProfileManager mProfileManager; @Mock private LocalBluetoothProfileManager mProfileManager;
@Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothLeBroadcast mBroadcast;
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant; @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater; @Mock private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater;
@Mock private VolumeControlProfile mVolumeControl; @Mock private VolumeControlProfile mVolumeControl;
@Mock private PreferenceScreen mScreen; @Mock private PreferenceScreen mScreen;
@@ -164,6 +171,7 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
doReturn(TEST_DEVICE_GROUP_ID1).when(mCachedDevice1).getGroupId(); doReturn(TEST_DEVICE_GROUP_ID1).when(mCachedDevice1).getGroupId();
doReturn(mDevice1).when(mCachedDevice1).getDevice(); doReturn(mDevice1).when(mCachedDevice1).getDevice();
doReturn(ImmutableSet.of()).when(mCachedDevice1).getMemberDevice(); doReturn(ImmutableSet.of()).when(mCachedDevice1).getMemberDevice();
when(mCachedDeviceManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
when(mPreference1.getCachedDevice()).thenReturn(mCachedDevice1); when(mPreference1.getCachedDevice()).thenReturn(mCachedDevice1);
doReturn(TEST_DEVICE_NAME2).when(mCachedDevice2).getName(); doReturn(TEST_DEVICE_NAME2).when(mCachedDevice2).getName();
doReturn(TEST_DEVICE_GROUP_ID2).when(mCachedDevice2).getGroupId(); doReturn(TEST_DEVICE_GROUP_ID2).when(mCachedDevice2).getGroupId();
@@ -185,13 +193,13 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
public void onStart_flagOff_doNothing() { public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mAssistant, times(0)) verify(mAssistant, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class)); any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mDeviceUpdater, times(0)).registerCallback(); verify(mDeviceUpdater, never()).registerCallback();
verify(mVolumeControl, times(0)) verify(mVolumeControl, never())
.registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class)); .registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
verify(mContentResolver, times(0)) verify(mContentResolver, never())
.registerContentObserver( .registerContentObserver(
Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID), Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
false, false,
@@ -215,16 +223,33 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mContentObserver); mContentObserver);
} }
@Test
public void onAudioSharingProfilesConnected_flagOn_registerCallbacks() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onAudioSharingProfilesConnected();
verify(mAssistant)
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mDeviceUpdater).registerCallback();
verify(mVolumeControl)
.registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
verify(mContentResolver)
.registerContentObserver(
Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
false,
mContentObserver);
}
@Test @Test
public void onStop_flagOff_doNothing() { public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mDeviceUpdater, times(0)).unregisterCallback(); verify(mDeviceUpdater, never()).unregisterCallback();
verify(mVolumeControl, times(0)) verify(mVolumeControl, never())
.unregisterCallback(any(BluetoothVolumeControl.Callback.class)); .unregisterCallback(any(BluetoothVolumeControl.Callback.class));
verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver); verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
} }
@Test @Test
@@ -232,12 +257,12 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(false); mController.setCallbacksRegistered(false);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mDeviceUpdater, times(0)).unregisterCallback(); verify(mDeviceUpdater, never()).unregisterCallback();
verify(mVolumeControl, times(0)) verify(mVolumeControl, never())
.unregisterCallback(any(BluetoothVolumeControl.Callback.class)); .unregisterCallback(any(BluetoothVolumeControl.Callback.class));
verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver); verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
} }
@Test @Test
@@ -257,7 +282,7 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse(); assertThat(mPreferenceGroup.isVisible()).isFalse();
verify(mDeviceUpdater, times(0)).forceUpdate(); verify(mDeviceUpdater, never()).forceUpdate();
} }
@Test @Test
@@ -324,7 +349,7 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mPreferenceGroup.addPreference(mPreference1); mPreferenceGroup.addPreference(mPreference1);
mController.setPreferenceGroup(mPreferenceGroup); mController.setPreferenceGroup(mPreferenceGroup);
mController.onDeviceRemoved(mPreference1); mController.onDeviceRemoved(mPreference1);
verify(mPreferenceGroup, times(0)).setVisible(false); verify(mPreferenceGroup, never()).setVisible(false);
assertThat(mPreferenceGroup.isVisible()).isTrue(); assertThat(mPreferenceGroup.isVisible()).isTrue();
} }
@@ -344,7 +369,7 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mController.updateVisibility(); mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mPreferenceGroup, times(0)).setVisible(anyBoolean()); verify(mPreferenceGroup, never()).setVisible(anyBoolean());
} }
@Test @Test
@@ -411,4 +436,64 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
verify(mPreference1).setOrder(0); verify(mPreference1).setOrder(0);
verify(mPreference2).setOrder(1); verify(mPreference2).setOrder(1);
} }
@Test
public void onDeviceVolumeChanged_updatePreference() {
when(mPreference1.getProgress()).thenReturn(TEST_MAX_VOLUME_VALUE);
mController.setPreferenceGroup(mPreferenceGroup);
mController.onDeviceAdded(mPreference1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
mController.mVolumeControlCallback.onDeviceVolumeChanged(mDevice1, TEST_VOLUME_VALUE);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference1).setProgress(TEST_VOLUME_VALUE);
}
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
// onReceiveStateChanged with unconnected state will do nothing
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
verify(mDeviceUpdater, never()).forceUpdate();
// onReceiveStateChanged with connected state will update group preference
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
verify(mDeviceUpdater).forceUpdate();
// onSourceRemoved will update group preference
mController.mBroadcastAssistantCallback.onSourceRemoved(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
verify(mDeviceUpdater, times(2)).forceUpdate();
}
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModified(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModifyFailed(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceFound(mSource);
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
// Above callbacks won't update group preference
verify(mDeviceUpdater, never()).forceUpdate();
}
} }

View File

@@ -19,7 +19,11 @@ package com.android.settings.connecteddevice.audiosharing;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
@@ -27,6 +31,8 @@ import static org.robolectric.Shadows.shadowOf;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
@@ -38,7 +44,6 @@ import android.util.Pair;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.Utils; import com.android.settings.bluetooth.Utils;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
@@ -71,6 +76,7 @@ import org.robolectric.shadows.androidx.fragment.FragmentController;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config( @Config(
@@ -82,6 +88,7 @@ public class AudioSharingDialogHandlerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final int TEST_SOURCE_ID = 1;
private static final String TEST_DEVICE_NAME1 = "test1"; private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2"; private static final String TEST_DEVICE_NAME2 = "test2";
private static final String TEST_DEVICE_NAME3 = "test3"; private static final String TEST_DEVICE_NAME3 = "test3";
@@ -109,15 +116,22 @@ public class AudioSharingDialogHandlerTest {
@Mock private BluetoothDevice mDevice3; @Mock private BluetoothDevice mDevice3;
@Mock private BluetoothDevice mDevice4; @Mock private BluetoothDevice mDevice4;
@Mock private LeAudioProfile mLeAudioProfile; @Mock private LeAudioProfile mLeAudioProfile;
private Fragment mParentFragment;
@Mock private BluetoothLeBroadcastReceiveState mState; @Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private BluetoothLeBroadcastMetadata mMetadata;
private Fragment mParentFragment;
private Context mContext; private Context mContext;
private AudioSharingDialogHandler mHandler; private AudioSharingDialogHandler mHandler;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
@Before @Before
public void setup() { public void setup() {
mContext = ApplicationProvider.getApplicationContext(); mParentFragment = new Fragment();
FragmentController.setupFragment(
mParentFragment,
FragmentActivity.class,
0 /* containerViewId */,
null /* bundle */);
mContext = mParentFragment.getContext();
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBtManager = Utils.getLocalBtManager(mContext); mLocalBtManager = Utils.getLocalBtManager(mContext);
ShadowBluetoothAdapter shadowBluetoothAdapter = ShadowBluetoothAdapter shadowBluetoothAdapter =
@@ -135,6 +149,7 @@ public class AudioSharingDialogHandlerTest {
List<Long> bisSyncState = new ArrayList<>(); List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L); bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState); when(mState.getBisSyncState()).thenReturn(bisSyncState);
when(mState.getSourceId()).thenReturn(TEST_SOURCE_ID);
when(mLeAudioProfile.isEnabled(any())).thenReturn(true); when(mLeAudioProfile.isEnabled(any())).thenReturn(true);
when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1); when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
when(mCachedDevice1.getDevice()).thenReturn(mDevice1); when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
@@ -158,12 +173,6 @@ public class AudioSharingDialogHandlerTest {
when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2); when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3); when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
when(mCacheManager.findDevice(mDevice4)).thenReturn(mCachedDevice4); when(mCacheManager.findDevice(mDevice4)).thenReturn(mCachedDevice4);
mParentFragment = new Fragment();
FragmentController.setupFragment(
mParentFragment,
FragmentActivity.class,
0 /* containerViewId */,
null /* bundle */);
mHandler = new AudioSharingDialogHandler(mContext, mParentFragment); mHandler = new AudioSharingDialogHandler(mContext, mParentFragment);
} }
@@ -269,6 +278,10 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
2)); 2));
AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onShareClick();
verify(mBroadcast).startPrivateBroadcast();
} }
@Test @Test
@@ -309,6 +322,10 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
1)); 1));
AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onShareClick();
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
} }
@Test @Test
@@ -351,6 +368,11 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
1)); 1));
AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
} }
@Test @Test
@@ -363,7 +385,7 @@ public class AudioSharingDialogHandlerTest {
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of()); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ false); mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ false);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mCachedDevice2, times(0)).setActive(); verify(mCachedDevice2, never()).setActive();
} }
@Test @Test
@@ -415,7 +437,7 @@ public class AudioSharingDialogHandlerTest {
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of()); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false); mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mCachedDevice1, times(0)).setActive(); verify(mCachedDevice1, never()).setActive();
} }
@Test @Test
@@ -455,6 +477,10 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
2)); 2));
AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onShareClick();
verify(mBroadcast).startPrivateBroadcast();
} }
@Test @Test
@@ -495,6 +521,10 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
1)); 1));
AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onShareClick();
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
} }
@Test @Test
@@ -536,6 +566,11 @@ public class AudioSharingDialogHandlerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(), .ordinal(),
1)); 1));
AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
} }
@Test @Test
@@ -588,7 +623,106 @@ public class AudioSharingDialogHandlerTest {
SettingsEnums.DIALOG_STOP_AUDIO_SHARING); SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
} }
@Test
public void closeOpeningDialogsOtherThan() {
setUpBroadcast(true);
ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice3);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(deviceList);
when(mAssistant.getAllSources(mDevice3)).thenReturn(ImmutableList.of(mState));
mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ true);
shadowOf(Looper.getMainLooper()).idle();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(TAG_EQUALS)
.containsExactly(AudioSharingStopDialogFragment.tag());
deviceList = ImmutableList.of(mDevice1, mDevice3);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(deviceList);
when(mAssistant.getAllSources(mDevice1)).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
shadowOf(Looper.getMainLooper()).idle();
childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(TAG_EQUALS)
.containsExactly(AudioSharingJoinDialogFragment.tag());
verify(mFeatureFactory.metricsFeatureProvider)
.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_AUTO_DISMISS,
SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
}
@Test
public void registerCallbacks() {
Executor executor = mock(Executor.class);
mHandler.registerCallbacks(executor);
verify(mBroadcast)
.registerServiceCallBack(eq(executor), any(BluetoothLeBroadcast.Callback.class));
}
@Test
public void unregisterCallbacks() {
mHandler.unregisterCallbacks();
verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
}
@Test
public void onPlaybackStarted_addSource() {
setUpBroadcast(false);
ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice1, mDevice3);
when(mAssistant.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED}))
.thenReturn(deviceList);
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true);
shadowOf(Looper.getMainLooper()).idle();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(TAG_EQUALS)
.containsExactly(AudioSharingJoinDialogFragment.tag());
AudioSharingJoinDialogFragment fragment =
(AudioSharingJoinDialogFragment) Iterables.getOnlyElement(childFragments);
AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
assertThat(listener).isNotNull();
listener.onShareClick();
setUpBroadcast(true);
mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
verify(mAssistant).addSource(mDevice3, mMetadata, /* isGroupOp= */ false);
}
@Test
public void testBluetoothLeBroadcastCallbacks_doNothing() {
mHandler.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
mHandler.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
mHandler.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
mHandler.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
mHandler.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
mHandler.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
mHandler.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
mHandler.mBroadcastCallback.onBroadcastUpdateFailed(/* reason= */ 1, /* broadcastId= */ 1);
verify(mAssistant, never())
.addSource(
any(BluetoothDevice.class),
any(BluetoothLeBroadcastMetadata.class),
anyBoolean());
verify(mAssistant, never()).removeSource(any(BluetoothDevice.class), anyInt());
}
private void setUpBroadcast(boolean isBroadcasting) { private void setUpBroadcast(boolean isBroadcasting) {
when(mBroadcast.isEnabled(any())).thenReturn(isBroadcasting); when(mBroadcast.isEnabled(any())).thenReturn(isBroadcasting);
if (isBroadcasting) {
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
}
} }
} }

View File

@@ -22,11 +22,13 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
@@ -36,6 +38,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -181,7 +184,7 @@ public class AudioSharingSwitchBarControllerTest {
doNothing() doNothing()
.when(mAssistant) .when(mAssistant)
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
mSwitchBar = new SettingsMainSwitchBar(mContext); mSwitchBar = spy(new SettingsMainSwitchBar(mContext));
mSwitchBar.setDisabledByAdmin(mock(RestrictedLockUtils.EnforcedAdmin.class)); mSwitchBar.setDisabledByAdmin(mock(RestrictedLockUtils.EnforcedAdmin.class));
mOnAudioSharingStateChanged = false; mOnAudioSharingStateChanged = false;
mOnAudioSharingServiceConnected = false; mOnAudioSharingServiceConnected = false;
@@ -258,15 +261,15 @@ public class AudioSharingSwitchBarControllerTest {
public void onStart_flagOff_doNothing() { public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mContext, times(0)) verify(mContext, never())
.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt()); .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
verify(mBroadcast, times(0)) verify(mBroadcast, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class)); any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
verify(mAssistant, times(0)) verify(mAssistant, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class)); any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBtProfileManager, times(0)).addServiceListener(mController); verify(mBtProfileManager, never()).addServiceListener(mController);
} }
@Test @Test
@@ -279,10 +282,10 @@ public class AudioSharingSwitchBarControllerTest {
verify(mContext) verify(mContext)
.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt()); .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
verify(mBroadcast, times(0)) verify(mBroadcast, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class)); any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
verify(mAssistant, times(0)) verify(mAssistant, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class)); any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBtProfileManager).addServiceListener(mController); verify(mBtProfileManager).addServiceListener(mController);
@@ -305,7 +308,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mAssistant) verify(mAssistant)
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class)); any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBtProfileManager, times(0)).addServiceListener(mController); verify(mBtProfileManager, never()).addServiceListener(mController);
assertThat(mSwitchBar.isChecked()).isTrue(); assertThat(mSwitchBar.isChecked()).isTrue();
assertThat(mSwitchBar.isEnabled()).isTrue(); assertThat(mSwitchBar.isEnabled()).isTrue();
} }
@@ -314,12 +317,12 @@ public class AudioSharingSwitchBarControllerTest {
public void onStop_flagOff_doNothing() { public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mContext, times(0)).unregisterReceiver(any(BroadcastReceiver.class)); verify(mContext, never()).unregisterReceiver(any(BroadcastReceiver.class));
verify(mBroadcast, times(0)) verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBtProfileManager, times(0)).removeServiceListener(mController); verify(mBtProfileManager, never()).removeServiceListener(mController);
} }
@Test @Test
@@ -331,9 +334,9 @@ public class AudioSharingSwitchBarControllerTest {
verify(mContext).unregisterReceiver(any(BroadcastReceiver.class)); verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
verify(mBtProfileManager).removeServiceListener(mController); verify(mBtProfileManager).removeServiceListener(mController);
verify(mBroadcast, times(0)) verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
verify(mAssistant, times(0)) verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
} }
@@ -358,7 +361,7 @@ public class AudioSharingSwitchBarControllerTest {
when(mBtnView.isEnabled()).thenReturn(true); when(mBtnView.isEnabled()).thenReturn(true);
when(mBroadcast.isEnabled(null)).thenReturn(true); when(mBroadcast.isEnabled(null)).thenReturn(true);
mController.onCheckedChanged(mBtnView, /* isChecked= */ true); mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
verify(mBroadcast, times(0)).startPrivateBroadcast(); verify(mBroadcast, never()).startPrivateBroadcast();
} }
@Test @Test
@@ -372,7 +375,7 @@ public class AudioSharingSwitchBarControllerTest {
doNothing().when(mBroadcast).startPrivateBroadcast(); doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true); mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
assertThat(mSwitchBar.isChecked()).isFalse(); assertThat(mSwitchBar.isChecked()).isFalse();
verify(mBroadcast, times(0)).startPrivateBroadcast(); verify(mBroadcast, never()).startPrivateBroadcast();
} }
@Test @Test
@@ -407,7 +410,7 @@ public class AudioSharingSwitchBarControllerTest {
when(mBroadcast.isEnabled(null)).thenReturn(false); when(mBroadcast.isEnabled(null)).thenReturn(false);
when(mBroadcast.getLatestBroadcastId()).thenReturn(1); when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
mController.onCheckedChanged(mBtnView, /* isChecked= */ false); mController.onCheckedChanged(mBtnView, /* isChecked= */ false);
verify(mBroadcast, times(0)).stopBroadcast(anyInt()); verify(mBroadcast, never()).stopBroadcast(anyInt());
} }
@Test @Test
@@ -465,4 +468,46 @@ public class AudioSharingSwitchBarControllerTest {
.ordinal(), .ordinal(),
1)); 1));
} }
@Test
public void testBluetoothLeBroadcastCallbacks_updateSwitch() {
mOnAudioSharingStateChanged = false;
mSwitchBar.setChecked(false);
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mSwitchBar.isChecked()).isFalse();
assertThat(mOnAudioSharingStateChanged).isFalse();
when(mBroadcast.isEnabled(any())).thenReturn(true);
mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mSwitchBar.isChecked()).isTrue();
assertThat(mOnAudioSharingStateChanged).isTrue();
mOnAudioSharingStateChanged = false;
mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mSwitchBar.isChecked()).isTrue();
assertThat(mOnAudioSharingStateChanged).isFalse();
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mSwitchBar.isChecked()).isFalse();
assertThat(mOnAudioSharingStateChanged).isTrue();
}
@Test
public void testBluetoothLeBroadcastCallbacks_doNothing() {
BluetoothLeBroadcastMetadata metadata = mock(BluetoothLeBroadcastMetadata.class);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, metadata);
mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
mController.mBroadcastCallback.onBroadcastUpdateFailed(
/* reason= */ 1, /* broadcastId= */ 1);
verify(mSwitchBar, never()).setChecked(anyBoolean());
assertThat(mOnAudioSharingStateChanged).isFalse();
}
} }