Add Spatial audio settings for LE Audio devices

- Adds TYPE_BLE_HEADSE, TYPE_BLE_SPEAKER and TYPE_BLE_BROADCAST for
  display Le audio devices.
- Adds TYPE_HEARING_AID for display hearing aid devices.

Bug: 244528781
Test: make -j64 RunSettingsRoboTests
Change-Id: I1278a5e0c93fdc5a4873df68032128ffedfe72d6
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
index 89d923d..29066b8 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
@@ -53,6 +53,8 @@
     @VisibleForTesting
     AudioDeviceAttributes mAudioDevice;
 
+    private boolean mIsAvailable;
+
     public BluetoothDetailsSpatialAudioController(
             Context context,
             PreferenceFragmentCompat fragment,
@@ -61,16 +63,13 @@
         super(context, fragment, device, lifecycle);
         AudioManager audioManager = context.getSystemService(AudioManager.class);
         mSpatializer = audioManager.getSpatializer();
-        mAudioDevice = new AudioDeviceAttributes(
-                AudioDeviceAttributes.ROLE_OUTPUT,
-                AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
-                mCachedDevice.getAddress());
+        getAvailableDevice();
 
     }
 
     @Override
     public boolean isAvailable() {
-        return mSpatializer.isAvailableForDevice(mAudioDevice) ? true : false;
+        return mIsAvailable;
     }
 
     @Override
@@ -152,4 +151,52 @@
         pref.setOnPreferenceClickListener(this);
         return pref;
     }
+
+    private void getAvailableDevice() {
+        AudioDeviceAttributes a2dpDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
+                mCachedDevice.getAddress());
+        AudioDeviceAttributes bleHeadsetDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_HEADSET,
+                mCachedDevice.getAddress());
+        AudioDeviceAttributes bleSpeakerDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_SPEAKER,
+                mCachedDevice.getAddress());
+        AudioDeviceAttributes bleBroadcastDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_BROADCAST,
+                mCachedDevice.getAddress());
+        AudioDeviceAttributes hearingAidDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_HEARING_AID,
+                mCachedDevice.getAddress());
+
+        mIsAvailable = true;
+        if (mSpatializer.isAvailableForDevice(bleHeadsetDevice)) {
+            mAudioDevice = bleHeadsetDevice;
+        } else if (mSpatializer.isAvailableForDevice(bleSpeakerDevice)) {
+            mAudioDevice = bleSpeakerDevice;
+        } else if (mSpatializer.isAvailableForDevice(bleBroadcastDevice)) {
+            mAudioDevice = bleBroadcastDevice;
+        } else if (mSpatializer.isAvailableForDevice(a2dpDevice)) {
+            mAudioDevice = a2dpDevice;
+        } else {
+            mIsAvailable = mSpatializer.isAvailableForDevice(hearingAidDevice);
+            mAudioDevice = hearingAidDevice;
+        }
+
+        Log.d(TAG, "getAvailableDevice() device : "
+                + mCachedDevice.getDevice().getAnonymizedAddress()
+                + ", type : " + mAudioDevice.getType()
+                + ", is available : " + mIsAvailable);
+    }
+
+    @VisibleForTesting
+    void setAvailableDevice(AudioDeviceAttributes audioDevice) {
+        mAudioDevice = audioDevice;
+        mIsAvailable = mSpatializer.isAvailableForDevice(audioDevice);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
index ef81247..1f0adcf 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
@@ -22,7 +22,9 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.bluetooth.BluetoothDevice;
 import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
 import android.media.Spatializer;
 
@@ -57,6 +59,8 @@
     private Lifecycle mSpatialAudioLifecycle;
     @Mock
     private PreferenceCategory mProfilesContainer;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
 
     private BluetoothDetailsSpatialAudioController mController;
     private SwitchPreference mSpatialAudioPref;
@@ -70,6 +74,8 @@
         when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
         when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
         when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS);
+        when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
+        when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(MAC_ADDRESS);
 
         mController = new BluetoothDetailsSpatialAudioController(mContext, mFragment,
                 mCachedDevice, mSpatialAudioLifecycle);
@@ -83,15 +89,85 @@
     }
 
     @Test
-    public void isAvailable_spatialAudioIsAvailable_returnsTrue() {
-        when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true);
+    public void isAvailable_spatialAudioSupportA2dpDevice_returnsTrue() {
+        AudioDeviceAttributes a2dpDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
+                MAC_ADDRESS);
+        when(mSpatializer.isAvailableForDevice(a2dpDevice)).thenReturn(true);
+
+        mController.setAvailableDevice(a2dpDevice);
+
         assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
     }
 
     @Test
-    public void isAvailable_spatialAudioIsNotAvailable_returnsFalse() {
-        when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(false);
+    public void isAvailable_spatialAudioSupportBleHeadsetDevice_returnsTrue() {
+        AudioDeviceAttributes bleHeadsetDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_HEADSET,
+                MAC_ADDRESS);
+        when(mSpatializer.isAvailableForDevice(bleHeadsetDevice)).thenReturn(true);
+
+        mController.setAvailableDevice(bleHeadsetDevice);
+
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_BLE_HEADSET);
+    }
+
+    @Test
+    public void isAvailable_spatialAudioSupportBleSpeakerDevice_returnsTrue() {
+        AudioDeviceAttributes bleSpeakerDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_SPEAKER,
+                MAC_ADDRESS);
+        when(mSpatializer.isAvailableForDevice(bleSpeakerDevice)).thenReturn(true);
+
+        mController.setAvailableDevice(bleSpeakerDevice);
+
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_BLE_SPEAKER);
+    }
+
+    @Test
+    public void isAvailable_spatialAudioSupportBleBroadcastDevice_returnsTrue() {
+        AudioDeviceAttributes bleBroadcastDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_BLE_BROADCAST,
+                MAC_ADDRESS);
+        when(mSpatializer.isAvailableForDevice(bleBroadcastDevice)).thenReturn(true);
+
+        mController.setAvailableDevice(bleBroadcastDevice);
+
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_BLE_BROADCAST);
+    }
+
+    @Test
+    public void isAvailable_spatialAudioSupportHearingAidDevice_returnsTrue() {
+        AudioDeviceAttributes hearingAidDevice = new AudioDeviceAttributes(
+                AudioDeviceAttributes.ROLE_OUTPUT,
+                AudioDeviceInfo.TYPE_HEARING_AID,
+                MAC_ADDRESS);
+        when(mSpatializer.isAvailableForDevice(hearingAidDevice)).thenReturn(true);
+
+        mController.setAvailableDevice(hearingAidDevice);
+
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID);
+    }
+
+    @Test
+    public void isAvailable_spatialAudioNotSupported_returnsFalse() {
         assertThat(mController.isAvailable()).isFalse();
+        assertThat(mController.mAudioDevice.getType())
+                .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID);
     }
 
     @Test