Merge "[Audiosharing] Increase test coverage for audio sharing" into main

This commit is contained in:
Yiyi Shen
2024-06-11 09:32:10 +00:00
committed by Android (Google) Code Review
7 changed files with 263 additions and 46 deletions

View File

@@ -57,9 +57,10 @@ public class AudioSharingCompatibilityPreferenceController extends TogglePrefere
@Nullable private TwoStatePreference mPreference; @Nullable private TwoStatePreference mPreference;
private final Executor mExecutor; private final Executor mExecutor;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
private final BluetoothLeBroadcast.Callback mBroadcastCallback = @VisibleForTesting
protected 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

@@ -20,6 +20,8 @@ import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsCategoryController; import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsCategoryController;
@@ -31,7 +33,6 @@ public class AudioSharingDashboardFragment extends DashboardFragment
private static final String TAG = "AudioSharingDashboardFrag"; private static final String TAG = "AudioSharingDashboardFrag";
SettingsMainSwitchBar mMainSwitchBar; SettingsMainSwitchBar mMainSwitchBar;
private AudioSharingSwitchBarController mSwitchBarController;
private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController; private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController;
private AudioSharingCallAudioPreferenceController mAudioSharingCallAudioPreferenceController; private AudioSharingCallAudioPreferenceController mAudioSharingCallAudioPreferenceController;
private AudioSharingPlaySoundPreferenceController mAudioSharingPlaySoundPreferenceController; private AudioSharingPlaySoundPreferenceController mAudioSharingPlaySoundPreferenceController;
@@ -83,9 +84,10 @@ public class AudioSharingDashboardFragment extends DashboardFragment
final SettingsActivity activity = (SettingsActivity) getActivity(); final SettingsActivity activity = (SettingsActivity) getActivity();
mMainSwitchBar = activity.getSwitchBar(); mMainSwitchBar = activity.getSwitchBar();
mMainSwitchBar.setTitle(getText(R.string.audio_sharing_switch_title)); mMainSwitchBar.setTitle(getText(R.string.audio_sharing_switch_title));
mSwitchBarController = new AudioSharingSwitchBarController(activity, mMainSwitchBar, this); AudioSharingSwitchBarController switchBarController =
mSwitchBarController.init(this); new AudioSharingSwitchBarController(activity, mMainSwitchBar, this);
getSettingsLifecycle().addObserver(mSwitchBarController); switchBarController.init(this);
getSettingsLifecycle().addObserver(switchBarController);
mMainSwitchBar.show(); mMainSwitchBar.show();
} }
@@ -99,6 +101,19 @@ public class AudioSharingDashboardFragment extends DashboardFragment
onProfilesConnectedForAttachedPreferences(); onProfilesConnectedForAttachedPreferences();
} }
/** Test only: set mock controllers for the {@link AudioSharingDashboardFragment} */
@VisibleForTesting
protected void setControllers(
AudioSharingDeviceVolumeGroupController volumeGroupController,
AudioSharingCallAudioPreferenceController callAudioController,
AudioSharingPlaySoundPreferenceController playSoundController,
AudioStreamsCategoryController streamsCategoryController) {
mAudioSharingDeviceVolumeGroupController = volumeGroupController;
mAudioSharingCallAudioPreferenceController = callAudioController;
mAudioSharingPlaySoundPreferenceController = playSoundController;
mAudioStreamsCategoryController = streamsCategoryController;
}
private void updateVisibilityForAttachedPreferences() { private void updateVisibilityForAttachedPreferences() {
mAudioSharingDeviceVolumeGroupController.updateVisibility(); mAudioSharingDeviceVolumeGroupController.updateVisibility();
mAudioSharingCallAudioPreferenceController.updateVisibility(); mAudioSharingCallAudioPreferenceController.updateVisibility();

View File

@@ -23,6 +23,7 @@ import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -50,7 +51,8 @@ public class AudioSharingPreferenceController extends BasePreferenceController
@Nullable private Preference mPreference; @Nullable private Preference mPreference;
private final Executor mExecutor; private final Executor mExecutor;
private final BluetoothLeBroadcast.Callback mBroadcastCallback = @VisibleForTesting
protected 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

@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; 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.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
@@ -34,6 +35,7 @@ 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.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.os.Looper; import android.os.Looper;
@@ -94,28 +96,28 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant; @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private VolumeControlProfile mVolumeControl; @Mock private VolumeControlProfile mVolumeControl;
@Mock private TwoStatePreference mPreference; @Mock private TwoStatePreference mPreference;
@Mock private BluetoothLeBroadcastMetadata mMetadata;
private AudioSharingCompatibilityPreferenceController mController; private AudioSharingCompatibilityPreferenceController mController;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private LocalBluetoothManager mLocalBluetoothManager;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
private Lifecycle mLifecycle; private Lifecycle mLifecycle;
private LifecycleOwner mLifecycleOwner; private LifecycleOwner mLifecycleOwner;
@Before @Before
public void setUp() { public void setUp() {
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); ShadowBluetoothAdapter shadowBluetoothAdapter =
mShadowBluetoothAdapter.setEnabled(true); Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED); BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED); BluetoothStatusCodes.FEATURE_SUPPORTED);
mLifecycleOwner = () -> mLifecycle; mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner); mLifecycle = new Lifecycle(mLifecycleOwner);
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext); LocalBluetoothManager localBluetoothManager = Utils.getLocalBtManager(mContext);
mFeatureFactory = FakeFeatureFactory.setupForTest(); mFeatureFactory = FakeFeatureFactory.setupForTest();
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBtEventManager); when(localBluetoothManager.getEventManager()).thenReturn(mBtEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mBtProfileManager); when(localBluetoothManager.getProfileManager()).thenReturn(mBtProfileManager);
when(mBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); when(mBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
when(mBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); when(mBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
when(mBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl); when(mBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
@@ -133,7 +135,7 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
verify(mBroadcast) verify(mBroadcast)
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class)); any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
verify(mBtProfileManager, times(0)).addServiceListener(mController); verify(mBtProfileManager, never()).addServiceListener(mController);
} }
@Test @Test
@@ -141,7 +143,7 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mBroadcast.isProfileReady()).thenReturn(false); when(mBroadcast.isProfileReady()).thenReturn(false);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mBroadcast, times(0)) verify(mBroadcast, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class)); any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
verify(mBtProfileManager).addServiceListener(mController); verify(mBtProfileManager).addServiceListener(mController);
@@ -151,7 +153,7 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
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(mBroadcast, times(0)) verify(mBroadcast, never())
.registerServiceCallBack( .registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class)); any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
} }
@@ -170,9 +172,9 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
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(mBroadcast, times(0)) verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class)); .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
verify(mBtProfileManager, times(0)).removeServiceListener(mController); verify(mBtProfileManager, never()).removeServiceListener(mController);
} }
@Test @Test
@@ -224,11 +226,10 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mPreference).setEnabled(false); verify(mPreference).setEnabled(false);
verify(mPreference) String expected =
.setSummary( mContext.getString(
eq(mContext.getString( R.string.audio_sharing_stream_compatibility_disabled_description);
R.string verify(mPreference).setSummary(eq(expected));
.audio_sharing_stream_compatibility_disabled_description)));
} }
@Test @Test
@@ -237,10 +238,9 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mPreference).setEnabled(true); verify(mPreference).setEnabled(true);
verify(mPreference) String expected =
.setSummary( mContext.getString(R.string.audio_sharing_stream_compatibility_description);
eq(mContext.getString( verify(mPreference).setSummary(eq(expected));
R.string.audio_sharing_stream_compatibility_description)));
} }
@Test @Test
@@ -272,8 +272,73 @@ public class AudioSharingCompatibilityPreferenceControllerTest {
public void setCheckedToCurrentValue_returnsFalse() { public void setCheckedToCurrentValue_returnsFalse() {
when(mBroadcast.getImproveCompatibility()).thenReturn(true); when(mBroadcast.getImproveCompatibility()).thenReturn(true);
boolean setChecked = mController.setChecked(true); boolean setChecked = mController.setChecked(true);
verify(mBroadcast, times(0)).setImproveCompatibility(anyBoolean()); verify(mBroadcast, never()).setImproveCompatibility(anyBoolean());
verifyNoInteractions(mFeatureFactory.metricsFeatureProvider); verifyNoInteractions(mFeatureFactory.metricsFeatureProvider);
assertThat(setChecked).isFalse(); assertThat(setChecked).isFalse();
} }
@Test
public void testBluetoothLeBroadcastCallbacks_refreshPreference() {
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference).setEnabled(true);
String expected =
mContext.getString(R.string.audio_sharing_stream_compatibility_description);
verify(mPreference).setSummary(eq(expected));
when(mBroadcast.isEnabled(any())).thenReturn(true);
mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference).setEnabled(false);
expected =
mContext.getString(
R.string.audio_sharing_stream_compatibility_disabled_description);
verify(mPreference).setSummary(eq(expected));
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
// Verify one extra setEnabled/setSummary is called other than the first call in
// displayPreference.
verify(mPreference, times(2)).setEnabled(true);
expected = mContext.getString(R.string.audio_sharing_stream_compatibility_description);
verify(mPreference, times(2)).setSummary(eq(expected));
}
@Test
public void testBluetoothLeBroadcastCallbacks_doNothing() {
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference).setEnabled(true);
String expected =
mContext.getString(R.string.audio_sharing_stream_compatibility_description);
verify(mPreference).setSummary(eq(expected));
// Verify no extra setEnabled/setSummary is called other than call in displayPreference.
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
mController.mBroadcastCallback.onBroadcastUpdateFailed(
/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference).setSummary(any());
}
} }

View File

@@ -18,22 +18,45 @@ 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.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsCategoryController;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.widget.SettingsMainSwitchBar;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowFragment.class})
public class AudioSharingDashboardFragmentTest { public class AudioSharingDashboardFragmentTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private SettingsActivity mActivity;
@Mock private SettingsMainSwitchBar mSwitchBar;
@Mock private AudioSharingDeviceVolumeGroupController mVolumeGroupController;
@Mock private AudioSharingCallAudioPreferenceController mCallAudioController;
@Mock private AudioSharingPlaySoundPreferenceController mPlaySoundController;
@Mock private AudioStreamsCategoryController mStreamsCategoryController;
private final Context mContext = ApplicationProvider.getApplicationContext();
private AudioSharingDashboardFragment mFragment; private AudioSharingDashboardFragment mFragment;
@Before @Before
@@ -59,7 +82,42 @@ public class AudioSharingDashboardFragmentTest {
@Test @Test
public void getHelpResource_returnsCorrectResource() { public void getHelpResource_returnsCorrectResource() {
assertThat(mFragment.getHelpResource()) assertThat(mFragment.getHelpResource()).isEqualTo(R.string.help_url_audio_sharing);
.isEqualTo(R.string.help_url_audio_sharing); }
@Test
public void onActivityCreated_showSwitchBar() {
doReturn(mSwitchBar).when(mActivity).getSwitchBar();
mFragment = spy(new AudioSharingDashboardFragment());
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mContext).when(mFragment).getContext();
mFragment.onAttach(mContext);
mFragment.onActivityCreated(new Bundle());
verify(mSwitchBar).show();
}
@Test
public void onAudioSharingStateChanged_updateVisibilityForControllers() {
mFragment.setControllers(
mVolumeGroupController,
mCallAudioController,
mPlaySoundController,
mStreamsCategoryController);
mFragment.onAudioSharingStateChanged();
verify(mVolumeGroupController).updateVisibility();
verify(mCallAudioController).updateVisibility();
verify(mPlaySoundController).updateVisibility();
verify(mStreamsCategoryController).updateVisibility();
}
@Test
public void onAudioSharingProfilesConnected_registerCallbacksForVolumeGroupController() {
mFragment.setControllers(
mVolumeGroupController,
mCallAudioController,
mPlaySoundController,
mStreamsCategoryController);
mFragment.onAudioSharingProfilesConnected();
verify(mVolumeGroupController).onAudioSharingProfilesConnected();
} }
} }

View File

@@ -63,4 +63,19 @@ public class AudioSharingDeviceItemTest {
public void creator_newArray() { public void creator_newArray() {
assertThat(AudioSharingDeviceItem.CREATOR.newArray(2)).hasLength(2); assertThat(AudioSharingDeviceItem.CREATOR.newArray(2)).hasLength(2);
} }
@Test
public void creator_createFromParcel() {
AudioSharingDeviceItem item =
new AudioSharingDeviceItem(TEST_NAME, TEST_GROUP_ID, TEST_IS_ACTIVE);
Parcel parcel = Parcel.obtain();
item.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
AudioSharingDeviceItem itemFromParcel =
AudioSharingDeviceItem.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertThat(itemFromParcel.getName()).isEqualTo(TEST_NAME);
assertThat(itemFromParcel.getGroupId()).isEqualTo(TEST_GROUP_ID);
assertThat(itemFromParcel.isActive()).isEqualTo(TEST_IS_ACTIVE);
}
} }

View File

@@ -25,12 +25,15 @@ 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.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;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.os.Looper; import android.os.Looper;
@@ -84,47 +87,67 @@ public class AudioSharingPreferenceControllerTest {
@Mock private BluetoothEventManager mBtEventManager; @Mock private BluetoothEventManager mBtEventManager;
@Mock private LocalBluetoothProfileManager mLocalBtProfileManager; @Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
@Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothLeBroadcast mBroadcast;
@Mock private BluetoothLeBroadcastMetadata mMetadata;
private AudioSharingPreferenceController mController; private AudioSharingPreferenceController mController;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private LocalBluetoothManager mLocalBluetoothManager;
private Lifecycle mLifecycle; private Lifecycle mLifecycle;
private LifecycleOwner mLifecycleOwner; private LifecycleOwner mLifecycleOwner;
private Preference mPreference; @Spy private Preference mPreference;
@Before @Before
public void setUp() { public void setUp() {
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); ShadowBluetoothAdapter shadowBluetoothAdapter =
mShadowBluetoothAdapter.setEnabled(true); Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED); BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED); BluetoothStatusCodes.FEATURE_SUPPORTED);
mLifecycleOwner = () -> mLifecycle; mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner); mLifecycle = new Lifecycle(mLifecycleOwner);
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext); LocalBluetoothManager localBluetoothManager = Utils.getLocalBtManager(mContext);
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBtEventManager); when(localBluetoothManager.getEventManager()).thenReturn(mBtEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBtProfileManager); when(localBluetoothManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
mController = new AudioSharingPreferenceController(mContext, PREF_KEY); mController = new AudioSharingPreferenceController(mContext, PREF_KEY);
mPreference = new Preference(mContext); mPreference = spy(new Preference(mContext));
when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference); when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
} }
@Test @Test
public void onStart_registerCallback() { public void onStart_flagOn_registerCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mBtEventManager).registerCallback(mController); verify(mBtEventManager).registerCallback(mController);
verify(mBroadcast).registerServiceCallBack(any(), any(BluetoothLeBroadcast.Callback.class)); verify(mBroadcast).registerServiceCallBack(any(), any(BluetoothLeBroadcast.Callback.class));
} }
@Test @Test
public void onStop_unregisterCallback() { public void onStart_flagOff_skipRegisterCallback() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
verify(mBtEventManager, never()).registerCallback(mController);
verify(mBroadcast, never())
.registerServiceCallBack(any(), any(BluetoothLeBroadcast.Callback.class));
}
@Test
public void onStop_flagOn_unregisterCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mBtEventManager).unregisterCallback(mController); verify(mBtEventManager).unregisterCallback(mController);
verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class)); verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
} }
@Test
public void onStop_flagOff_skipUnregisterCallback() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
verify(mBtEventManager, never()).unregisterCallback(mController);
verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
}
@Test @Test
public void getAvailabilityStatus_flagOn() { public void getAvailabilityStatus_flagOn() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
@@ -166,4 +189,42 @@ public class AudioSharingPreferenceControllerTest {
assertThat(mPreference.getSummary().toString()) assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.audio_sharing_summary_off)); .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
} }
@Test
public void testBluetoothLeBroadcastCallbacks_refreshSummary() {
mController.displayPreference(mScreen);
when(mBroadcast.isEnabled(any())).thenReturn(true);
mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.audio_sharing_summary_on));
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
}
@Test
public void testBluetoothLeBroadcastCallbacks_doNothing() {
mController.displayPreference(mScreen);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
verify(mPreference, never()).setSummary(any());
mController.mBroadcastCallback.onBroadcastUpdateFailed(
/* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference, never()).setSummary(any());
}
} }