Set communication device when device become active Bluetooth device

There is no need to double time set device as communication device.
First one when connecting audio in Telecomm and second time when device
becomes active (send ACTIVE_DEVICE_CHANGED broadcast intent).

Only already active device can be communication device, it can be
directly set (not changing audio device).

Tag: #feature
Bug: 258555681
Test: atest GoogleBluetoothInstrumentationTests
Change-Id: I559e1ba6880cd6d429031b81622bf30c981526e2
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 7968dca..64a3f20 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -558,7 +558,7 @@
 
     // 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) {
+    public boolean connectAudio(String address, boolean switchingBtDevices) {
         if (mLeAudioDevicesByAddress.containsKey(address)) {
             if (mBluetoothLeAudioService == null) {
                 Log.w(this, "Attempting to turn on audio when the le audio service is null");
@@ -567,7 +567,15 @@
             BluetoothDevice device = mLeAudioDevicesByAddress.get(address);
             if (mBluetoothAdapter.setActiveDevice(
                     device, BluetoothAdapter.ACTIVE_DEVICE_ALL)) {
-                return setLeAudioCommunicationDevice();
+
+                /* ACTION_ACTIVE_DEVICE_CHANGED intent will trigger setting communication device.
+                 * Only after receiving ACTION_ACTIVE_DEVICE_CHANGED it is known that device that
+                 * will be audio switched to is available to be choose as communication device */
+                if (!switchingBtDevices) {
+                    return setLeAudioCommunicationDevice();
+                }
+
+                return true;
             }
             return false;
         } else if (mHearingAidDevicesByAddress.containsKey(address)) {
@@ -578,7 +586,15 @@
             if (mBluetoothAdapter.setActiveDevice(
                     mHearingAidDevicesByAddress.get(address),
                     BluetoothAdapter.ACTIVE_DEVICE_ALL)) {
-                return setHearingAidCommunicationDevice();
+
+                /* ACTION_ACTIVE_DEVICE_CHANGED intent will trigger setting communication device.
+                 * Only after receiving ACTION_ACTIVE_DEVICE_CHANGED it is known that device that
+                 * will be audio switched to is available to be choose as communication device */
+                if (!switchingBtDevices) {
+                    return setHearingAidCommunicationDevice();
+                }
+
+                return true;
             }
             return false;
         } else if (mHfpDevicesByAddress.containsKey(address)) {
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index bd2c6f1..fea663d 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -713,7 +713,7 @@
             return null;
         }
 
-        if (!mDeviceManager.connectAudio(actualAddress)) {
+        if (!mDeviceManager.connectAudio(actualAddress, switchingBtDevices)) {
             boolean shouldRetry = retryCount < MAX_CONNECTION_RETRIES;
             Log.w(LOG_TAG, "Could not connect to %s. Will %s", actualAddress,
                     shouldRetry ? "retry" : "not retry");
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index 81f476e..6c7c0ac 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -386,7 +386,7 @@
                         BluetoothDeviceManager.DEVICE_TYPE_HEADSET));
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                     eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
-        mBluetoothDeviceManager.connectAudio(device1.getAddress());
+        mBluetoothDeviceManager.connectAudio(device1.getAddress(), false);
         verify(mAdapter).setActiveDevice(device1, BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL);
         verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL));
@@ -415,12 +415,15 @@
         when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo)))
                 .thenReturn(true);
 
-        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        mBluetoothDeviceManager.connectAudio(device5.getAddress(), false);
         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));
 
+        receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device5,
+                BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
+
         when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo);
         mBluetoothDeviceManager.disconnectAudio();
         verify(mockAudioManager).clearCommunicationDevice();
@@ -447,12 +450,15 @@
         when(mockAudioManager.setCommunicationDevice(mockAudioDeviceInfo))
                        .thenReturn(true);
 
-        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        mBluetoothDeviceManager.connectAudio(device5.getAddress(), false);
         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));
 
+        receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device5,
+                BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
+
         mBluetoothDeviceManager.disconnectAudio();
         verify(mockAudioManager).clearCommunicationDevice();
     }
@@ -471,7 +477,7 @@
         leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1);
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
-        mBluetoothDeviceManager.connectAudio(device5.getAddress());
+        mBluetoothDeviceManager.connectAudio(device5.getAddress(), false);
         verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL);
         verify(mBluetoothHeadset, never()).connectAudio();
         verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
@@ -484,7 +490,7 @@
                 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
 
-        mBluetoothDeviceManager.connectAudio(device6.getAddress());
+        mBluetoothDeviceManager.connectAudio(device6.getAddress(), false);
         verify(mAdapter).setActiveDevice(device6, BluetoothAdapter.ACTIVE_DEVICE_ALL);
     }
 
@@ -530,6 +536,31 @@
         return i;
     }
 
+
+    private Intent buildActiveDeviceChangeActionIntent(BluetoothDevice device, int deviceType) {
+        String intentString;
+
+        switch (deviceType) {
+            case BluetoothDeviceManager.DEVICE_TYPE_HEADSET:
+                intentString = BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED;
+                break;
+            case BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID:
+                intentString = BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED;
+                break;
+            case BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO:
+                intentString = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED;
+                break;
+            default:
+                return null;
+        }
+
+        Intent i = new Intent(intentString);
+        i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+        i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        return i;
+    }
+
     private BluetoothDevice makeBluetoothDevice(String address) {
         Parcel p1 = Parcel.obtain();
         p1.writeString(address);
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index e01cbbe..1a6fb88 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -48,6 +48,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.reset;
@@ -245,6 +246,7 @@
     }
 
     private void verifyConnectionAttempt(BluetoothDevice device, int numTimes) {
-        verify(mDeviceManager, times(numTimes)).connectAudio(device.getAddress());
+        verify(mDeviceManager, times(numTimes)).connectAudio(eq(device.getAddress()),
+            anyBoolean());
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
index b729f35..5eecccc 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
@@ -359,18 +359,22 @@
 
         switch (mParams.expectedBluetoothInteraction) {
             case NONE:
-                verify(mDeviceManager, never()).connectAudio(nullable(String.class));
+                verify(mDeviceManager, never()).connectAudio(nullable(String.class),
+                    any(boolean.class));
                 break;
             case CONNECT:
-                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress());
+                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress(),
+                    false);
                 verify(mDeviceManager, never()).disconnectAudio();
                 break;
             case CONNECT_SWITCH_DEVICE:
                 verify(mDeviceManager).disconnectAudio();
-                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress());
+                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress(),
+                    true);
             break;
             case DISCONNECT:
-                verify(mDeviceManager, never()).connectAudio(nullable(String.class));
+                verify(mDeviceManager, never()).connectAudio(nullable(String.class),
+                    any(boolean.class));
                 verify(mDeviceManager).disconnectAudio();
                 break;
         }
@@ -402,7 +406,8 @@
         when(mDeviceManager.getBluetoothHeadset()).thenReturn(mBluetoothHeadset);
         when(mDeviceManager.getBluetoothHearingAid()).thenReturn(mBluetoothHearingAid);
         when(mDeviceManager.getLeAudioService()).thenReturn(mBluetoothLeAudio);
-        when(mDeviceManager.connectAudio(nullable(String.class))).thenReturn(true);
+        when(mDeviceManager.connectAudio(nullable(String.class), any(boolean.class)))
+            .thenReturn(true);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(100000L);
         when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis(