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

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

Migrate the fallback device logic of A2dp and Hfp into AudioRoutingManager

Bug: 299023147
Test: atest BluetoothInstrumentationTests
Change-Id: If1557f97456699929ce879dd53a72a572046f184
parent b6deb9c9
Loading
Loading
Loading
Loading
+82 −67
Original line number Original line Diff line number Diff line
@@ -334,6 +334,7 @@ public class AudioRoutingManager extends ActiveDeviceManager {
                return;
                return;
            }
            }
            mHearingAidConnectedDevices.add(device);
            mHearingAidConnectedDevices.add(device);
        }
        // New connected device: select it as active
        // New connected device: select it as active
        if (setHearingAidActiveDevice(device)) {
        if (setHearingAidActiveDevice(device)) {
            setA2dpActiveDevice(null, true);
            setA2dpActiveDevice(null, true);
@@ -341,7 +342,6 @@ public class AudioRoutingManager extends ActiveDeviceManager {
            setLeAudioActiveDevice(null, true);
            setLeAudioActiveDevice(null, true);
        }
        }
    }
    }
    }


    private void handleLeAudioConnected(BluetoothDevice device) {
    private void handleLeAudioConnected(BluetoothDevice device) {
        synchronized (mLock) {
        synchronized (mLock) {
@@ -675,13 +675,13 @@ public class AudioRoutingManager extends ActiveDeviceManager {
                            hearingAidService.getConnectedPeerDevices(hiSyncId));
                            hearingAidService.getConnectedPeerDevices(hiSyncId));
                }
                }
            }
            }
        }
        if (device != null) {
        if (device != null) {
            setA2dpActiveDevice(null, true);
            setA2dpActiveDevice(null, true);
            setHfpActiveDevice(null);
            setHfpActiveDevice(null);
            setLeAudioActiveDevice(null, true);
            setLeAudioActiveDevice(null, true);
        }
        }
    }
    }
    }


    private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) {
    private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) {
        synchronized (mLock) {
        synchronized (mLock) {
@@ -854,14 +854,15 @@ public class AudioRoutingManager extends ActiveDeviceManager {


    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    private boolean setHfpActiveDevice(BluetoothDevice device) {
    private boolean setHfpActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
        if (DBG) {
        if (DBG) {
            Log.d(TAG, "setHfpActiveDevice(" + device + ")");
            Log.d(TAG, "setHfpActiveDevice(" + device + ")");
        }
        }
        synchronized (mLock) {
            if (mPendingActiveDevice != null) {
            if (mPendingActiveDevice != null) {
                mHandler.removeCallbacksAndMessages(mPendingActiveDevice);
                mHandler.removeCallbacksAndMessages(mPendingActiveDevice);
                mPendingActiveDevice = null;
                mPendingActiveDevice = null;
            }
            }
        }
        final HeadsetService headsetService = mFactory.getHeadsetService();
        final HeadsetService headsetService = mFactory.getHeadsetService();
        if (headsetService == null) {
        if (headsetService == null) {
            return false;
            return false;
@@ -875,6 +876,7 @@ public class AudioRoutingManager extends ActiveDeviceManager {
        if (!headsetService.setActiveDevice(device)) {
        if (!headsetService.setActiveDevice(device)) {
            return false;
            return false;
        }
        }
        synchronized (mLock) {
            mHfpActiveDevice = device;
            mHfpActiveDevice = device;
        }
        }
        return true;
        return true;
@@ -938,7 +940,6 @@ public class AudioRoutingManager extends ActiveDeviceManager {
                            + ")"
                            + ")"
                            + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : ""));
                            + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : ""));
        }
        }
        synchronized (mLock) {
        final LeAudioService leAudioService = mFactory.getLeAudioService();
        final LeAudioService leAudioService = mFactory.getLeAudioService();
        if (leAudioService == null) {
        if (leAudioService == null) {
            return false;
            return false;
@@ -954,6 +955,7 @@ public class AudioRoutingManager extends ActiveDeviceManager {
            return false;
            return false;
        }
        }


        synchronized (mLock) {
            mLeAudioActiveDevice = device;
            mLeAudioActiveDevice = device;
            if (device == null) {
            if (device == null) {
                mLeHearingAidActiveDevice = null;
                mLeHearingAidActiveDevice = null;
@@ -1025,45 +1027,33 @@ public class AudioRoutingManager extends ActiveDeviceManager {
            }
            }
        }
        }


        A2dpService a2dpService = mFactory.getA2dpService();
        List<BluetoothDevice> hfpFallbackCandidates = removeWatchDevices(mHfpConnectedDevices);
        BluetoothDevice a2dpFallbackDevice = null;
        List<BluetoothDevice> fallbackCandidates = new ArrayList<>();
        if (a2dpService != null) {
        fallbackCandidates.addAll(mLeAudioConnectedDevices);
            a2dpFallbackDevice = a2dpService.getFallbackDevice();
        }


        HeadsetService headsetService = mFactory.getHeadsetService();
        HeadsetService headsetService = mFactory.getHeadsetService();
        BluetoothDevice headsetFallbackDevice = null;
        if (headsetService != null) {
            headsetFallbackDevice = headsetService.getFallbackDevice();
        }

        List<BluetoothDevice> connectedDevices = new ArrayList<>();
        connectedDevices.addAll(mLeAudioConnectedDevices);
        switch (mAudioManager.getMode()) {
        switch (mAudioManager.getMode()) {
            case AudioManager.MODE_NORMAL:
            case AudioManager.MODE_NORMAL:
                if (a2dpFallbackDevice != null) {
                fallbackCandidates.addAll(mA2dpConnectedDevices);
                    connectedDevices.add(a2dpFallbackDevice);
                }
                break;
                break;
            case AudioManager.MODE_RINGTONE:
            case AudioManager.MODE_RINGTONE:
                if (headsetFallbackDevice != null && headsetService.isInbandRingingEnabled()) {
                if (headsetService.isInbandRingingEnabled()) {
                    connectedDevices.add(headsetFallbackDevice);
                    fallbackCandidates.addAll(hfpFallbackCandidates);
                }
                }
                break;
                break;
            default:
            default:
                if (headsetFallbackDevice != null) {
                fallbackCandidates.addAll(hfpFallbackCandidates);
                    connectedDevices.add(headsetFallbackDevice);
        }
        }
        }
        BluetoothDevice device =
        BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(connectedDevices);
                mDbManager.getMostRecentlyConnectedDevicesInList(fallbackCandidates);
        if (device != null) {
        if (device != null) {
            if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
            if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
                if (Objects.equals(a2dpFallbackDevice, device)) {
                if (mA2dpConnectedDevices.contains(device)) {
                    if (DBG) {
                    if (DBG) {
                        Log.d(TAG, "Found an A2DP fallback device: " + device);
                        Log.d(TAG, "Found an A2DP fallback device: " + device);
                    }
                    }
                    setA2dpActiveDevice(device);
                    setA2dpActiveDevice(device);
                    if (Objects.equals(headsetFallbackDevice, device)) {
                    if (hfpFallbackCandidates.contains(device)) {
                        setHfpActiveDevice(device);
                        setHfpActiveDevice(device);
                    } else {
                    } else {
                        setHfpActiveDevice(null);
                        setHfpActiveDevice(null);
@@ -1089,13 +1079,13 @@ public class AudioRoutingManager extends ActiveDeviceManager {
                    setHearingAidActiveDevice(null, true);
                    setHearingAidActiveDevice(null, true);
                }
                }
            } else {
            } else {
                if (Objects.equals(headsetFallbackDevice, device)) {
                if (hfpFallbackCandidates.contains(device)) {
                    if (DBG) {
                    if (DBG) {
                        Log.d(TAG, "Found a HFP fallback device: " + device);
                        Log.d(TAG, "Found a HFP fallback device: " + device);
                    }
                    }
                    setHfpActiveDevice(device);
                    setHfpActiveDevice(device);
                    if (Objects.equals(a2dpFallbackDevice, device)) {
                    if (mA2dpConnectedDevices.contains(device)) {
                        setA2dpActiveDevice(a2dpFallbackDevice);
                        setA2dpActiveDevice(device);
                    } else {
                    } else {
                        setA2dpActiveDevice(null, true);
                        setA2dpActiveDevice(null, true);
                    }
                    }
@@ -1144,6 +1134,31 @@ public class AudioRoutingManager extends ActiveDeviceManager {
        }
        }
    }
    }


    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    List<BluetoothDevice> removeWatchDevices(List<BluetoothDevice> devices) {
        List<BluetoothDevice> fallbackCandidates;
        synchronized (mLock) {
            fallbackCandidates = new ArrayList<>(devices);
        }
        List<BluetoothDevice> uninterestedCandidates = new ArrayList<>();
        for (BluetoothDevice device : fallbackCandidates) {
            byte[] deviceType =
                    mDbManager.getCustomMeta(device, BluetoothDevice.METADATA_DEVICE_TYPE);
            BluetoothClass deviceClass = device.getBluetoothClass();
            if ((deviceClass != null
                            && deviceClass.getMajorDeviceClass()
                                    == BluetoothClass.Device.WEARABLE_WRIST_WATCH)
                    || (deviceType != null
                            && BluetoothDevice.DEVICE_TYPE_WATCH.equals(new String(deviceType)))) {
                uninterestedCandidates.add(device);
            }
        }
        for (BluetoothDevice device : uninterestedCandidates) {
            fallbackCandidates.remove(device);
        }
        return fallbackCandidates;
    }

    @VisibleForTesting
    @VisibleForTesting
    BluetoothDevice getA2dpActiveDevice() {
    BluetoothDevice getA2dpActiveDevice() {
        synchronized (mLock) {
        synchronized (mLock) {
+0 −26
Original line number Original line Diff line number Diff line
@@ -62,7 +62,6 @@ import org.mockito.MockitoAnnotations;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Objects;


@MediumTest
@MediumTest
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
@@ -146,31 +145,6 @@ public class AudioRoutingManagerTest {
        when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId);
        when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId);
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId))
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId))
                .thenReturn(connectedHearingAidDevices);
                .thenReturn(connectedHearingAidDevices);

        when(mA2dpService.getFallbackDevice())
                .thenAnswer(
                        invocation -> {
                            if (!mDeviceConnectionStack.isEmpty()
                                    && Objects.equals(
                                            mA2dpDevice,
                                            mDeviceConnectionStack.get(
                                                    mDeviceConnectionStack.size() - 1))) {
                                return mA2dpDevice;
                            }
                            return null;
                        });
        when(mHeadsetService.getFallbackDevice())
                .thenAnswer(
                        invocation -> {
                            if (!mDeviceConnectionStack.isEmpty()
                                    && Objects.equals(
                                            mHeadsetDevice,
                                            mDeviceConnectionStack.get(
                                                    mDeviceConnectionStack.size() - 1))) {
                                return mHeadsetDevice;
                            }
                            return null;
                        });
    }
    }


    @After
    @After