Loading res/xml/connected_devices.xml +8 −7 Original line number Diff line number Diff line Loading @@ -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"> <Preference android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment" android:icon="@drawable/ic_bt_le_audio_sharing" android:key="connected_device_audio_sharing_settings" android:order="100" android:title="@string/audio_sharing_title" settings:searchable="false" /> </PreferenceCategory> <PreferenceCategory Loading @@ -44,6 +37,14 @@ android:title="@string/connected_device_temp_bond_device_title" settings:controller="com.android.settings.connecteddevice.audiosharing.TemporaryBondDeviceGroupController" /> <Preference android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment" android:icon="@drawable/ic_bt_le_audio_sharing" android:key="connected_device_audio_sharing_settings" android:title="@string/audio_sharing_title" settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingPreferenceController" settings:searchable="false" /> <PreferenceCategory android:key="available_device_list" android:title="@string/connected_device_media_device_title" Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +2 −16 Original line number Diff line number Diff line Loading @@ -78,8 +78,6 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro private static final String TAG = "AudioSharingDevicePrefController"; private static final String KEY = "audio_sharing_device_list"; private static final String KEY_AUDIO_SHARING_SETTINGS = "connected_device_audio_sharing_settings"; @Nullable private final LocalBluetoothManager mBtManager; @Nullable private final CachedBluetoothDeviceManager mDeviceManager; Loading @@ -89,7 +87,6 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro private final Executor mExecutor; private final MetricsFeatureProvider mMetricsFeatureProvider; @Nullable private PreferenceGroup mPreferenceGroup; @Nullable private Preference mAudioSharingSettingsPreference; @Nullable private BluetoothDeviceUpdater mBluetoothDeviceUpdater; @Nullable private DashboardFragment mFragment; @Nullable private AudioSharingDialogHandler mDialogHandler; Loading Loading @@ -280,13 +277,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro super.displayPreference(screen); mPreferenceGroup = screen.findPreference(KEY); if (mPreferenceGroup != null) { mAudioSharingSettingsPreference = mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS); mPreferenceGroup.setVisible(false); } if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(false); } if (isAvailable()) { if (mBluetoothDeviceUpdater != null) { Loading Loading @@ -320,11 +312,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro @Override public void onDeviceAdded(Preference preference) { if (mPreferenceGroup != null) { if (mPreferenceGroup.getPreferenceCount() == 1) { if (mPreferenceGroup.getPreferenceCount() == 0) { mPreferenceGroup.setVisible(true); if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(true); } } mPreferenceGroup.addPreference(preference); } Loading @@ -334,11 +323,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro public void onDeviceRemoved(Preference preference) { if (mPreferenceGroup != null) { mPreferenceGroup.removePreference(preference); if (mPreferenceGroup.getPreferenceCount() == 1) { if (mPreferenceGroup.getPreferenceCount() == 0) { mPreferenceGroup.setVisible(false); if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(false); } } } } Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java +54 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ import java.util.concurrent.Executors; public class AudioSharingPreferenceController extends BasePreferenceController implements DefaultLifecycleObserver, BluetoothCallback { private static final String TAG = "AudioSharingPreferenceController"; private static final String CONNECTED_DEVICES_PREF_KEY = "connected_device_audio_sharing_settings"; private static final String CONNECTION_PREFERENCES_PREF_KEY = "audio_sharing_settings"; @Nullable private final LocalBluetoothManager mBtManager; @Nullable private final BluetoothEventManager mEventManager; Loading @@ -57,7 +60,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController new BluetoothLeBroadcast.Callback() { @Override public void onBroadcastStarted(int reason, int broadcastId) { refreshSummary(); refreshPreference(); } @Override Loading @@ -69,7 +72,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController @Override public void onBroadcastStopped(int reason, int broadcastId) { refreshSummary(); refreshPreference(); } @Override Loading Loading @@ -111,6 +114,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController } mEventManager.registerCallback(this); mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback); updateVisibility(); } @Override Loading @@ -131,6 +135,13 @@ public class AudioSharingPreferenceController extends BasePreferenceController public void displayPreference(@NonNull PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); // super.displayPreference set the visibility based on isAvailable() // immediately set the preference invisible on Connected devices page to avoid the audio // sharing entrance being shown before updateVisibility(need binder call) take effects. if (mPreference != null && CONNECTED_DEVICES_PREF_KEY.equals(getPreferenceKey())) { mPreference.setVisible(false); } updateVisibility(); } @Override Loading @@ -141,14 +152,51 @@ public class AudioSharingPreferenceController extends BasePreferenceController @Override public CharSequence getSummary() { return BluetoothUtils.isBroadcasting(mBtManager) return switch (getPreferenceKey()) { case CONNECTION_PREFERENCES_PREF_KEY -> 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() { Loading tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java +2 −13 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); } Loading @@ -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(); } Loading Loading @@ -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 Loading @@ -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 Loading tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java +121 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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 Loading @@ -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)); Loading @@ -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()) Loading @@ -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)); Loading @@ -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()) Loading @@ -158,65 +162,169 @@ 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()); 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).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()); Loading @@ -233,5 +341,12 @@ public class AudioSharingPreferenceControllerTest { 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); } } Loading
res/xml/connected_devices.xml +8 −7 Original line number Diff line number Diff line Loading @@ -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"> <Preference android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment" android:icon="@drawable/ic_bt_le_audio_sharing" android:key="connected_device_audio_sharing_settings" android:order="100" android:title="@string/audio_sharing_title" settings:searchable="false" /> </PreferenceCategory> <PreferenceCategory Loading @@ -44,6 +37,14 @@ android:title="@string/connected_device_temp_bond_device_title" settings:controller="com.android.settings.connecteddevice.audiosharing.TemporaryBondDeviceGroupController" /> <Preference android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment" android:icon="@drawable/ic_bt_le_audio_sharing" android:key="connected_device_audio_sharing_settings" android:title="@string/audio_sharing_title" settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingPreferenceController" settings:searchable="false" /> <PreferenceCategory android:key="available_device_list" android:title="@string/connected_device_media_device_title" Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +2 −16 Original line number Diff line number Diff line Loading @@ -78,8 +78,6 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro private static final String TAG = "AudioSharingDevicePrefController"; private static final String KEY = "audio_sharing_device_list"; private static final String KEY_AUDIO_SHARING_SETTINGS = "connected_device_audio_sharing_settings"; @Nullable private final LocalBluetoothManager mBtManager; @Nullable private final CachedBluetoothDeviceManager mDeviceManager; Loading @@ -89,7 +87,6 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro private final Executor mExecutor; private final MetricsFeatureProvider mMetricsFeatureProvider; @Nullable private PreferenceGroup mPreferenceGroup; @Nullable private Preference mAudioSharingSettingsPreference; @Nullable private BluetoothDeviceUpdater mBluetoothDeviceUpdater; @Nullable private DashboardFragment mFragment; @Nullable private AudioSharingDialogHandler mDialogHandler; Loading Loading @@ -280,13 +277,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro super.displayPreference(screen); mPreferenceGroup = screen.findPreference(KEY); if (mPreferenceGroup != null) { mAudioSharingSettingsPreference = mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS); mPreferenceGroup.setVisible(false); } if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(false); } if (isAvailable()) { if (mBluetoothDeviceUpdater != null) { Loading Loading @@ -320,11 +312,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro @Override public void onDeviceAdded(Preference preference) { if (mPreferenceGroup != null) { if (mPreferenceGroup.getPreferenceCount() == 1) { if (mPreferenceGroup.getPreferenceCount() == 0) { mPreferenceGroup.setVisible(true); if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(true); } } mPreferenceGroup.addPreference(preference); } Loading @@ -334,11 +323,8 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro public void onDeviceRemoved(Preference preference) { if (mPreferenceGroup != null) { mPreferenceGroup.removePreference(preference); if (mPreferenceGroup.getPreferenceCount() == 1) { if (mPreferenceGroup.getPreferenceCount() == 0) { mPreferenceGroup.setVisible(false); if (mAudioSharingSettingsPreference != null) { mAudioSharingSettingsPreference.setVisible(false); } } } } Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java +54 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ import java.util.concurrent.Executors; public class AudioSharingPreferenceController extends BasePreferenceController implements DefaultLifecycleObserver, BluetoothCallback { private static final String TAG = "AudioSharingPreferenceController"; private static final String CONNECTED_DEVICES_PREF_KEY = "connected_device_audio_sharing_settings"; private static final String CONNECTION_PREFERENCES_PREF_KEY = "audio_sharing_settings"; @Nullable private final LocalBluetoothManager mBtManager; @Nullable private final BluetoothEventManager mEventManager; Loading @@ -57,7 +60,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController new BluetoothLeBroadcast.Callback() { @Override public void onBroadcastStarted(int reason, int broadcastId) { refreshSummary(); refreshPreference(); } @Override Loading @@ -69,7 +72,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController @Override public void onBroadcastStopped(int reason, int broadcastId) { refreshSummary(); refreshPreference(); } @Override Loading Loading @@ -111,6 +114,7 @@ public class AudioSharingPreferenceController extends BasePreferenceController } mEventManager.registerCallback(this); mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback); updateVisibility(); } @Override Loading @@ -131,6 +135,13 @@ public class AudioSharingPreferenceController extends BasePreferenceController public void displayPreference(@NonNull PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); // super.displayPreference set the visibility based on isAvailable() // immediately set the preference invisible on Connected devices page to avoid the audio // sharing entrance being shown before updateVisibility(need binder call) take effects. if (mPreference != null && CONNECTED_DEVICES_PREF_KEY.equals(getPreferenceKey())) { mPreference.setVisible(false); } updateVisibility(); } @Override Loading @@ -141,14 +152,51 @@ public class AudioSharingPreferenceController extends BasePreferenceController @Override public CharSequence getSummary() { return BluetoothUtils.isBroadcasting(mBtManager) return switch (getPreferenceKey()) { case CONNECTION_PREFERENCES_PREF_KEY -> 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() { Loading
tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java +2 −13 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); } Loading @@ -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(); } Loading Loading @@ -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 Loading @@ -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 Loading
tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java +121 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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 Loading @@ -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)); Loading @@ -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()) Loading @@ -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)); Loading @@ -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()) Loading @@ -158,65 +162,169 @@ 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()); 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).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()); Loading @@ -233,5 +341,12 @@ public class AudioSharingPreferenceControllerTest { 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); } }