From a2577fd60e1b47dc9f2b95947ffd728f5510c50c Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Mon, 19 Feb 2024 18:18:23 +0800 Subject: [PATCH] [Audiosharing] Impl audio sharing feature provider in Settings Bug: 324023639 Test: manual Change-Id: I4005ea8fbc0983a833f5a7dee2815f09eab48d3c --- .../AvailableMediaBluetoothDeviceUpdater.java | 53 ++++--- .../ConnectedDeviceDashboardFragment.java | 42 +++++- .../AudioSharingFeatureProvider.java | 50 +++++++ .../AudioSharingFeatureProviderImpl.java | 49 ++++++ .../settings/overlay/FeatureFactory.kt | 6 + .../settings/overlay/FeatureFactoryImpl.kt | 7 + ...ilableMediaBluetoothDeviceUpdaterTest.java | 140 +++--------------- .../AudioSharingFeatureProviderImplTest.java | 67 +++++++++ .../testutils/FakeFeatureFactory.java | 8 + .../settings/testutils/FakeFeatureFactory.kt | 3 + .../testutils/FakeFeatureFactory.java | 8 + 11 files changed, 290 insertions(+), 143 deletions(-) create mode 100644 src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java create mode 100644 src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java index 23ba4f66379..8250f70e738 100644 --- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java +++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java @@ -23,7 +23,7 @@ import android.util.Log; import androidx.preference.Preference; import com.android.settings.connecteddevice.DevicePreferenceCallback; -import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -72,6 +72,32 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater if (isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice)) { Log.d(TAG, "isFilterMatched() current audio profile : " + currentAudioProfile); + // If device is LE Audio, it is compatible with HFP and A2DP. + // It would show in Available Devices group if the audio sharing flag is disabled or + // the device is not in the audio sharing session. + if (cachedDevice.isConnectedLeAudioDevice()) { + boolean isAudioSharingFilterMatched = + FeatureFactory.getFeatureFactory() + .getAudioSharingFeatureProvider() + .isAudioSharingFilterMatched(cachedDevice, mLocalManager); + if (!isAudioSharingFilterMatched) { + Log.d( + TAG, + "isFilterMatched() device : " + + cachedDevice.getName() + + ", the LE Audio profile is connected and not in sharing " + + "if broadcast enabled."); + return true; + } else { + Log.d( + TAG, + "Filter out device : " + + cachedDevice.getName() + + ", it is in audio sharing."); + return false; + } + } + // If device is Hearing Aid, it is compatible with HFP and A2DP. // It would show in Available Devices group. if (cachedDevice.isConnectedAshaHearingAidDevice()) { @@ -82,20 +108,7 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater + ", the Hearing Aid profile is connected."); return true; } - // If device is LE Audio, it is compatible with HFP and A2DP. - // It would show in Available Devices group if the audio sharing flag is disabled or - // the device is not in the audio sharing session. - if (cachedDevice.isConnectedLeAudioDevice()) { - if (!AudioSharingUtils.isFeatureEnabled() - || !AudioSharingUtils.hasBroadcastSource(cachedDevice, mLocalManager)) { - Log.d( - TAG, - "isFilterMatched() device : " - + cachedDevice.getName() - + ", the LE Audio profile is connected and not in sharing."); - return true; - } - } + // According to the current audio profile type, // this page will show the bluetooth device that have corresponding profile. // For example: @@ -125,13 +138,9 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater mMetricsFeatureProvider.logClickedPreference(preference, mMetricsCategory); final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference).getBluetoothDevice(); - if (AudioSharingUtils.isFeatureEnabled() - && AudioSharingUtils.isBroadcasting(mLocalBtManager)) { - if (DBG) { - Log.d(TAG, "onPreferenceClick stop broadcasting."); - } - AudioSharingUtils.stopBroadcasting(mLocalBtManager); - } + FeatureFactory.getFeatureFactory() + .getAudioSharingFeatureProvider() + .handleMediaDeviceOnClick(mLocalManager); return device.setActive(); } diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index 27001d6e071..2798be45186 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -22,12 +22,13 @@ import android.provider.DeviceConfig; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; -import com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController; import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils; import com.android.settings.core.SettingsUIDeviceConfig; import com.android.settings.dashboard.DashboardFragment; @@ -36,8 +37,12 @@ import com.android.settings.overlay.SurveyFeatureProvider; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.slices.SlicePreferenceController; import com.android.settingslib.bluetooth.HearingAidStatsLogUtils; +import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.SearchIndexable; +import java.util.ArrayList; +import java.util.List; + @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class ConnectedDeviceDashboardFragment extends DashboardFragment { @@ -87,9 +92,6 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { + ", action : " + action); } - if (AudioSharingUtils.isFeatureEnabled()) { - use(AudioSharingDevicePreferenceController.class).init(this); - } use(AvailableMediaDeviceGroupController.class).init(this); use(ConnectedDeviceGroupController.class).init(this); use(PreviouslyConnectedDevicePreferenceController.class).init(this); @@ -112,6 +114,29 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { } } + @Override + protected List createPreferenceControllers(Context context) { + return buildPreferenceControllers(context, /* fragment= */ this, getSettingsLifecycle()); + } + + private static List buildPreferenceControllers( + Context context, + @Nullable ConnectedDeviceDashboardFragment fragment, + @Nullable Lifecycle lifecycle) { + final List controllers = new ArrayList<>(); + if (AudioSharingUtils.isFeatureEnabled()) { + AbstractPreferenceController audioSharingController = + FeatureFactory.getFeatureFactory() + .getAudioSharingFeatureProvider() + .createAudioSharingDevicePreferenceController( + context, fragment, lifecycle); + if (audioSharingController != null) { + controllers.add(audioSharingController); + } + } + return controllers; + } + @VisibleForTesting boolean isAlwaysDiscoverable(String callingAppPackageName, String action) { return TextUtils.equals(SLICE_ACTION, action) @@ -122,5 +147,12 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { /** For Search. */ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.connected_devices); + new BaseSearchIndexProvider(R.xml.connected_devices) { + @Override + public List createPreferenceControllers( + Context context) { + return buildPreferenceControllers( + context, /* fragment= */ null, /* lifecycle= */ null); + } + }; } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java new file mode 100644 index 00000000000..c71a368640c --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.connecteddevice.audiosharing; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.Lifecycle; + +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.core.AbstractPreferenceController; + +/** Feature provider for the audio sharing related features, */ +public interface AudioSharingFeatureProvider { + + /** Create audio sharing device preference controller. */ + @Nullable + AbstractPreferenceController createAudioSharingDevicePreferenceController( + @NonNull Context context, + @Nullable DashboardFragment fragment, + @Nullable Lifecycle lifecycle); + + /** + * Check if the device match the audio sharing filter. + * + *

The filter is used to filter device in "Media devices" section. + */ + boolean isAudioSharingFilterMatched( + @NonNull CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager); + + /** Handle preference onClick in "Media devices" section. */ + void handleMediaDeviceOnClick(LocalBluetoothManager localBtManager); +} diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java new file mode 100644 index 00000000000..05a6a6383af --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.connecteddevice.audiosharing; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.Lifecycle; + +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.core.AbstractPreferenceController; + +public class AudioSharingFeatureProviderImpl implements AudioSharingFeatureProvider { + + @Nullable + @Override + public AbstractPreferenceController createAudioSharingDevicePreferenceController( + @NonNull Context context, + @Nullable DashboardFragment fragment, + @Nullable Lifecycle lifecycle) { + return null; + } + + @Override + public boolean isAudioSharingFilterMatched( + @NonNull CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager) { + return false; + } + + @Override + public void handleMediaDeviceOnClick(LocalBluetoothManager localBtManager) {} +} diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt index 37507a82274..2c4a2957422 100644 --- a/src/com/android/settings/overlay/FeatureFactory.kt +++ b/src/com/android/settings/overlay/FeatureFactory.kt @@ -24,6 +24,7 @@ import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider import com.android.settings.bluetooth.BluetoothFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.stylus.StylusFeatureProvider import com.android.settings.dashboard.DashboardFeatureProvider @@ -182,6 +183,11 @@ abstract class FeatureFactory { */ abstract val displayFeatureProvider: DisplayFeatureProvider + /** + * Gets implementation for audio sharing related feature. + */ + abstract val audioSharingFeatureProvider: AudioSharingFeatureProvider + companion object { private var _factory: FeatureFactory? = null diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt index e0313b7b7f1..e1519b3af1f 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt @@ -34,6 +34,8 @@ import com.android.settings.biometrics.fingerprint.FingerprintFeatureProviderImp import com.android.settings.biometrics2.factory.BiometricsRepositoryProviderImpl import com.android.settings.bluetooth.BluetoothFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProviderImpl +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProviderImpl import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProviderImpl @@ -192,7 +194,12 @@ open class FeatureFactoryImpl : FeatureFactory() { override val privateSpaceLoginFeatureProvider: PrivateSpaceLoginFeatureProvider by lazy { PrivateSpaceLoginFeatureProviderImpl() } + override val displayFeatureProvider: DisplayFeatureProvider by lazy { DisplayFeatureProviderImpl() } + + override val audioSharingFeatureProvider: AudioSharingFeatureProvider by lazy { + AudioSharingFeatureProviderImpl() + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java index dceadeb97aa..5a7e247c5b2 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java @@ -16,7 +16,6 @@ package com.android.settings.bluetooth; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -25,36 +24,26 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothStatusCodes; import android.content.Context; import android.graphics.drawable.Drawable; import android.media.AudioManager; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Pair; import com.android.settings.connecteddevice.DevicePreferenceCallback; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.flags.Flags; +import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowAudioManager; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; -import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; -import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -75,9 +64,6 @@ import java.util.Collection; ShadowBluetoothUtils.class }) public class AvailableMediaBluetoothDeviceUpdaterTest { - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; @Mock private DashboardFragment mDashboardFragment; @@ -86,11 +72,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { @Mock private BluetoothDevice mBluetoothDevice; @Mock private Drawable mDrawable; @Mock private LocalBluetoothManager mLocalBtManager; - @Mock private LocalBluetoothProfileManager mLocalBtProfileManager; @Mock private CachedBluetoothDeviceManager mCachedDeviceManager; - @Mock private LocalBluetoothLeBroadcast mBroadcast; - @Mock private LocalBluetoothLeBroadcastAssistant mAssistant; - @Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState; private Context mContext; private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater; @@ -98,12 +80,14 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { private AudioManager mAudioManager; private BluetoothDevicePreference mPreference; private ShadowBluetoothAdapter mShadowBluetoothAdapter; + private AudioSharingFeatureProvider mFeatureProvider; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; + mFeatureProvider = FakeFeatureFactory.setupForTest().getAudioSharingFeatureProvider(); mAudioManager = mContext.getSystemService(AudioManager.class); ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; mLocalBtManager = Utils.getLocalBtManager(mContext); @@ -267,13 +251,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { } @Test - @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void onProfileConnectionStateChanged_leAudioDeviceConnected_notInCall_addsPreference() { - setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false); + public void + onProfileConnectionStateChanged_leaDeviceConnected_notInCallNoSharing_addsPreference() { mAudioManager.setMode(AudioManager.MODE_NORMAL); when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) .thenReturn(true); when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); + when(mFeatureProvider.isAudioSharingFilterMatched( + any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class))) + .thenReturn(false); mBluetoothDeviceUpdater.onProfileConnectionStateChanged( mCachedBluetoothDevice, @@ -284,13 +270,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { } @Test - @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void onProfileConnectionStateChanged_leAudioDeviceConnected_inCall_addsPreference() { - setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false); + public void + onProfileConnectionStateChanged_leaDeviceConnected_inCallNoSharing_addsPreference() { mAudioManager.setMode(AudioManager.MODE_IN_CALL); when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) .thenReturn(true); when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); + when(mFeatureProvider.isAudioSharingFilterMatched( + any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class))) + .thenReturn(false); mBluetoothDeviceUpdater.onProfileConnectionStateChanged( mCachedBluetoothDevice, @@ -301,50 +289,16 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void - onProfileConnectionStateChanged_leaDeviceConnected_notInCall_notInBroadcast_addsPref() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false); + onProfileConnectionStateChanged_leaDeviceConnected_notInCallInSharing_removesPref() { mAudioManager.setMode(AudioManager.MODE_NORMAL); when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) .thenReturn(true); when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); - - mBluetoothDeviceUpdater.onProfileConnectionStateChanged( - mCachedBluetoothDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.LE_AUDIO); - - verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); - } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void - onProfileConnectionStateChanged_leaDeviceConnected_inCall_notInBroadcast_addsPref() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false); - mAudioManager.setMode(AudioManager.MODE_IN_CALL); - when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) + when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true); + when(mFeatureProvider.isAudioSharingFilterMatched( + any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class))) .thenReturn(true); - when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); - - mBluetoothDeviceUpdater.onProfileConnectionStateChanged( - mCachedBluetoothDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.LE_AUDIO); - - verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); - } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void - onProfileConnectionStateChanged_leaDeviceConnected_notInCall_inBroadcast_removesPref() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true); - mAudioManager.setMode(AudioManager.MODE_NORMAL); - when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) - .thenReturn(true); - when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); mBluetoothDeviceUpdater.onProfileConnectionStateChanged( mCachedBluetoothDevice, @@ -355,14 +309,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void - onProfileConnectionStateChanged_leaDeviceConnected_inCall_inBroadcast_removesPref() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true); - mAudioManager.setMode(AudioManager.MODE_IN_CALL); + public void onProfileConnectionStateChanged_leaDeviceConnected_inCallInSharing_removesPref() { + mAudioManager.setMode(AudioManager.MODE_NORMAL); when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class))) .thenReturn(true); when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); + when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true); + when(mFeatureProvider.isAudioSharingFilterMatched( + any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class))) + .thenReturn(true); mBluetoothDeviceUpdater.onProfileConnectionStateChanged( mCachedBluetoothDevice, @@ -414,56 +369,9 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { } @Test - @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onClick_Preference_setActive() { - setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false); mBluetoothDeviceUpdater.onPreferenceClick(mPreference); verify(mCachedBluetoothDevice).setActive(); } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void onClick_Preference_isNotBroadcasting_setActive() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false); - mBluetoothDeviceUpdater.onPreferenceClick(mPreference); - - verify(mCachedBluetoothDevice).setActive(); - } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) - public void onClick_Preference_isBroadcasting_stopBroadcastingAndSetActive() { - setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true); - doNothing().when(mBroadcast).stopBroadcast(anyInt()); - mBluetoothDeviceUpdater.onPreferenceClick(mPreference); - - verify(mBroadcast).stopBroadcast(anyInt()); - verify(mCachedBluetoothDevice).setActive(); - } - - private void setUpBroadcast(boolean isSupported, boolean isBroadcasting) { - if (isSupported) { - mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( - BluetoothStatusCodes.FEATURE_SUPPORTED); - mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( - BluetoothStatusCodes.FEATURE_SUPPORTED); - when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager); - when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); - when(mBroadcast.isEnabled(null)).thenReturn(isBroadcasting); - when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()) - .thenReturn(mAssistant); - if (isBroadcasting) { - when(mAssistant.getAllSources(any())) - .thenReturn(ImmutableList.of(mBroadcastReceiveState)); - } else { - when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of()); - } - } else { - mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); - mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); - } - } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java new file mode 100644 index 00000000000..0edbc7709ba --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.connecteddevice.audiosharing; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class AudioSharingFeatureProviderImplTest { + @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock private CachedBluetoothDevice mCachedDevice; + @Mock private LocalBluetoothManager mLocalBtManager; + @Mock private DashboardFragment mFragment; + private Context mContext; + private AudioSharingFeatureProviderImpl mFeatureProvider; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mFeatureProvider = new AudioSharingFeatureProviderImpl(); + } + + @Test + public void createAudioSharingDevicePreferenceController_returnsNull() { + assertThat( + mFeatureProvider.createAudioSharingDevicePreferenceController( + mContext, mFragment, /* lifecycle= */ null)) + .isNull(); + } + + @Test + public void isAudioSharingFilterMatched_returnsFalse() { + assertThat(mFeatureProvider.isAudioSharingFilterMatched(mCachedDevice, mLocalBtManager)) + .isFalse(); + } +} diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java index a11b226db28..f49cc6873eb 100644 --- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java @@ -27,6 +27,7 @@ import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; import com.android.settings.connecteddevice.stylus.StylusFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider; @@ -103,6 +104,7 @@ public class FakeFeatureFactory extends FeatureFactory { public FastPairFeatureProvider mFastPairFeatureProvider; public PrivateSpaceLoginFeatureProvider mPrivateSpaceLoginFeatureProvider; public DisplayFeatureProvider mDisplayFeatureProvider; + public AudioSharingFeatureProvider mAudioSharingFeatureProvider; /** * Call this in {@code @Before} method of the test class to use fake factory. @@ -152,6 +154,7 @@ public class FakeFeatureFactory extends FeatureFactory { mFastPairFeatureProvider = mock(FastPairFeatureProvider.class); mPrivateSpaceLoginFeatureProvider = mock(PrivateSpaceLoginFeatureProvider.class); mDisplayFeatureProvider = mock(DisplayFeatureProvider.class); + mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class); } @Override @@ -339,5 +342,10 @@ public class FakeFeatureFactory extends FeatureFactory { public DisplayFeatureProvider getDisplayFeatureProvider() { return mDisplayFeatureProvider; } + + @Override + public AudioSharingFeatureProvider getAudioSharingFeatureProvider() { + return mAudioSharingFeatureProvider; + } } diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt index 4048c24754d..606db8e1c87 100644 --- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt +++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt @@ -25,6 +25,7 @@ import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider import com.android.settings.bluetooth.BluetoothFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.stylus.StylusFeatureProvider import com.android.settings.dashboard.DashboardFeatureProvider @@ -149,4 +150,6 @@ class FakeFeatureFactory : FeatureFactory() { get() = TODO("Not yet implemented") override val displayFeatureProvider: DisplayFeatureProvider get() = TODO("Not yet implemented") + override val audioSharingFeatureProvider: AudioSharingFeatureProvider + get() = TODO("Not yet implemented") } diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java index 9e7948c7da8..4f17a3acfff 100644 --- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -27,6 +27,7 @@ import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; import com.android.settings.connecteddevice.stylus.StylusFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider; @@ -102,6 +103,7 @@ public class FakeFeatureFactory extends FeatureFactory { public FastPairFeatureProvider mFastPairFeatureProvider; public PrivateSpaceLoginFeatureProvider mPrivateSpaceLoginFeatureProvider; public DisplayFeatureProvider mDisplayFeatureProvider; + public AudioSharingFeatureProvider mAudioSharingFeatureProvider; /** Call this in {@code @Before} method of the test class to use fake factory. */ public static FakeFeatureFactory setupForTest() { @@ -153,6 +155,7 @@ public class FakeFeatureFactory extends FeatureFactory { mFastPairFeatureProvider = mock(FastPairFeatureProvider.class); mPrivateSpaceLoginFeatureProvider = mock(PrivateSpaceLoginFeatureProvider.class); mDisplayFeatureProvider = mock(DisplayFeatureProvider.class); + mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class); } @Override @@ -340,4 +343,9 @@ public class FakeFeatureFactory extends FeatureFactory { public DisplayFeatureProvider getDisplayFeatureProvider() { return mDisplayFeatureProvider; } + + @Override + public AudioSharingFeatureProvider getAudioSharingFeatureProvider() { + return mAudioSharingFeatureProvider; + } }