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

Commit b9fafb10 authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Activate HFP and A2DP at the same time

When BT classic is connected there is time gap between HFP
connection and A2DP connection. So if BT classic is connected
while LE audio is in use, there are some change the audio comes
from phone speaker for a while.
This CL fixes that issue by activating both HFP and A2DP
at the same time.

Bug: 247453067
Test: atest BluetoothInstrumentationTests:ActiveDeviceManagerTest
Change-Id: Ie1ab1582732b4faa7b29b9f2f6dd543b4ba96a51
parent 7af58be5
Loading
Loading
Loading
Loading
+331 −252
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.hearingaid.HearingAidService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.le_audio.LeAudioService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
@@ -120,16 +121,28 @@ class ActiveDeviceManager {
    private final AudioManager mAudioManager;
    private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;

    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final List<BluetoothDevice> mA2dpConnectedDevices = new ArrayList<>();
    @GuardedBy("mLock")
    private final List<BluetoothDevice> mHfpConnectedDevices = new ArrayList<>();
    @GuardedBy("mLock")
    private final List<BluetoothDevice> mHearingAidConnectedDevices = new ArrayList<>();
    @GuardedBy("mLock")
    private final List<BluetoothDevice> mLeAudioConnectedDevices = new ArrayList<>();
    @GuardedBy("mLock")
    private final List<BluetoothDevice> mLeHearingAidConnectedDevices = new ArrayList<>();
    @GuardedBy("mLock")
    private List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>();
    @GuardedBy("mLock")
    private BluetoothDevice mA2dpActiveDevice = null;
    @GuardedBy("mLock")
    private BluetoothDevice mHfpActiveDevice = null;
    @GuardedBy("mLock")
    private final Set<BluetoothDevice> mHearingAidActiveDevices = new ArraySet<>();
    @GuardedBy("mLock")
    private BluetoothDevice mLeAudioActiveDevice = null;
    @GuardedBy("mLock")
    private BluetoothDevice mLeHearingAidActiveDevice = null;

    // Broadcast receiver for all changes
@@ -225,6 +238,7 @@ class ActiveDeviceManager {
    }

    private void handleA2dpConnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleA2dpConnected: " + device);
            }
@@ -235,12 +249,26 @@ class ActiveDeviceManager {
            mA2dpConnectedDevices.add(device);
            if (mHearingAidActiveDevices.isEmpty() && mLeHearingAidActiveDevice == null) {
                // New connected device: select it as active
                // Activate HFP and A2DP at the same time if both profile already connected.
                if (mHfpConnectedDevices.contains(device)) {
                    setA2dpActiveDevice(device);
                    setHfpActiveDevice(device);
                    setLeAudioActiveDevice(null);
                    return;
                }
                DatabaseManager dbManager = mAdapterService.getDatabase();
                // Activate A2DP, if HFP is not supported or enabled.
                if (dbManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET)
                        != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                    setA2dpActiveDevice(device);
                    setLeAudioActiveDevice(null);
                }
            }
        }
    }

    private void handleHfpConnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHfpConnected: " + device);
            }
@@ -250,12 +278,26 @@ class ActiveDeviceManager {
            mHfpConnectedDevices.add(device);
            if (mHearingAidActiveDevices.isEmpty() && mLeHearingAidActiveDevice == null) {
                // New connected device: select it as active
                // Activate HFP and A2DP at the same time once both profile connected.
                if (mA2dpConnectedDevices.contains(device)) {
                    setA2dpActiveDevice(device);
                    setHfpActiveDevice(device);
                    setLeAudioActiveDevice(null);
                    return;
                }
                DatabaseManager dbManager = mAdapterService.getDatabase();
                // Activate HFP, if A2DP is not supported or enabled.
                if (dbManager.getProfileConnectionPolicy(device, BluetoothProfile.A2DP)
                        != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                    setHfpActiveDevice(device);
                    setLeAudioActiveDevice(null);
                }
            }
        }
    }

    private void handleHearingAidConnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHearingAidConnected: " + device);
            }
@@ -269,8 +311,10 @@ class ActiveDeviceManager {
            setHfpActiveDevice(null);
            setLeAudioActiveDevice(null);
        }
    }

    private void handleLeAudioConnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleLeAudioConnected: " + device);
            }
@@ -292,8 +336,10 @@ class ActiveDeviceManager {
                setHfpActiveDevice(null);
            }
        }
    }

    private void handleHapConnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHapConnected: " + device);
            }
@@ -313,8 +359,10 @@ class ActiveDeviceManager {
                setHfpActiveDevice(null);
            }
        }
    }

    private void handleA2dpDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleA2dpDisconnected: " + device);
            }
@@ -323,11 +371,13 @@ class ActiveDeviceManager {
                if (mA2dpConnectedDevices.isEmpty()) {
                    setA2dpActiveDevice(null);
                }
            setFallbackDeviceActive();
                setFallbackDeviceActiveLocked();
            }
        }
    }

    private void handleHfpDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHfpDisconnected: " + device);
            }
@@ -336,11 +386,13 @@ class ActiveDeviceManager {
                if (mHfpConnectedDevices.isEmpty()) {
                    setHfpActiveDevice(null);
                }
            setFallbackDeviceActive();
                setFallbackDeviceActiveLocked();
            }
        }
    }

    private void handleHearingAidDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHearingAidDisconnected: " + device);
            }
@@ -349,11 +401,13 @@ class ActiveDeviceManager {
                if (mHearingAidConnectedDevices.isEmpty()) {
                    setHearingAidActiveDevice(null);
                }
            setFallbackDeviceActive();
                setFallbackDeviceActiveLocked();
            }
        }
    }

    private void handleLeAudioDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleLeAudioDisconnected: " + device);
            }
@@ -363,11 +417,13 @@ class ActiveDeviceManager {
                if (mLeAudioConnectedDevices.isEmpty()) {
                    setLeAudioActiveDevice(null);
                }
            setFallbackDeviceActive();
                setFallbackDeviceActiveLocked();
            }
        }
    }

    private void handleHapDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHapDisconnected: " + device);
            }
@@ -377,8 +433,10 @@ class ActiveDeviceManager {
                mLeHearingAidActiveDevice = null;
            }
        }
    }

    private void handleA2dpActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleA2dpActiveDeviceChanged: " + device);
            }
@@ -392,8 +450,10 @@ class ActiveDeviceManager {
            // Just assign locally the new value
            mA2dpActiveDevice = device;
        }
    }

    private void handleHfpActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHfpActiveDeviceChanged: " + device);
            }
@@ -407,8 +467,10 @@ class ActiveDeviceManager {
            // Just assign locally the new value
            mHfpActiveDevice = device;
        }
    }

    private void handleHearingAidActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHearingAidActiveDeviceChanged: " + device);
            }
@@ -416,7 +478,7 @@ class ActiveDeviceManager {
            final HearingAidService hearingAidService = mFactory.getHearingAidService();
            if (hearingAidService != null) {
                long hiSyncId = hearingAidService.getHiSyncId(device);
            if (getHearingAidActiveHiSyncId() == hiSyncId) {
                if (getHearingAidActiveHiSyncIdLocked() == hiSyncId) {
                    mHearingAidActiveDevices.add(device);
                } else {
                    mHearingAidActiveDevices.clear();
@@ -430,8 +492,10 @@ class ActiveDeviceManager {
                setLeAudioActiveDevice(null);
            }
        }
    }

    private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleLeAudioActiveDeviceChanged: " + device);
            }
@@ -446,8 +510,10 @@ class ActiveDeviceManager {
            }
            mLeAudioActiveDevice = device;
        }
    }

    private void handleHapActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "handleHapActiveDeviceChanged: " + device);
            }
@@ -463,6 +529,7 @@ class ActiveDeviceManager {
            mLeAudioActiveDevice = device;
            mLeHearingAidActiveDevice = device;
        }
    }

    /** Notifications of audio device connection and disconnection events. */
    @SuppressLint("AndroidFrameworkRequiresPermission")
@@ -567,6 +634,7 @@ class ActiveDeviceManager {
    }

    private void setA2dpActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "setA2dpActiveDevice(" + device + ")");
            }
@@ -579,9 +647,11 @@ class ActiveDeviceManager {
            }
            mA2dpActiveDevice = device;
        }
    }

    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    private void setHfpActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "setHfpActiveDevice(" + device + ")");
            }
@@ -598,8 +668,10 @@ class ActiveDeviceManager {
                mHfpActiveDevice = device;
            }
        }
    }

    private void setHearingAidActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "setHearingAidActiveDevice(" + device + ")");
            }
@@ -615,7 +687,7 @@ class ActiveDeviceManager {
            }

            long hiSyncId = hearingAidService.getHiSyncId(device);
        if (getHearingAidActiveHiSyncId() == hiSyncId) {
            if (getHearingAidActiveHiSyncIdLocked() == hiSyncId) {
                mHearingAidActiveDevices.add(device);
                return;
            }
@@ -626,8 +698,10 @@ class ActiveDeviceManager {
            mHearingAidActiveDevices.clear();
            mHearingAidActiveDevices.addAll(hearingAidService.getConnectedPeerDevices(hiSyncId));
        }
    }

    private void setLeAudioActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "setLeAudioActiveDevice(" + device + ")");
            }
@@ -644,8 +718,10 @@ class ActiveDeviceManager {
                mPendingLeHearingAidActiveDevice.remove(device);
            }
        }
    }

    private void setLeHearingAidActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (!Objects.equals(mLeAudioActiveDevice, device)) {
                setLeAudioActiveDevice(device);
            }
@@ -655,8 +731,9 @@ class ActiveDeviceManager {
                mPendingLeHearingAidActiveDevice.remove(device);
            }
        }
    }

    private void setFallbackDeviceActive() {
    private void setFallbackDeviceActiveLocked() {
        if (DBG) {
            Log.d(TAG, "setFallbackDeviceActive");
        }
@@ -769,6 +846,7 @@ class ActiveDeviceManager {
    }

    private void resetState() {
        synchronized (mLock) {
            mA2dpConnectedDevices.clear();
            mA2dpActiveDevice = null;

@@ -785,6 +863,7 @@ class ActiveDeviceManager {
            mLeHearingAidActiveDevice = null;
            mPendingLeHearingAidActiveDevice.clear();
        }
    }

    @VisibleForTesting
    BroadcastReceiver getBroadcastReceiver() {
@@ -811,7 +890,7 @@ class ActiveDeviceManager {
        return mLeAudioActiveDevice;
    }

    long getHearingAidActiveHiSyncId() {
    long getHearingAidActiveHiSyncIdLocked() {
        final HearingAidService hearingAidService = mFactory.getHearingAidService();
        if (hearingAidService != null && !mHearingAidActiveDevices.isEmpty()) {
            return hearingAidService.getHiSyncId(mHearingAidActiveDevices.iterator().next());
+61 −53

File changed.

Preview size limit exceeded, changes collapsed.