[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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user