Merge "[Audiosharing] Change main toggle enable conditions." into main
This commit is contained in:
@@ -25,7 +25,6 @@ import android.bluetooth.BluetoothLeBroadcast;
|
|||||||
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
||||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
import android.bluetooth.BluetoothProfile;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -377,9 +376,9 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
// FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST is always true in
|
// FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST is always true in
|
||||||
// prod. We can turn off the flag for debug purpose.
|
// prod. We can turn off the flag for debug purpose.
|
||||||
if (FeatureFlagUtils.isEnabled(
|
if (FeatureFlagUtils.isEnabled(
|
||||||
mContext,
|
mContext,
|
||||||
FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)
|
FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)
|
||||||
&& mAssistant.getAllConnectedDevices().isEmpty()) {
|
&& hasEmptyConnectedSink()) {
|
||||||
// Pop up dialog to ask users to connect at least one lea buds before audio sharing.
|
// Pop up dialog to ask users to connect at least one lea buds before audio sharing.
|
||||||
AudioSharingUtils.postOnMainThread(
|
AudioSharingUtils.postOnMainThread(
|
||||||
mContext,
|
mContext,
|
||||||
@@ -435,8 +434,12 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
public void onActiveDeviceChanged(@Nullable CachedBluetoothDevice activeDevice,
|
||||||
if (activeDevice != null && bluetoothProfile == BluetoothProfile.LE_AUDIO) {
|
int bluetoothProfile) {
|
||||||
|
if (activeDevice != null) {
|
||||||
|
Log.d(TAG, "onActiveDeviceChanged: device = "
|
||||||
|
+ activeDevice.getDevice().getAnonymizedAddress()
|
||||||
|
+ ", profile = " + bluetoothProfile);
|
||||||
updateSwitch();
|
updateSwitch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,13 +539,19 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
boolean isBroadcasting = BluetoothUtils.isBroadcasting(mBtManager);
|
boolean isBroadcasting = BluetoothUtils.isBroadcasting(mBtManager);
|
||||||
boolean hasActiveDevice =
|
boolean hasActiveDevice =
|
||||||
AudioSharingUtils.hasActiveConnectedLeadDevice(mBtManager);
|
AudioSharingUtils.hasActiveConnectedLeadDevice(mBtManager);
|
||||||
|
boolean hasEmptyConnectedDevice = hasEmptyConnectedSink();
|
||||||
boolean isStateReady =
|
boolean isStateReady =
|
||||||
isBluetoothOn()
|
isBluetoothOn()
|
||||||
&& AudioSharingUtils.isAudioSharingProfileReady(
|
&& AudioSharingUtils.isAudioSharingProfileReady(
|
||||||
mProfileManager)
|
mProfileManager)
|
||||||
|
&& (isBroadcasting
|
||||||
|
// Always enable toggle when no connected sink. We have
|
||||||
|
// dialog to guide users to connect compatible devices
|
||||||
|
// for audio sharing.
|
||||||
|
|| hasEmptyConnectedDevice
|
||||||
// Disable toggle till device gets active after
|
// Disable toggle till device gets active after
|
||||||
// broadcast ends.
|
// broadcast ends.
|
||||||
&& (isBroadcasting || hasActiveDevice);
|
|| hasActiveDevice);
|
||||||
AudioSharingUtils.postOnMainThread(
|
AudioSharingUtils.postOnMainThread(
|
||||||
mContext,
|
mContext,
|
||||||
() -> {
|
() -> {
|
||||||
@@ -566,6 +575,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();
|
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasEmptyConnectedSink() {
|
||||||
|
return mAssistant != null && mAssistant.getAllConnectedDevices().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private void handleOnBroadcastReady() {
|
private void handleOnBroadcastReady() {
|
||||||
Pair<Integer, Object>[] eventData =
|
Pair<Integer, Object>[] eventData =
|
||||||
AudioSharingUtils.buildAudioSharingDialogEventData(
|
AudioSharingUtils.buildAudioSharingDialogEventData(
|
||||||
|
@@ -215,15 +215,12 @@ public class AudioSharingUtils {
|
|||||||
@Nullable LocalBluetoothManager localBtManager) {
|
@Nullable LocalBluetoothManager localBtManager) {
|
||||||
CachedBluetoothDeviceManager deviceManager =
|
CachedBluetoothDeviceManager deviceManager =
|
||||||
localBtManager == null ? null : localBtManager.getCachedDeviceManager();
|
localBtManager == null ? null : localBtManager.getCachedDeviceManager();
|
||||||
Map<Integer, List<BluetoothDevice>> groupedConnectedDevices =
|
if (deviceManager == null) {
|
||||||
fetchConnectedDevicesByGroupId(localBtManager);
|
Log.d(TAG, "hasActiveConnectedLeadDevice return false due to null device manager.");
|
||||||
for (List<BluetoothDevice> devices : groupedConnectedDevices.values()) {
|
return false;
|
||||||
CachedBluetoothDevice leadDevice = getLeadDevice(deviceManager, devices);
|
|
||||||
if (isActiveLeAudioDevice(leadDevice)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return deviceManager.getCachedDevicesCopy().stream().anyMatch(
|
||||||
|
BluetoothUtils::isActiveMediaDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
|
/** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
|
||||||
|
@@ -111,10 +111,10 @@ import java.util.concurrent.Executor;
|
|||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(
|
@Config(
|
||||||
shadows = {
|
shadows = {
|
||||||
ShadowBluetoothAdapter.class,
|
ShadowBluetoothAdapter.class,
|
||||||
ShadowBluetoothUtils.class,
|
ShadowBluetoothUtils.class,
|
||||||
ShadowThreadUtils.class,
|
ShadowThreadUtils.class,
|
||||||
ShadowAlertDialogCompat.class
|
ShadowAlertDialogCompat.class
|
||||||
})
|
})
|
||||||
public class AudioSharingSwitchBarControllerTest {
|
public class AudioSharingSwitchBarControllerTest {
|
||||||
private static final String TEST_DEVICE_NAME1 = "test1";
|
private static final String TEST_DEVICE_NAME1 = "test1";
|
||||||
@@ -123,12 +123,13 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
private static final String TEST_DEVICE_ANONYMIZED_ADDR2 = "XX:XX:02";
|
private static final String TEST_DEVICE_ANONYMIZED_ADDR2 = "XX:XX:02";
|
||||||
private static final int TEST_DEVICE_GROUP_ID1 = 1;
|
private static final int TEST_DEVICE_GROUP_ID1 = 1;
|
||||||
private static final int TEST_DEVICE_GROUP_ID2 = 2;
|
private static final int TEST_DEVICE_GROUP_ID2 = 2;
|
||||||
private static final Correspondence<Fragment, String> TAG_EQUALS =
|
private static final Correspondence<Fragment, String> CLAZZNAME_EQUALS =
|
||||||
Correspondence.from(
|
Correspondence.from(
|
||||||
(Fragment fragment, String tag) ->
|
(Fragment fragment, String clazzName) ->
|
||||||
fragment instanceof DialogFragment
|
fragment instanceof DialogFragment
|
||||||
&& ((DialogFragment) fragment).getTag() != null
|
&& ((DialogFragment) fragment).getClass().getName() != null
|
||||||
&& ((DialogFragment) fragment).getTag().equals(tag),
|
&& ((DialogFragment) fragment).getClass().getName().equals(
|
||||||
|
clazzName),
|
||||||
"is equal to");
|
"is equal to");
|
||||||
|
|
||||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
@@ -343,6 +344,18 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
assertThat(mSwitchBar.isEnabled()).isTrue();
|
assertThat(mSwitchBar.isEnabled()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onStart_flagOn_updateSwitch() {
|
||||||
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||||
|
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
||||||
|
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
|
||||||
|
mController.onStart(mLifecycleOwner);
|
||||||
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
|
|
||||||
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
|
assertThat(mSwitchBar.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@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);
|
||||||
@@ -398,15 +411,21 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onCheckedChangedToChecked_noConnectedLeaDevices_flagOn_notStartAudioSharing() {
|
public void onCheckedChangedToChecked_noConnectedLeaDevices_flagOn_showDialog() {
|
||||||
FeatureFlagUtils.setEnabled(
|
FeatureFlagUtils.setEnabled(
|
||||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||||
when(mBtnView.isEnabled()).thenReturn(true);
|
when(mBtnView.isEnabled()).thenReturn(true);
|
||||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
|
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
|
||||||
doNothing().when(mBroadcast).startPrivateBroadcast();
|
doNothing().when(mBroadcast).startPrivateBroadcast();
|
||||||
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
|
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
|
||||||
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
|
|
||||||
assertThat(mSwitchBar.isChecked()).isFalse();
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
verify(mBroadcast, never()).startPrivateBroadcast();
|
verify(mBroadcast, never()).startPrivateBroadcast();
|
||||||
|
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
||||||
|
assertThat(childFragments)
|
||||||
|
.comparingElementsUsing(CLAZZNAME_EQUALS)
|
||||||
|
.containsExactly(AudioSharingConfirmDialogFragment.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -526,8 +545,8 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
|
|
||||||
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
||||||
assertThat(childFragments)
|
assertThat(childFragments)
|
||||||
.comparingElementsUsing(TAG_EQUALS)
|
.comparingElementsUsing(CLAZZNAME_EQUALS)
|
||||||
.containsExactly(AudioSharingDialogFragment.tag());
|
.containsExactly(AudioSharingDialogFragment.class.getName());
|
||||||
|
|
||||||
AudioSharingDialogFragment fragment =
|
AudioSharingDialogFragment fragment =
|
||||||
(AudioSharingDialogFragment) Iterables.getOnlyElement(childFragments);
|
(AudioSharingDialogFragment) Iterables.getOnlyElement(childFragments);
|
||||||
@@ -613,6 +632,8 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
mSwitchBar.setChecked(false);
|
mSwitchBar.setChecked(false);
|
||||||
when(mBroadcast.isEnabled(any())).thenReturn(false);
|
when(mBroadcast.isEnabled(any())).thenReturn(false);
|
||||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
|
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
|
||||||
|
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||||
|
ImmutableList.of(mCachedDevice1, mCachedDevice2));
|
||||||
mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
|
mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
assertThat(mSwitchBar.isChecked()).isFalse();
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
@@ -706,12 +727,30 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
mSwitchBar.setEnabled(false);
|
mSwitchBar.setEnabled(false);
|
||||||
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
||||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
|
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
|
||||||
|
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||||
|
ImmutableList.of(mCachedDevice2, mCachedDevice1));
|
||||||
mController.onActiveDeviceChanged(mCachedDevice2, BluetoothProfile.LE_AUDIO);
|
mController.onActiveDeviceChanged(mCachedDevice2, BluetoothProfile.LE_AUDIO);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
assertThat(mSwitchBar.isChecked()).isFalse();
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
verify(mSwitchBar).setEnabled(true);
|
verify(mSwitchBar).setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onActiveDeviceChanged_a2dpProfile_updateSwitch() {
|
||||||
|
mSwitchBar.setChecked(true);
|
||||||
|
mSwitchBar.setEnabled(false);
|
||||||
|
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
||||||
|
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
|
||||||
|
when(mCachedDevice2.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
|
||||||
|
when(mCachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).thenReturn(true);
|
||||||
|
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
|
||||||
|
ImmutableList.of(mCachedDevice1, mCachedDevice2));
|
||||||
|
mController.onActiveDeviceChanged(mCachedDevice2, BluetoothProfile.A2DP);
|
||||||
|
shadowOf(Looper.getMainLooper()).idle();
|
||||||
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
|
verify(mSwitchBar).setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onActiveDeviceChanged_nullActiveDevice_doNothing() {
|
public void onActiveDeviceChanged_nullActiveDevice_doNothing() {
|
||||||
mController.onActiveDeviceChanged(/* activeDevice= */ null, BluetoothProfile.LE_AUDIO);
|
mController.onActiveDeviceChanged(/* activeDevice= */ null, BluetoothProfile.LE_AUDIO);
|
||||||
@@ -720,14 +759,6 @@ public class AudioSharingSwitchBarControllerTest {
|
|||||||
verify(mSwitchBar, never()).setChecked(anyBoolean());
|
verify(mSwitchBar, never()).setChecked(anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onActiveDeviceChanged_notLeaProfile_doNothing() {
|
|
||||||
mController.onActiveDeviceChanged(mCachedDevice2, BluetoothProfile.HEADSET);
|
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
|
||||||
verify(mSwitchBar, never()).setEnabled(anyBoolean());
|
|
||||||
verify(mSwitchBar, never()).setChecked(anyBoolean());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAccessibilityDelegate() {
|
public void testAccessibilityDelegate() {
|
||||||
View view = new View(mContext);
|
View view = new View(mContext);
|
||||||
|
Reference in New Issue
Block a user