From 5a8e10bbe3ecc795336696398f23042931d5144b Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Mon, 20 Jan 2025 18:16:55 +0800 Subject: [PATCH] [Audiosharing] Move entry preference out of group category Test: atest Bug: 305620450 Flag: com.android.settingslib.flags.enable_le_audio_sharing Change-Id: I0573c9c35c05ca7915f94e6f67064cc5b3d79fec --- res/xml/connected_devices.xml | 15 ++- ...udioSharingDevicePreferenceController.java | 18 +-- .../AudioSharingPreferenceController.java | 60 ++++++++- ...SharingDevicePreferenceControllerTest.java | 15 +-- .../AudioSharingPreferenceControllerTest.java | 127 +++++++++++++++++- 5 files changed, 187 insertions(+), 48 deletions(-) diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml index 05bf925e56d..e8c169ce92c 100644 --- a/res/xml/connected_devices.xml +++ b/res/xml/connected_devices.xml @@ -30,13 +30,6 @@ android:key="audio_sharing_device_list" android:title="@string/audio_sharing_device_group_title" settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController"> - + + BluetoothUtils.isBroadcasting(mBtManager) + ? mContext.getString(R.string.audio_sharing_summary_on) + : mContext.getString(R.string.audio_sharing_summary_off); + default -> ""; + }; } @Override public void onBluetoothStateChanged(@AdapterState int bluetoothState) { - refreshSummary(); + refreshPreference(); + } + + private void refreshPreference() { + switch (getPreferenceKey()) { + // Audio sharing entrance on Connected devices page has no summary, but its visibility + // will change based on audio sharing state + case CONNECTED_DEVICES_PREF_KEY -> updateVisibility(); + // Audio sharing entrance on Connection preferences page always show up, but its summary + // will change based on audio sharing state + case CONNECTION_PREFERENCES_PREF_KEY -> refreshSummary(); + } + } + + private void updateVisibility() { + if (mPreference == null) { + return; + } + switch (getPreferenceKey()) { + case CONNECTED_DEVICES_PREF_KEY -> { + var unused = + ThreadUtils.postOnBackgroundThread( + () -> { + boolean visible = BluetoothUtils.isBroadcasting(mBtManager); + AudioSharingUtils.postOnMainThread( + mContext, + () -> { + // Check nullability to pass NullAway check + if (mPreference != null) { + mPreference.setVisible(visible); + } + }); + }); + } + } } private void refreshSummary() { diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java index a49d0c13890..1913debc5af 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java @@ -117,8 +117,6 @@ import java.util.concurrent.Executor; }) public class AudioSharingDevicePreferenceControllerTest { private static final String KEY = "audio_sharing_device_list"; - private static final String KEY_AUDIO_SHARING_SETTINGS = - "connected_device_audio_sharing_settings"; private static final String TEST_DEVICE_NAME = "test"; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @@ -151,7 +149,6 @@ public class AudioSharingDevicePreferenceControllerTest { private Lifecycle mLifecycle; private LifecycleOwner mLifecycleOwner; private PreferenceCategory mPreferenceGroup; - private Preference mAudioSharingPreference; private FakeFeatureFactory mFeatureFactory; private AudioManager mAudioManager; @@ -189,10 +186,6 @@ public class AudioSharingDevicePreferenceControllerTest { when(mScreen.getContext()).thenReturn(mContext); mPreferenceGroup = spy(new PreferenceCategory(mContext)); doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager(); - mAudioSharingPreference = new Preference(mContext); - mPreferenceGroup.addPreference(mAudioSharingPreference); - when(mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS)) - .thenReturn(mAudioSharingPreference); when(mScreen.findPreference(KEY)).thenReturn(mPreferenceGroup); mController = new AudioSharingDevicePreferenceController(mContext); mController.init(mFragment); @@ -260,7 +253,6 @@ public class AudioSharingDevicePreferenceControllerTest { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.displayPreference(mScreen); assertThat(mPreferenceGroup.isVisible()).isFalse(); - assertThat(mAudioSharingPreference.isVisible()).isFalse(); verify(mBluetoothDeviceUpdater, never()).forceUpdate(); } @@ -269,7 +261,6 @@ public class AudioSharingDevicePreferenceControllerTest { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.displayPreference(mScreen); assertThat(mPreferenceGroup.isVisible()).isFalse(); - assertThat(mAudioSharingPreference.isVisible()).isFalse(); verify(mBluetoothDeviceUpdater).setPrefContext(mContext); verify(mBluetoothDeviceUpdater).forceUpdate(); } @@ -299,8 +290,7 @@ public class AudioSharingDevicePreferenceControllerTest { shadowOf(Looper.getMainLooper()).idle(); assertThat(mPreferenceGroup.isVisible()).isTrue(); - assertThat(mAudioSharingPreference.isVisible()).isTrue(); - assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2); + assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); } @Test @@ -312,8 +302,7 @@ public class AudioSharingDevicePreferenceControllerTest { shadowOf(Looper.getMainLooper()).idle(); assertThat(mPreferenceGroup.isVisible()).isFalse(); - assertThat(mAudioSharingPreference.isVisible()).isFalse(); - assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); } @Test diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java index d9c883e5b1f..cdf21db9de2 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java @@ -25,8 +25,10 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @@ -77,7 +79,8 @@ import org.robolectric.shadow.api.Shadow; ShadowThreadUtils.class }) public class AudioSharingPreferenceControllerTest { - private static final String PREF_KEY = "audio_sharing_settings"; + private static final String PREF_KEY1 = "audio_sharing_settings"; + private static final String PREF_KEY2 = "connected_device_audio_sharing_settings"; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -110,9 +113,6 @@ public class AudioSharingPreferenceControllerTest { when(localBluetoothManager.getEventManager()).thenReturn(mBtEventManager); when(localBluetoothManager.getProfileManager()).thenReturn(mLocalBtProfileManager); when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); - mController = new AudioSharingPreferenceController(mContext, PREF_KEY); - mPreference = spy(new Preference(mContext)); - when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference); } @After @@ -124,6 +124,7 @@ public class AudioSharingPreferenceControllerTest { @Test public void onStart_flagOn_registerCallback() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); mController.onStart(mLifecycleOwner); verify(mBtEventManager).registerCallback(mController); verify(mBroadcast).registerServiceCallBack(any(), any(BluetoothLeBroadcast.Callback.class)); @@ -132,6 +133,7 @@ public class AudioSharingPreferenceControllerTest { @Test public void onStart_flagOff_skipRegisterCallback() { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); mController.onStart(mLifecycleOwner); verify(mBtEventManager, never()).registerCallback(mController); verify(mBroadcast, never()) @@ -141,6 +143,7 @@ public class AudioSharingPreferenceControllerTest { @Test public void onStop_flagOn_unregisterCallback() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); mController.onStop(mLifecycleOwner); verify(mBtEventManager).unregisterCallback(mController); verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class)); @@ -149,6 +152,7 @@ public class AudioSharingPreferenceControllerTest { @Test public void onStop_flagOff_skipUnregisterCallback() { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); mController.onStop(mLifecycleOwner); verify(mBtEventManager, never()).unregisterCallback(mController); verify(mBroadcast, never()) @@ -158,65 +162,147 @@ public class AudioSharingPreferenceControllerTest { @Test public void getAvailabilityStatus_flagOn() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } @Test public void getAvailabilityStatus_flagOff() { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + setupControllerWithKey(PREF_KEY1); assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } @Test - public void getSummary_broadcastOn() { + public void getSummary_connectionPreference_broadcastOn() { when(mBroadcast.isEnabled(any())).thenReturn(true); + setupControllerWithKey(PREF_KEY1); assertThat(mController.getSummary().toString()) .isEqualTo(mContext.getString(R.string.audio_sharing_summary_on)); } @Test - public void getSummary_broadcastOff() { + public void getSummary_connectionPreference_broadcastOff() { when(mBroadcast.isEnabled(any())).thenReturn(false); + setupControllerWithKey(PREF_KEY1); assertThat(mController.getSummary().toString()) .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off)); } + @Test + public void getSummary_connectedDevices_broadcastOn() { + when(mBroadcast.isEnabled(any())).thenReturn(true); + setupControllerWithKey(PREF_KEY2); + assertThat(mController.getSummary().toString()).isEmpty(); + } + + @Test + public void getSummary_connectedDevices_broadcastOff() { + when(mBroadcast.isEnabled(any())).thenReturn(false); + setupControllerWithKey(PREF_KEY2); + assertThat(mController.getSummary().toString()).isEmpty(); + } + @Test public void onBluetoothStateChanged_refreshSummary() { + setupControllerWithKey(PREF_KEY1); + mController.updateState(mPreference); mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off)); + assertThat(mPreference.isVisible()).isTrue(); + when(mBroadcast.isEnabled(any())).thenReturn(true); mController.onBluetoothStateChanged(STATE_ON); shadowOf(Looper.getMainLooper()).idle(); assertThat(mPreference.getSummary().toString()) .isEqualTo(mContext.getString(R.string.audio_sharing_summary_on)); + assertThat(mPreference.isVisible()).isTrue(); when(mBroadcast.isEnabled(any())).thenReturn(false); mController.onBluetoothStateChanged(STATE_OFF); shadowOf(Looper.getMainLooper()).idle(); assertThat(mPreference.getSummary().toString()) .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off)); + assertThat(mPreference.isVisible()).isTrue(); + } + + @Test + public void onBluetoothStateChanged_refreshVisibility() { + setupControllerWithKey(PREF_KEY2); + mController.updateState(mPreference); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isFalse(); + + when(mBroadcast.isEnabled(any())).thenReturn(true); + mController.onBluetoothStateChanged(STATE_ON); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isTrue(); + + when(mBroadcast.isEnabled(any())).thenReturn(false); + mController.onBluetoothStateChanged(STATE_OFF); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isFalse(); } @Test public void testBluetoothLeBroadcastCallbacks_refreshSummary() { + setupControllerWithKey(PREF_KEY1); + mController.updateState(mPreference); mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off)); + assertThat(mPreference.isVisible()).isTrue(); 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)); + assertThat(mPreference.isVisible()).isTrue(); 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)); + assertThat(mPreference.isVisible()).isTrue(); + } + + @Test + public void testBluetoothLeBroadcastCallbacks_refreshVisibility() { + setupControllerWithKey(PREF_KEY2); + mController.updateState(mPreference); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isFalse(); + + when(mBroadcast.isEnabled(any())).thenReturn(true); + mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isTrue(); + + when(mBroadcast.isEnabled(any())).thenReturn(false); + mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + assertThat(mPreference.isVisible()).isFalse(); } @Test public void testBluetoothLeBroadcastCallbacks_doNothing() { + setupControllerWithKey(PREF_KEY1); mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + verify(mPreference).setVisible(anyBoolean()); mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata); verify(mPreference, never()).setSummary(any()); @@ -233,5 +319,34 @@ public class AudioSharingPreferenceControllerTest { mController.mBroadcastCallback.onBroadcastUpdateFailed( /* reason= */ 1, /* broadcastId= */ 1); verify(mPreference, never()).setSummary(any()); + verify(mPreference).setVisible(anyBoolean()); + + setupControllerWithKey(PREF_KEY2); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + verify(mPreference, times(3)).setVisible(anyBoolean()); + + 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()); + verify(mPreference, times(3)).setVisible(anyBoolean()); + } + + private void setupControllerWithKey(String preferenceKey) { + mController = new AudioSharingPreferenceController(mContext, preferenceKey); + mPreference = spy(new Preference(mContext)); + when(mScreen.findPreference(preferenceKey)).thenReturn(mPreference); } }