Use setCommunicationDevice to connect hearing aid BT devices. am: 0405bd349f am: 8aef2f7b73

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telecomm/+/18298493

Change-Id: I9a3456b7d42e857a9de13099fff568325bbe6f7a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 7c87cfa..81982c9 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -186,6 +186,7 @@
     private boolean mLeAudioCallbackRegistered = false;
     private BluetoothLeAudio mBluetoothLeAudioService;
     private boolean mLeAudioSetAsCommunicationDevice = false;
+    private boolean mHearingAidSetAsCommunicationDevice = false;
     private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
     private BluetoothAdapter mBluetoothAdapter;
     private AudioManager mAudioManager;
@@ -396,6 +397,7 @@
     public void disconnectAudio() {
         disconnectSco();
         clearLeAudioCommunicationDevice();
+        clearHearingAidCommunicationDevice();
     }
 
     public void disconnectSco() {
@@ -410,17 +412,43 @@
         return mLeAudioSetAsCommunicationDevice;
     }
 
+    public boolean isHearingAidSetAsCommunicationDevice() {
+        return mHearingAidSetAsCommunicationDevice;
+    }
+
     public void clearLeAudioCommunicationDevice() {
         if (!mLeAudioSetAsCommunicationDevice) {
             return;
         }
-        mLeAudioSetAsCommunicationDevice = false;
 
         if (mAudioManager == null) {
-            Log.i(this, " mAudioManager is null");
+            Log.i(this, "clearLeAudioCommunicationDevice: mAudioManager is null");
+            mLeAudioSetAsCommunicationDevice = false;
             return;
         }
-        mAudioManager.clearCommunicationDevice();
+        if (mAudioManager.getCommunicationDevice() != null
+                && mAudioManager.getCommunicationDevice().getType()
+                == AudioDeviceInfo.TYPE_BLE_HEADSET) {
+            mAudioManager.clearCommunicationDevice();
+            mLeAudioSetAsCommunicationDevice = false;
+        }
+    }
+
+    public void clearHearingAidCommunicationDevice() {
+        if (!mHearingAidSetAsCommunicationDevice) {
+            return;
+        }
+
+        if (mAudioManager == null) {
+            Log.i(this, "clearHearingAidCommunicationDevice: mAudioManager is null");
+            mHearingAidSetAsCommunicationDevice = false;
+        }
+        if (mAudioManager.getCommunicationDevice() != null
+                && mAudioManager.getCommunicationDevice().getType()
+                == AudioDeviceInfo.TYPE_HEARING_AID) {
+            mAudioManager.clearCommunicationDevice();
+            mHearingAidSetAsCommunicationDevice = false;
+        }
     }
 
     public boolean setLeAudioCommunicationDevice() {
@@ -456,6 +484,9 @@
             return false;
         }
 
+        // clear hearing aid communication device if set
+        clearHearingAidCommunicationDevice();
+
         // Turn BLE_OUT_HEADSET ON.
         boolean result = mAudioManager.setCommunicationDevice(bleHeadset);
         if (!result) {
@@ -467,6 +498,53 @@
         return result;
     }
 
+    public boolean setHearingAidCommunicationDevice() {
+        Log.i(this, "setHearingAidCommunicationDevice");
+
+        if (mHearingAidSetAsCommunicationDevice) {
+            Log.i(this, "mHearingAidSetAsCommunicationDevice already set");
+            return true;
+        }
+
+        if (mAudioManager == null) {
+            Log.w(this, " mAudioManager is null");
+            return false;
+        }
+
+        AudioDeviceInfo hearingAid = null;
+        List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices();
+        if (devices.size() == 0) {
+            Log.w(this, " No communication devices available.");
+            return false;
+        }
+
+        for (AudioDeviceInfo device : devices) {
+            Log.i(this, " Available device type:  " + device.getType());
+            if (device.getType() == AudioDeviceInfo.TYPE_HEARING_AID) {
+                hearingAid = device;
+                break;
+            }
+        }
+
+        if (hearingAid == null) {
+            Log.w(this, " No hearingAid device available");
+            return false;
+        }
+
+        // clear LE audio communication device if set
+        clearLeAudioCommunicationDevice();
+
+        // Turn hearing aid ON.
+        boolean result = mAudioManager.setCommunicationDevice(hearingAid);
+        if (!result) {
+            Log.w(this, " Could not set hearingAid device");
+        } else {
+            Log.i(this, " hearingAid device set");
+            mHearingAidSetAsCommunicationDevice = true;
+        }
+        return result;
+    }
+
     // Connect audio to the bluetooth device at address, checking to see whether it's
     // le audio, hearing aid or a HFP device, and using the proper BT API.
     public boolean connectAudio(String address) {
@@ -486,9 +564,12 @@
                 Log.w(this, "Attempting to turn on audio when the hearing aid service is null");
                 return false;
             }
-            return mBluetoothAdapter.setActiveDevice(
+            if (mBluetoothAdapter.setActiveDevice(
                     mHearingAidDevicesByAddress.get(address),
-                    BluetoothAdapter.ACTIVE_DEVICE_ALL);
+                    BluetoothAdapter.ACTIVE_DEVICE_ALL)) {
+                return setHearingAidCommunicationDevice();
+            }
+            return false;
         } else if (mHfpDevicesByAddress.containsKey(address)) {
             BluetoothDevice device = mHfpDevicesByAddress.get(address);
             if (mBluetoothHeadset == null) {
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index 8ae42cb..bd2c6f1 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -381,7 +381,10 @@
                         break;
                     case CONNECT_BT:
                         if (!switchingBtDevices) {
-                            // Ignore connection to already connected device.
+                            // Ignore connection to already connected device but still notify
+                            // CallAudioRouteStateMachine since this might be a switch from other
+                            // to this already connected BT audio
+                            mListener.onBluetoothAudioConnected();
                             break;
                         }
 
@@ -621,6 +624,9 @@
             }
         } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID) {
             mHearingAidActiveDeviceCache = device;
+            if (device == null) {
+                mDeviceManager.clearHearingAidCommunicationDevice();
+            }
         } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEADSET) {
             mHfpActiveDeviceCache = device;
         } else {
@@ -791,12 +797,14 @@
         }
 
         if (bluetoothHearingAid != null) {
-            for (BluetoothDevice device : bluetoothAdapter.getActiveDevices(
+            if (mDeviceManager.isHearingAidSetAsCommunicationDevice()) {
+                for (BluetoothDevice device : bluetoothAdapter.getActiveDevices(
                         BluetoothProfile.HEARING_AID)) {
-                if (device != null) {
-                    hearingAidActiveDevice = device;
-                    activeDevices++;
-                    break;
+                    if (device != null) {
+                        hearingAidActiveDevice = device;
+                        activeDevices++;
+                        break;
+                    }
                 }
             }
         }
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 5c5ded0..1ffcc8a 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -185,9 +185,18 @@
                      * is set as communication device before we can say that BT_AUDIO_IS_ON
                      */
                     if (!mBluetoothDeviceManager.setLeAudioCommunicationDevice()) {
-                        Log.w(LOG_TAG, "Device %s cannot be use as communication device.", device);
+                        Log.w(LOG_TAG,
+                                "Device %s cannot be use as LE audio communication device.",
+                                device);
                         return;
                     }
+                } else {
+                    /* deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID */
+                    if (!mBluetoothDeviceManager.setHearingAidCommunicationDevice()) {
+                        Log.w(LOG_TAG,
+                                "Device %s cannot be use as hearing aid communication device.",
+                                device);
+                    }
                 }
                 mBluetoothRouteManager.sendMessage(BT_AUDIO_IS_ON, args);
            }
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index 764885b..ce1e221 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -391,22 +391,33 @@
     @SmallTest
     @Test
     public void testConnectDisconnectAudioHearingAid() {
+        receiverUnderTest.setIsInCall(true);
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
-        mBluetoothDeviceManager.connectAudio(device2.getAddress());
-        verify(mAdapter).setActiveDevice(device2, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+
+        AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class);
+        when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HEARING_AID);
+        List<AudioDeviceInfo> devices = new ArrayList<>();
+        devices.add(mockAudioDeviceInfo);
+
+        when(mockAudioManager.getAvailableCommunicationDevices())
+                .thenReturn(devices);
+        when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo)))
+                .thenReturn(true);
+
+        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL);
         verify(mBluetoothHeadset, never()).connectAudio();
         verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));
 
-        when(mAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
-                .thenReturn(Arrays.asList(device2, null));
-
+        when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo);
         mBluetoothDeviceManager.disconnectAudio();
-        verify(mBluetoothHeadset).disconnectAudio();
+        verify(mockAudioManager).clearCommunicationDevice();
     }
 
     @SmallTest
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index d1d48ce..e01cbbe 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -123,7 +123,7 @@
         verifyConnectionAttempt(DEVICE1, 0);
         verifyConnectionAttempt(DEVICE2, 0);
         assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
-                        + ":" + HEARING_AID_DEVICE.getAddress(),
+                        + ":" + DEVICE1.getAddress(),
                 sm.getCurrentState().getName());
         sm.quitNow();
     }