[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
This commit is contained in:
Yiyi Shen
2024-09-11 19:21:53 +08:00
parent 0e7d5fcf0d
commit a6d9fa163e
4 changed files with 201 additions and 53 deletions

View File

@@ -44,7 +44,7 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
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 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
}
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 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
@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 class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
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);
}
}

View File

@@ -70,6 +70,7 @@ import java.util.HashMap;
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
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 class AudioSharingSwitchBarController extends BasePreferenceController
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
}
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
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 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
});
}
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();

View File

@@ -150,7 +150,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
}
@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 @@ public class AudioSharingLoadingStateDialogFragmentTest {
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);
}
}

View File

@@ -57,7 +57,9 @@ import android.util.Pair;
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 @@ public class AudioSharingSwitchBarControllerTest {
@After
public void tearDown() {
ShadowAlertDialogCompat.reset();
ShadowBluetoothUtils.reset();
ShadowThreadUtils.reset();
}
@@ -426,6 +429,8 @@ public class AudioSharingSwitchBarControllerTest {
assertThat(childFragments)
.comparingElementsUsing(CLAZZNAME_EQUALS)
.containsExactly(AudioSharingConfirmDialogFragment.class.getName());
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -490,14 +495,21 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
@@ -582,6 +625,8 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
}
@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 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_logAction() {
public void testAssistantCallbacks_onSourceAddFailed_logAction() {
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mMetadata, /* reason= */ 1);
verify(mFeatureFactory.metricsFeatureProvider)
@@ -696,7 +765,24 @@ public class AudioSharingSwitchBarControllerTest {
}
@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 @@ public class AudioSharingSwitchBarControllerTest {
@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 class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
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 @@ public class AudioSharingSwitchBarControllerTest {
.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 @@ public class AudioSharingSwitchBarControllerTest {
.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);
}
}