[Audiosharing] Show loading state on audio sharing page
1. Show "Sharing audio stream..." once starting audio sharing
2. Show "Sharing with <devicename>..." once adding source to the device
Test: atest
Flag: com.android.settingslib.flags.enable_le_audio_sharing
Bug: 362858894
Change-Id: I6c19d999baaa91d6a5365f24e88efe79c2b38072
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java
index b00f407..79cc56e 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java
@@ -44,7 +44,7 @@
private static final String TAG = "AudioSharingLoadingDlg";
private static final String BUNDLE_KEY_MESSAGE = "bundle_key_message";
- private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(10);
+ private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15);
private static final int AUTO_DISMISS_MESSAGE_ID = R.id.message;
private static String sMessage = "";
@@ -74,13 +74,15 @@
}
AlertDialog dialog = AudioSharingDialogHelper.getDialogIfShowing(manager, TAG);
if (dialog != null) {
- if (sMessage.equals(message)) {
- Log.d(TAG, "Dialog is showing with same message, return.");
- return;
- } else {
- Log.d(TAG, "Dialog is showing with different message, dismiss and reshow.");
- dialog.dismiss();
+ if (!sMessage.equals(message)) {
+ Log.d(TAG, "Update dialog message.");
+ TextView messageView = dialog.findViewById(R.id.message);
+ if (messageView != null) {
+ messageView.setText(message);
+ }
}
+ Log.d(TAG, "Dialog is showing, return.");
+ return;
}
sMessage = message;
Log.d(TAG, "Show up the loading dialog.");
@@ -113,8 +115,10 @@
@NonNull
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
mHandler = new Handler(Looper.getMainLooper());
- mHandler.postDelayed(() -> dismiss(), AUTO_DISMISS_MESSAGE_ID,
- AUTO_DISMISS_TIME_THRESHOLD_MS);
+ mHandler.postDelayed(() -> {
+ Log.d(TAG, "Auto dismiss dialog after timeout");
+ dismiss();
+ }, AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
Bundle args = requireArguments();
String message = args.getString(BUNDLE_KEY_MESSAGE, "");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
@@ -132,6 +136,7 @@
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (mHandler != null) {
+ Log.d(TAG, "Dialog dismissed, remove auto dismiss task");
mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID);
}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 2040694..c0f463d 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -70,6 +70,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -112,12 +113,13 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final OnAudioSharingStateChangedListener mListener;
private Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
- private List<BluetoothDevice> mTargetActiveSinks = new ArrayList<>();
+ @Nullable private AudioSharingDeviceItem mTargetActiveItem;
private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>();
@VisibleForTesting IntentFilter mIntentFilter;
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
private AtomicInteger mIntentHandleStage =
new AtomicInteger(StartIntentHandleStage.TO_HANDLE.ordinal());
+ private CopyOnWriteArrayList<BluetoothDevice> mSinksInAdding = new CopyOnWriteArrayList<>();
@VisibleForTesting
BroadcastReceiver mReceiver =
@@ -294,7 +296,16 @@
public void onReceiveStateChanged(
@NonNull BluetoothDevice sink,
int sourceId,
- @NonNull BluetoothLeBroadcastReceiveState state) {}
+ @NonNull BluetoothLeBroadcastReceiveState state) {
+ if (BluetoothUtils.isConnected(state)) {
+ if (mSinksInAdding.contains(sink)) {
+ mSinksInAdding.remove(sink);
+ }
+ dismissLoadingStateDialogIfNeeded();
+ Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink
+ + ", remaining sinks = " + mSinksInAdding);
+ }
+ }
};
AudioSharingSwitchBarController(
@@ -506,17 +517,20 @@
mBtManager, mGroupedConnectedDevices, /* filterByInSharing= */ false);
// deviceItems is ordered. The active device is the first place if exits.
mDeviceItemsForSharing = new ArrayList<>(deviceItems);
- mTargetActiveSinks = new ArrayList<>();
+ mTargetActiveItem = null;
if (!deviceItems.isEmpty() && deviceItems.get(0).isActive()) {
// If active device exists for audio sharing, share to it
// automatically once the broadcast is started.
- mTargetActiveSinks =
- mGroupedConnectedDevices.getOrDefault(
- deviceItems.get(0).getGroupId(), ImmutableList.of());
+ mTargetActiveItem = deviceItems.get(0);
mDeviceItemsForSharing.remove(0);
}
if (mBroadcast != null) {
mBroadcast.startPrivateBroadcast();
+ mSinksInAdding.clear();
+ // TODO: use string res once finalized.
+ AudioSharingUtils.postOnMainThread(mContext,
+ () -> AudioSharingLoadingStateDialogFragment.show(mFragment,
+ "Starting audio stream..."));
mMetricsFeatureProvider.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_ON,
@@ -580,27 +594,30 @@
}
private void handleOnBroadcastReady() {
+ List<BluetoothDevice> targetActiveSinks = mTargetActiveItem == null ? ImmutableList.of()
+ : mGroupedConnectedDevices.getOrDefault(
+ mTargetActiveItem.getGroupId(), ImmutableList.of());
Pair<Integer, Object>[] eventData =
AudioSharingUtils.buildAudioSharingDialogEventData(
SettingsEnums.AUDIO_SHARING_SETTINGS,
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
/* userTriggered= */ false,
- /* deviceCountInSharing= */ mTargetActiveSinks.isEmpty() ? 0 : 1,
+ /* deviceCountInSharing= */ targetActiveSinks.isEmpty() ? 0 : 1,
/* candidateDeviceCount= */ mDeviceItemsForSharing.size());
- if (!mTargetActiveSinks.isEmpty()) {
+ if (!targetActiveSinks.isEmpty() && mTargetActiveItem != null) {
Log.d(TAG, "handleOnBroadcastReady: automatically add source to active sinks.");
- AudioSharingUtils.addSourceToTargetSinks(mTargetActiveSinks, mBtManager);
+ addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName());
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING);
- mTargetActiveSinks.clear();
+ mTargetActiveItem = null;
if (mIntentHandleStage.compareAndSet(
StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(),
StartIntentHandleStage.HANDLED.ordinal())
&& mDeviceItemsForSharing.size() == 1) {
Log.d(TAG, "handleOnBroadcastReady: auto add source to the second device");
- AudioSharingUtils.addSourceToTargetSinks(
- mGroupedConnectedDevices.getOrDefault(
- mDeviceItemsForSharing.get(0).getGroupId(), ImmutableList.of()),
- mBtManager);
+ AudioSharingDeviceItem target = mDeviceItemsForSharing.get(0);
+ List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
+ target.getGroupId(), ImmutableList.of());
+ addSourceToTargetSinks(targetSinks, target.getName());
cleanUp();
// TODO: Add metric for auto add by intent
return;
@@ -611,6 +628,7 @@
StartIntentHandleStage.HANDLED.ordinal());
if (mFragment == null) {
Log.d(TAG, "handleOnBroadcastReady: dialog fail to show due to null fragment.");
+ dismissLoadingStateDialogIfNeeded();
cleanUp();
return;
}
@@ -622,15 +640,15 @@
new AudioSharingDialogFragment.DialogEventListener() {
@Override
public void onItemClick(@NonNull AudioSharingDeviceItem item) {
- AudioSharingUtils.addSourceToTargetSinks(
- mGroupedConnectedDevices.getOrDefault(
- item.getGroupId(), ImmutableList.of()),
- mBtManager);
+ List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
+ item.getGroupId(), ImmutableList.of());
+ addSourceToTargetSinks(targetSinks, item.getName());
cleanUp();
}
@Override
public void onCancelClick() {
+ dismissLoadingStateDialogIfNeeded();
cleanUp();
}
};
@@ -700,6 +718,27 @@
});
}
+ private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks,
+ @NonNull String sinkName) {
+ mSinksInAdding.addAll(targetActiveSinks);
+ AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager);
+ // TODO: move to res once finalized
+ String loadingMessage = "Sharing with " + sinkName + "...";
+ showLoadingStateDialog(loadingMessage);
+ }
+
+ private void showLoadingStateDialog(@NonNull String loadingMessage) {
+ AudioSharingUtils.postOnMainThread(mContext,
+ () -> AudioSharingLoadingStateDialogFragment.show(mFragment, loadingMessage));
+ }
+
+ private void dismissLoadingStateDialogIfNeeded() {
+ if (mSinksInAdding.isEmpty()) {
+ AudioSharingUtils.postOnMainThread(mContext,
+ () -> AudioSharingLoadingStateDialogFragment.dismiss(mFragment));
+ }
+ }
+
private void cleanUp() {
mGroupedConnectedDevices.clear();
mDeviceItemsForSharing.clear();
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java
index b5da88c..ff15f52 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java
@@ -150,7 +150,7 @@
}
@Test
- public void showDialog_newMessage_dismissAndShowNewDialog() {
+ public void showDialog_newMessage_keepAndUpdateDialog() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
@@ -163,12 +163,7 @@
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE2);
shadowMainLooper().idle();
- assertThat(dialog.isShowing()).isFalse();
- AlertDialog newDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- assertThat(newDialog).isNotNull();
- assertThat(newDialog.isShowing()).isTrue();
- view = newDialog.findViewById(R.id.message);
- assertThat(view).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
assertThat(view.getText().toString()).isEqualTo(TEST_MESSAGE2);
}
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
index 354c5c7..0d21f18 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
@@ -57,7 +57,9 @@
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.widget.CompoundButton;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
@@ -235,6 +237,7 @@
@After
public void tearDown() {
+ ShadowAlertDialogCompat.reset();
ShadowBluetoothUtils.reset();
ShadowThreadUtils.reset();
}
@@ -426,6 +429,8 @@
assertThat(childFragments)
.comparingElementsUsing(CLAZZNAME_EQUALS)
.containsExactly(AudioSharingConfirmDialogFragment.class.getName());
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -490,14 +495,21 @@
public void onAudioSharingProfilesConnected() {}
});
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
verify(mBroadcast).startPrivateBroadcast();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ // No loading state dialog.
+ assertThat(childFragments).isEmpty();
+
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
- List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ // No audio sharing dialog.
assertThat(childFragments).isEmpty();
}
@@ -514,7 +526,13 @@
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
verify(mBroadcast).startPrivateBroadcast();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -522,8 +540,12 @@
verify(mFeatureFactory.metricsFeatureProvider, never())
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
- List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
- assertThat(childFragments).isEmpty();
+ childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ // No audio sharing dialog.
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).doesNotContain(
+ AudioSharingDialogFragment.class.getName());
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -534,23 +556,42 @@
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
doNothing().when(mBroadcast).startPrivateBroadcast();
- mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
+ mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
verify(mBroadcast).startPrivateBroadcast();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+ AudioSharingLoadingStateDialogFragment loadingFragment =
+ (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
+ // TODO: use string res once finalized
+ String expectedMessage = "Starting audio stream...";
+ checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
+
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
+ // TODO: use string res once finalized
+ expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "...";
+ checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
- List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(CLAZZNAME_EQUALS)
- .containsExactly(AudioSharingDialogFragment.class.getName());
+ .containsExactly(AudioSharingDialogFragment.class.getName(),
+ AudioSharingLoadingStateDialogFragment.class.getName());
- AudioSharingDialogFragment fragment =
- (AudioSharingDialogFragment) Iterables.getOnlyElement(childFragments);
- Pair<Integer, Object>[] eventData = fragment.getEventData();
+ Pair<Integer, Object>[] eventData = new Pair[0];
+ for (Fragment fragment : childFragments) {
+ if (fragment instanceof AudioSharingDialogFragment) {
+ eventData = ((AudioSharingDialogFragment) fragment).getEventData();
+ break;
+ }
+ }
assertThat(eventData)
.asList()
.containsExactly(
@@ -570,6 +611,8 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -582,6 +625,8 @@
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
verify(mBroadcast).startPrivateBroadcast();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -597,6 +642,17 @@
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
assertThat(dialog.isShowing()).isFalse();
+ // Loading state dialog shows sharing state for the user chosen sink.
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+ AudioSharingLoadingStateDialogFragment loadingFragment =
+ (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
+ // TODO: use string res once finalized
+ String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "...";
+ checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -609,6 +665,8 @@
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
verify(mBroadcast).startPrivateBroadcast();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -624,10 +682,21 @@
verify(mAssistant, never()).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
assertThat(dialog.isShowing()).isFalse();
+ // Loading state dialog shows sharing state for the auto add active sink.
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+ AudioSharingLoadingStateDialogFragment loadingFragment =
+ (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
+ // TODO: use string res once finalized
+ String expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "...";
+ checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
- public void testBluetoothLeBroadcastCallbacks_updateSwitch() {
+ public void testBroadcastCallbacks_updateSwitch() {
mOnAudioSharingStateChanged = false;
mSwitchBar.setChecked(false);
when(mBroadcast.isEnabled(any())).thenReturn(false);
@@ -673,7 +742,7 @@
}
@Test
- public void testBluetoothLeBroadcastCallbacks_doNothing() {
+ public void testBroadcastCallbacks_doNothing() {
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
@@ -685,7 +754,7 @@
}
@Test
- public void testBluetoothLeBroadcastAssistantCallbacks_logAction() {
+ public void testAssistantCallbacks_onSourceAddFailed_logAction() {
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mMetadata, /* reason= */ 1);
verify(mFeatureFactory.metricsFeatureProvider)
@@ -696,7 +765,24 @@
}
@Test
- public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+ public void testAssistantCallbacks_onReceiveStateChanged_dismissLoadingDialog() {
+ AudioSharingLoadingStateDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1);
+ shadowOf(Looper.getMainLooper()).idle();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+
+ BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
+ when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
+ state);
+ shadowOf(Looper.getMainLooper()).idle();
+ childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments).isEmpty();
+ }
+
+ @Test
+ public void testAssistantCallbacks_doNothing() {
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
// Do nothing
@@ -784,7 +870,7 @@
@Test
public void handleStartAudioSharingFromIntent_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
- setUpStartSharingIntent();
+ var unused = setUpFragmentWithStartSharingIntent();
mController.onStart(mLifecycleOwner);
shadowOf(Looper.getMainLooper()).idle();
@@ -795,7 +881,7 @@
public void handleStartAudioSharingFromIntent_profileNotReady_doNothing() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mAssistant.isProfileReady()).thenReturn(false);
- setUpStartSharingIntent();
+ var unused = setUpFragmentWithStartSharingIntent();
mController.onServiceConnected();
shadowOf(Looper.getMainLooper()).idle();
@@ -817,13 +903,16 @@
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
- setUpStartSharingIntent();
+ Fragment parentFragment = setUpFragmentWithStartSharingIntent();
mController.onServiceConnected();
shadowOf(Looper.getMainLooper()).idle();
verify(mSwitchBar).setChecked(true);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ verify(mBroadcast).startPrivateBroadcast();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -831,11 +920,21 @@
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
- List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
- assertThat(childFragments).isEmpty();
+ List<Fragment> childFragments = parentFragment.getChildFragmentManager().getFragments();
+ // Skip audio sharing dialog.
+ assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
+ AudioSharingLoadingStateDialogFragment.class.getName());
+ // The loading state dialog shows sharing state for the auto add second sink.
+ AudioSharingLoadingStateDialogFragment loadingFragment =
+ (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
+ // TODO: use string res once finalized
+ String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "...";
+ checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
+
+ childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
- private void setUpStartSharingIntent() {
+ private Fragment setUpFragmentWithStartSharingIntent() {
Bundle args = new Bundle();
args.putBoolean(EXTRA_START_LE_AUDIO_SHARING, true);
Intent intent = new Intent();
@@ -849,5 +948,15 @@
.get();
shadowOf(Looper.getMainLooper()).idle();
mController.init(fragment);
+ return fragment;
+ }
+
+ private void checkLoadingStateDialogMessage(
+ @NonNull AudioSharingLoadingStateDialogFragment fragment,
+ @NonNull String expectedMessage) {
+ TextView loadingMessage = fragment.getDialog() == null ? null
+ : fragment.getDialog().findViewById(R.id.message);
+ assertThat(loadingMessage).isNotNull();
+ assertThat(loadingMessage.getText().toString()).isEqualTo(expectedMessage);
}
}