Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 026ff5a8 authored by Krzysztof Kopyściński's avatar Krzysztof Kopyściński Committed by Krzysztof Kopyscinski (xWF)
Browse files

ActiveDeviceManager: stop audio when switched between ASHA and LE Audio

Depending if fallback device is already available or not, audio playback
was continued or not. This is unconsistent behavior for scenario when
same device is switching from ASHA to LE Audio profile. Now,
check if fallback device exists, and if it does, if the profile is
different. If the type changes, stop audio.

Bug: 368221990
Bug: 369799111:
Test: atest ActiveDeviceManagerTest
Flag: com.android.bluetooth.flags.adm_verify_active_fallback_device
Change-Id: I290a795db89aa75fcffa5518f16acbe5712ecf1c
parent 5db7f576
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -408,12 +408,18 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
            }
            // New connected device: select it as active
            if (setHearingAidActiveDevice(device)) {
                final LeAudioService leAudioService = mFactory.getLeAudioService();
                setA2dpActiveDevice(null, true);
                setHfpActiveDevice(null);
                if (Flags.admVerifyActiveFallbackDevice()) {
                    setLeAudioActiveDevice(
                            null, !leAudioService.getActiveDevices().contains(device));
                } else {
                    setLeAudioActiveDevice(null, true);
                }
            }
        }
    }

    private void handleLeAudioConnected(BluetoothDevice device) {
        synchronized (mLock) {
@@ -504,7 +510,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
                            + mA2dpActiveDevice);
            mA2dpConnectedDevices.remove(device);
            if (Objects.equals(mA2dpActiveDevice, device)) {
                if (!setFallbackDeviceActiveLocked()) {
                if (!setFallbackDeviceActiveLocked(device)) {
                    setA2dpActiveDevice(null, false);
                }
            }
@@ -521,7 +527,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
                if (mHfpConnectedDevices.isEmpty()) {
                    setHfpActiveDevice(null);
                }
                setFallbackDeviceActiveLocked();
                setFallbackDeviceActiveLocked(device);
            }
        }
    }
@@ -536,7 +542,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
                            + mHearingAidActiveDevices);
            mHearingAidConnectedDevices.remove(device);
            if (mHearingAidActiveDevices.remove(device) && mHearingAidActiveDevices.isEmpty()) {
                if (!setFallbackDeviceActiveLocked()) {
                if (!setFallbackDeviceActiveLocked(device)) {
                    setHearingAidActiveDevice(null, false);
                }
            }
@@ -562,7 +568,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac

            boolean hasFallbackDevice = false;
            if (Objects.equals(mLeAudioActiveDevice, device)) {
                hasFallbackDevice = setFallbackDeviceActiveLocked();
                hasFallbackDevice = setFallbackDeviceActiveLocked(device);
                if (!hasFallbackDevice) {
                    setLeAudioActiveDevice(null, false);
                }
@@ -816,7 +822,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
                return;
            }
            synchronized (mLock) {
                setFallbackDeviceActiveLocked();
                setFallbackDeviceActiveLocked(null);
            }
        }
    }
@@ -1043,7 +1049,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
     * @return true when the fallback device is activated, false otherwise
     */
    @GuardedBy("mLock")
    private boolean setFallbackDeviceActiveLocked() {
    private boolean setFallbackDeviceActiveLocked(BluetoothDevice recentlyRemovedDevice) {
        Log.d(TAG, "setFallbackDeviceActive");
        mDbManager = mAdapterService.getDatabase();
        List<BluetoothDevice> connectedHearingAidDevices = new ArrayList<>();
@@ -1057,17 +1063,29 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
            BluetoothDevice device =
                    mDbManager.getMostRecentlyConnectedDevicesInList(connectedHearingAidDevices);
            if (device != null) {
                /* Check if fallback device shall be used. It should be used when a new
                 * device is connected. If the most recently connected device is the same as
                 * recently removed device, it means it just switched profile it is using and is
                 * not new one.
                 */
                boolean hasFallbackDevice = true;
                if (Flags.admVerifyActiveFallbackDevice()) {
                    hasFallbackDevice =
                            !(recentlyRemovedDevice != null
                                    && device.equals(recentlyRemovedDevice)
                                    && connectedHearingAidDevices.size() == 1);
                }
                if (mHearingAidConnectedDevices.contains(device)) {
                    Log.d(TAG, "Found a hearing aid fallback device: " + device);
                    setHearingAidActiveDevice(device);
                    setA2dpActiveDevice(null, true);
                    setA2dpActiveDevice(null, hasFallbackDevice);
                    setHfpActiveDevice(null);
                    setLeAudioActiveDevice(null, true);
                    setLeAudioActiveDevice(null, hasFallbackDevice);
                } else {
                    Log.d(TAG, "Found a LE hearing aid fallback device: " + device);
                    setLeHearingAidActiveDevice(device);
                    setHearingAidActiveDevice(null, true);
                    setA2dpActiveDevice(null, true);
                    setHearingAidActiveDevice(null, hasFallbackDevice);
                    setA2dpActiveDevice(null, hasFallbackDevice);
                    setHfpActiveDevice(null);
                }
                return true;
+66 −0
Original line number Diff line number Diff line
@@ -1055,6 +1055,72 @@ public class ActiveDeviceManagerTest {
        verify(mA2dpService).setActiveDevice(mA2dpDevice);
    }

    /**
     * An ASHA device connected and set to active. Same device connected as a LE Audio device. ASHA
     * disconnects with no fallback and LE Audio is set to active. New LE Audio device is connected
     * and selected as active. First LE Audio device disconnects with fallback to new one.
     */
    @Test
    @EnableFlags(Flags.FLAG_ADM_VERIFY_ACTIVE_FALLBACK_DEVICE)
    public void sameDeviceAsAshaAndLeAudio_noFallbackOnSwitch() {
        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);

        /* Connect first device as ASHA */
        hearingAidConnected(mHearingAidDevice);
        mTestLooper.dispatchAll();
        verify(mHearingAidService).setActiveDevice(mHearingAidDevice);

        /* Connect first device as LE Audio */
        leAudioConnected(mHearingAidDevice);
        hearingAidDisconnected(mHearingAidDevice);
        mTestLooper.dispatchAll();
        verify(mHearingAidService).removeActiveDevice(false);
        verify(mLeAudioService).setActiveDevice(mHearingAidDevice);

        /* Connect second device as LE Audio. First device is disconnected with fallback to
         * new one.
         */
        leAudioConnected(mLeAudioDevice);
        leAudioDisconnected(mHearingAidDevice);
        mTestLooper.dispatchAll();
        verify(mLeAudioService).removeActiveDevice(true);
        verify(mLeAudioService).setActiveDevice(mLeAudioDevice);
    }

    /**
     * A LE Audio device connected and set to active. Same device connected as an ASHA device. LE
     * Audio disconnects with no fallback and ASHA is set to active. New ASHA device is connected
     * and selected as active. First ASHA device disconnects with fallback to new one.
     */
    @Test
    @EnableFlags(Flags.FLAG_ADM_VERIFY_ACTIVE_FALLBACK_DEVICE)
    public void sameDeviceAsLeAudioAndAsha_noFallbackOnSwitch() {
        // Turn on the dual mode audio flag so the A2DP won't disconnect LE Audio
        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
        List<BluetoothDevice> list = new ArrayList<>();
        when(mLeAudioService.getActiveDevices()).thenReturn(list);

        /* Connect first device as LE Audio */
        leAudioConnected(mHearingAidDevice);
        list.add(mHearingAidDevice);
        mTestLooper.dispatchAll();
        verify(mLeAudioService).setActiveDevice(mHearingAidDevice);

        /* Connect first device as ASHA */
        hearingAidConnected(mHearingAidDevice);
        leAudioDisconnected(mHearingAidDevice);
        mTestLooper.dispatchAll();
        verify(mHearingAidService).setActiveDevice(mHearingAidDevice);
        verify(mLeAudioService).removeActiveDevice(false);

        /* Connect second device as ASHA. It is set as fallback device for LE Audio Service
         */
        hearingAidConnected(mSecondaryAudioDevice);
        mTestLooper.dispatchAll();
        verify(mLeAudioService).removeActiveDevice(true);
        verify(mHearingAidService).setActiveDevice(mSecondaryAudioDevice);
    }

    /**
     * Two Hearing Aid are connected and the current active is then disconnected. Should then set
     * active device to fallback device.