Shows LE audio hearing aid device in a11y settings page (2/3)

Handles LE audio hearing aid in CachedBluetoothDevice. Previously
isHearingAidDevice() will only consider ASHA hearing aid, and now it
takes LE audio hearing aid into consideration as well.

Bug: 249235823
Test: make RunSettingsLibRoboTests ROBOTEST_FILTER=CachedBluetoothDeviceTest
Change-Id: I9c50a7b759b7fbcd80f1f5706909ce0a6ddc5959
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 950ee21..978e592 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -161,6 +161,8 @@
         mDevice = device;
         fillData();
         mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
+        mDeviceSide = HearingAidProfile.DeviceSide.SIDE_INVALID;
+        mDeviceMode = HearingAidProfile.DeviceMode.MODE_INVALID;
         mGroupId = BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
         initDrawableCache();
         mUnpairing = false;
@@ -363,10 +365,6 @@
         mHiSyncId = id;
     }
 
-    public boolean isHearingAidDevice() {
-        return mHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
-    }
-
     /**
      * Mark the discovered device as member of coordinated set.
      *
@@ -778,8 +776,6 @@
         ParcelUuid[] localUuids = new ParcelUuid[uuidsList.size()];
         uuidsList.toArray(localUuids);
 
-        if (localUuids == null) return false;
-
         /*
          * Now we know if the device supports PBAP, update permissions...
          */
@@ -1365,15 +1361,41 @@
     }
 
     /**
-     * @return {@code true} if {@code cachedBluetoothDevice} is Hearing Aid device
+     * @return {@code true} if {@code cachedBluetoothDevice} is ASHA hearing aid device
      */
-    public boolean isConnectedHearingAidDevice() {
+    public boolean isConnectedAshaHearingAidDevice() {
         HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
         return hearingAidProfile != null && hearingAidProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
     }
 
     /**
+     * @return {@code true} if {@code cachedBluetoothDevice} is HAP device
+     */
+    public boolean isConnectedHapClientDevice() {
+        HapClientProfile hapClientProfile = mProfileManager.getHapClientProfile();
+        return hapClientProfile != null && hapClientProfile.getConnectionStatus(mDevice)
+                == BluetoothProfile.STATE_CONNECTED;
+    }
+
+    /**
+     * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio hearing aid device
+     */
+    public boolean isConnectedLeAudioHearingAidDevice() {
+        return isConnectedHapClientDevice() && isConnectedLeAudioDevice();
+    }
+
+    /**
+     * @return {@code true} if {@code cachedBluetoothDevice} is hearing aid device
+     *
+     * The device may be an ASHA hearing aid that supports {@link HearingAidProfile} or a LeAudio
+     * hearing aid that supports {@link HapClientProfile} and {@link LeAudioProfile}.
+     */
+    public boolean isHearingAidDevice() {
+        return isConnectedAshaHearingAidDevice() || isConnectedLeAudioHearingAidDevice();
+    }
+
+    /**
      * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio device
      */
     public boolean isConnectedLeAudioDevice() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
index df6929e..b3a52b9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.media;
 
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
 import android.media.MediaRoute2Info;
 
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -32,7 +33,9 @@
      */
     public static String getId(CachedBluetoothDevice cachedDevice) {
         if (cachedDevice.isHearingAidDevice()) {
-            return Long.toString(cachedDevice.getHiSyncId());
+            if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+                return Long.toString(cachedDevice.getHiSyncId());
+            }
         }
         return cachedDevice.getAddress();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 79e9938..864725b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -74,6 +74,10 @@
     @Mock
     private HearingAidProfile mHearingAidProfile;
     @Mock
+    private HapClientProfile mHapClientProfile;
+    @Mock
+    private LeAudioProfile mLeAudioProfile;
+    @Mock
     private BluetoothDevice mDevice;
     @Mock
     private BluetoothDevice mSubDevice;
@@ -859,21 +863,21 @@
     }
 
     @Test
-    public void isConnectedHearingAidDevice_connected_returnTrue() {
+    public void isConnectedAshaHearingAidDevice_connected_returnTrue() {
         when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
         when(mHearingAidProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
 
-        assertThat(mCachedDevice.isConnectedHearingAidDevice()).isTrue();
+        assertThat(mCachedDevice.isConnectedAshaHearingAidDevice()).isTrue();
     }
 
     @Test
-    public void isConnectedHearingAidDevice_disconnected_returnFalse() {
+    public void isConnectedAshaHearingAidDevice_disconnected_returnFalse() {
         when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
         when(mHearingAidProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTED);
 
-        assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedAshaHearingAidDevice()).isFalse();
     }
 
     @Test
@@ -891,10 +895,10 @@
     }
 
     @Test
-    public void isConnectedHearingAidDevice_profileIsNull_returnFalse() {
+    public void isConnectedAshaHearingAidDevice_profileIsNull_returnFalse() {
         when(mProfileManager.getHearingAidProfile()).thenReturn(null);
 
-        assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedAshaHearingAidDevice()).isFalse();
     }
 
     @Test
@@ -987,11 +991,11 @@
 
     @Test
     public void getConnectionSummary_profileConnectedFail_showErrorMessage() {
-        final A2dpProfile profle = mock(A2dpProfile.class);
-        mCachedDevice.onProfileStateChanged(profle, BluetoothProfile.STATE_CONNECTED);
+        final A2dpProfile profile = mock(A2dpProfile.class);
+        mCachedDevice.onProfileStateChanged(profile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true);
 
-        when(profle.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED);
+        when(profile.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED);
 
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 mContext.getString(R.string.profile_connect_timeout_subtext));
@@ -1069,4 +1073,37 @@
         assertThat(mSubCachedDevice.mDevice).isEqualTo(mDevice);
         assertThat(mCachedDevice.getMemberDevice().contains(mSubCachedDevice)).isTrue();
     }
+
+    @Test
+    public void isConnectedHearingAidDevice_isConnectedAshaHearingAidDevice_returnTrue() {
+        when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+
+        assertThat(mCachedDevice.isHearingAidDevice()).isTrue();
+    }
+
+    @Test
+    public void isConnectedHearingAidDevice_isConnectedLeAudioHearingAidDevice_returnTrue() {
+        when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
+        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+
+        updateProfileStatus(mHapClientProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
+
+        assertThat(mCachedDevice.isHearingAidDevice()).isTrue();
+    }
+
+    @Test
+    public void isConnectedHearingAidDevice_isNotAnyConnectedHearingAidDevice_returnFalse() {
+        when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+        when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
+        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHapClientProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_DISCONNECTED);
+
+        assertThat(mCachedDevice.isHearingAidDevice()).isFalse();
+    }
 }