Check all member devices to determine whether it's LeAudio-only device

Bug: 352431349
Test: atest BluetoothDetailsProfilesControllerTest
Flag: com.android.settings.flags.hide_le_audio_toggle_for_le_audio_only_device
Change-Id: I3697b4f3abf5f789100b63f0b7a01c3b78d70a7f
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 3fa811a..2e5daeb 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -43,7 +43,6 @@
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.HeadsetProfile;
-import com.android.settingslib.bluetooth.HearingAidProfile;
 import com.android.settingslib.bluetooth.LeAudioProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfile;
@@ -95,6 +94,7 @@
             new HashMap<String, List<CachedBluetoothDevice>>();
     private boolean mIsLeContactSharingEnabled = false;
     private boolean mIsLeAudioToggleEnabled = false;
+    private boolean mIsLeAudioOnlyDevice = false;
 
     @VisibleForTesting
     PreferenceCategory mProfilesContainer;
@@ -345,6 +345,11 @@
             result.remove(mManager.getProfileManager().getA2dpProfile());
             result.remove(mManager.getProfileManager().getHeadsetProfile());
         }
+        boolean hearingAidSupported = result.contains(
+                mManager.getProfileManager().getHearingAidProfile());
+        if (leAudioSupported && !classicAudioSupported && !hearingAidSupported) {
+            mIsLeAudioOnlyDevice = true;
+        }
         Log.d(TAG, "getProfiles:Map:" + mProfileDeviceMap);
         return result;
     }
@@ -513,19 +518,6 @@
         refresh();
     }
 
-    private boolean isLeAudioOnlyDevice() {
-        if (mCachedDevice.getProfiles().stream()
-                .noneMatch(profile -> profile instanceof LeAudioProfile)) {
-            return false;
-        }
-        return mCachedDevice.getProfiles().stream()
-                .noneMatch(
-                        profile ->
-                                profile instanceof HearingAidProfile
-                                        || profile instanceof A2dpProfile
-                                        || profile instanceof HeadsetProfile);
-    }
-
     private void updateLeAudioConfig() {
         mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
                 SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
@@ -534,7 +526,7 @@
         boolean isLeEnabledByDefault =
                 SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true);
         mIsLeAudioToggleEnabled = isLeAudioToggleVisible || isLeEnabledByDefault;
-        if (Flags.hideLeAudioToggleForLeAudioOnlyDevice() && isLeAudioOnlyDevice()) {
+        if (Flags.hideLeAudioToggleForLeAudioOnlyDevice() && mIsLeAudioOnlyDevice) {
             mIsLeAudioToggleEnabled = false;
             Log.d(
                     TAG,
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
index 9b92234..2d1f4c0 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
@@ -90,6 +90,9 @@
     @Mock
     private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
 
+    private @Mock A2dpProfile mA2dpProfile;
+    private @Mock LeAudioProfile mLeAudioProfile;
+
     @Override
     public void setUp() {
         super.setUp();
@@ -103,11 +106,13 @@
         mConnectableProfiles = new ArrayList<>();
         when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
         when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedBluetoothDeviceManager);
+        setUpMockProfiles();
         when(mCachedBluetoothDeviceManager.getCachedDevicesCopy())
                 .thenReturn(ImmutableList.of(mCachedDevice));
-        when(mCachedDevice.getConnectableProfiles()).thenAnswer(invocation ->
-            new ArrayList<>(mConnectableProfiles)
-        );
+        when(mCachedDevice.getConnectableProfiles())
+                .thenAnswer(invocation -> new ArrayList<>(mConnectableProfiles));
+        when(mCachedDevice.getProfiles())
+                .thenAnswer(invocation -> ImmutableList.of(mConnectableProfiles));
 
         setupDevice(mDeviceConfig);
         mController = new BluetoothDetailsProfilesController(mContext, mFragment, mLocalManager,
@@ -389,21 +394,36 @@
         assertThat(mDevice.getMessageAccessPermission()).isEqualTo(BluetoothDevice.ACCESS_ALLOWED);
     }
 
-    private A2dpProfile addMockA2dpProfile(boolean preferred, boolean supportsHighQualityAudio,
-            boolean highQualityAudioEnabled) {
-        A2dpProfile profile = mock(A2dpProfile.class);
-        when(mProfileManager.getProfileByName(eq(profile.toString()))).thenReturn(profile);
-        when(profile.getNameResource(mDevice))
+    private void setUpMockProfiles() {
+        when(mA2dpProfile.toString()).thenReturn("A2DP");
+        when(mProfileManager.getProfileByName(eq(mA2dpProfile.toString())))
+                .thenReturn(mA2dpProfile);
+        when(mA2dpProfile.getNameResource(any()))
                 .thenReturn(com.android.settingslib.R.string.bluetooth_profile_a2dp);
-        when(profile.getHighQualityAudioOptionLabel(mDevice)).thenReturn(
+        when(mA2dpProfile.getHighQualityAudioOptionLabel(any())).thenReturn(
                 mContext.getString(com.android.settingslib.R
                         .string.bluetooth_profile_a2dp_high_quality_unknown_codec));
-        when(profile.supportsHighQualityAudio(mDevice)).thenReturn(supportsHighQualityAudio);
-        when(profile.isHighQualityAudioEnabled(mDevice)).thenReturn(highQualityAudioEnabled);
-        when(profile.isEnabled(mDevice)).thenReturn(preferred);
-        when(profile.isProfileReady()).thenReturn(true);
-        mConnectableProfiles.add(profile);
-        return profile;
+        when(mA2dpProfile.isProfileReady()).thenReturn(true);
+        when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
+
+        when(mLeAudioProfile.toString()).thenReturn("LE_AUDIO");
+        when(mLeAudioProfile.getNameResource(any()))
+                .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
+        when(mLeAudioProfile.isProfileReady()).thenReturn(true);
+        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+    }
+
+    private void addA2dpProfileToDevice(boolean preferred, boolean supportsHighQualityAudio,
+            boolean highQualityAudioEnabled) {
+        when(mA2dpProfile.supportsHighQualityAudio(any())).thenReturn(supportsHighQualityAudio);
+        when(mA2dpProfile.isHighQualityAudioEnabled(any())).thenReturn(highQualityAudioEnabled);
+        when(mA2dpProfile.isEnabled(any())).thenReturn(preferred);
+        mConnectableProfiles.add(mA2dpProfile);
+    }
+
+    private void addLeAudioProfileToDevice(boolean enabled) {
+        when(mLeAudioProfile.isEnabled(any())).thenReturn(enabled);
+        mConnectableProfiles.add(mLeAudioProfile);
     }
 
     private SwitchPreferenceCompat getHighQualityAudioPref() {
@@ -414,7 +434,7 @@
     @Test
     public void highQualityAudio_prefIsPresentWhenSupported() {
         setupDevice(makeDefaultDeviceConfig());
-        addMockA2dpProfile(true, true, true);
+        addA2dpProfileToDevice(true, true, true);
         showScreen(mController);
         SwitchPreferenceCompat pref = getHighQualityAudioPref();
         assertThat(pref.getKey()).isEqualTo(
@@ -431,7 +451,7 @@
     @Test
     public void highQualityAudio_prefIsAbsentWhenNotSupported() {
         setupDevice(makeDefaultDeviceConfig());
-        addMockA2dpProfile(true, false, false);
+        addA2dpProfileToDevice(true, false, false);
         showScreen(mController);
         assertThat(mProfiles.getPreferenceCount()).isEqualTo(2);
         SwitchPreferenceCompat pref = (SwitchPreferenceCompat) mProfiles.getPreference(0);
@@ -444,7 +464,7 @@
     @Test
     public void highQualityAudio_busyDeviceDisablesSwitch() {
         setupDevice(makeDefaultDeviceConfig());
-        addMockA2dpProfile(true, true, true);
+        addA2dpProfileToDevice(true, true, true);
         when(mCachedDevice.isBusy()).thenReturn(true);
         showScreen(mController);
         SwitchPreferenceCompat pref = getHighQualityAudioPref();
@@ -454,17 +474,17 @@
     @Test
     public void highQualityAudio_mediaAudioDisabledAndReEnabled() {
         setupDevice(makeDefaultDeviceConfig());
-        A2dpProfile audioProfile = addMockA2dpProfile(true, true, true);
+        addA2dpProfileToDevice(true, true, true);
         showScreen(mController);
         assertThat(mProfiles.getPreferenceCount()).isEqualTo(3);
 
         // Disabling media audio should cause the high quality audio switch to disappear, but not
         // the regular audio one.
         SwitchPreferenceCompat audioPref =
-                (SwitchPreferenceCompat) mScreen.findPreference(audioProfile.toString());
+                (SwitchPreferenceCompat) mScreen.findPreference(mA2dpProfile.toString());
         audioPref.performClick();
-        verify(audioProfile).setEnabled(mDevice, false);
-        when(audioProfile.isEnabled(mDevice)).thenReturn(false);
+        verify(mA2dpProfile).setEnabled(mDevice, false);
+        when(mA2dpProfile.isEnabled(mDevice)).thenReturn(false);
         mController.onDeviceAttributesChanged();
         assertThat(audioPref.isVisible()).isTrue();
         SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
@@ -472,8 +492,8 @@
 
         // And re-enabling media audio should make high quality switch to reappear.
         audioPref.performClick();
-        verify(audioProfile).setEnabled(mDevice, true);
-        when(audioProfile.isEnabled(mDevice)).thenReturn(true);
+        verify(mA2dpProfile).setEnabled(mDevice, true);
+        when(mA2dpProfile.isEnabled(mDevice)).thenReturn(true);
         mController.onDeviceAttributesChanged();
         highQualityAudioPref = getHighQualityAudioPref();
         assertThat(highQualityAudioPref.isVisible()).isTrue();
@@ -482,9 +502,9 @@
     @Test
     public void highQualityAudio_mediaAudioStartsDisabled() {
         setupDevice(makeDefaultDeviceConfig());
-        A2dpProfile audioProfile = addMockA2dpProfile(false, true, true);
+        addA2dpProfileToDevice(false, true, true);
         showScreen(mController);
-        SwitchPreferenceCompat audioPref = mScreen.findPreference(audioProfile.toString());
+        SwitchPreferenceCompat audioPref = mScreen.findPreference(mA2dpProfile.toString());
         SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
         assertThat(audioPref).isNotNull();
         assertThat(audioPref.isChecked()).isFalse();
@@ -522,15 +542,9 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
         setupDevice(makeDefaultDeviceConfig());
 
-        LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
-        when(leAudioProfile.getNameResource(mDevice))
-                .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
-        when(leAudioProfile.isProfileReady()).thenReturn(true);
-        when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
-        when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
+        addA2dpProfileToDevice(true, true, true);
         when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
-                .thenReturn(ImmutableSet.of("LE_AUDIO"));
-        mConnectableProfiles.add(leAudioProfile);
+                .thenReturn(ImmutableSet.of("A2DP"));
 
         showScreen(mController);
 
@@ -543,15 +557,9 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
         setupDevice(makeDefaultDeviceConfig());
 
-        LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
-        when(leAudioProfile.getNameResource(mDevice))
-                .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
-        when(leAudioProfile.isProfileReady()).thenReturn(true);
-        when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
-        when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
+        addA2dpProfileToDevice(true, true, true);
         when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
-                .thenReturn(ImmutableSet.of("A2DP"));
-        mConnectableProfiles.add(leAudioProfile);
+                .thenReturn(ImmutableSet.of("LE_AUDIO"));
 
         showScreen(mController);
 
@@ -563,19 +571,8 @@
     public void classicAudioDeviceWithLeAudio_showLeAudioToggle() {
         mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_LE_AUDIO_TOGGLE_FOR_LE_AUDIO_ONLY_DEVICE);
         setupDevice(makeDefaultDeviceConfig());
-
-        LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
-        when(leAudioProfile.getNameResource(mDevice))
-                .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
-        when(leAudioProfile.isProfileReady()).thenReturn(true);
-        when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
-        when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
-        mConnectableProfiles.add(leAudioProfile);
-        when(mCachedDevice.getProfiles())
-                .thenAnswer(
-                        invocation ->
-                                ImmutableList.of(
-                                        leAudioProfile, addMockA2dpProfile(false, false, false)));
+        addLeAudioProfileToDevice(false);
+        addA2dpProfileToDevice(false, false, false);
 
         showScreen(mController);
 
@@ -587,16 +584,7 @@
     public void leAudioOnlyDevice_hideLeAudioToggle() {
         mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_LE_AUDIO_TOGGLE_FOR_LE_AUDIO_ONLY_DEVICE);
         setupDevice(makeDefaultDeviceConfig());
-
-        LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
-        when(leAudioProfile.getNameResource(mDevice))
-                .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
-        when(leAudioProfile.isProfileReady()).thenReturn(true);
-        when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
-        when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
-        mConnectableProfiles.add(leAudioProfile);
-        when(mCachedDevice.getProfiles())
-                .thenAnswer(invocation -> ImmutableList.of(leAudioProfile));
+        addLeAudioProfileToDevice(false);
 
         showScreen(mController);