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

Commit e91ab8dc authored by Rahul Sabnis's avatar Rahul Sabnis
Browse files

Active device setters now return a boolean

Also ensures that we do not clear the active device for other profiles
upon connection unless making a device active for the connected profile
succeeds

Bug: 277008617
Test: atest ActiveDeviceManagerTest
Change-Id: I6edac61f081207c4196992fca7ceeac4378f4775
parent 3693e36e
Loading
Loading
Loading
Loading
+73 −52
Original line number Diff line number Diff line
@@ -262,9 +262,9 @@ class ActiveDeviceManager {
                // 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);
                    if (!Utils.isDualModeAudioEnabled()) {
                    boolean a2dpMadeActive = setA2dpActiveDevice(device);
                    boolean hfpMadeActive = setHfpActiveDevice(device);
                    if ((a2dpMadeActive || hfpMadeActive) && !Utils.isDualModeAudioEnabled()) {
                        setLeAudioActiveDevice(null, true);
                    }
                    return;
@@ -273,8 +273,8 @@ class ActiveDeviceManager {
                // Activate A2DP, if HFP is not supported or enabled.
                if (dbManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET)
                        != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                    setA2dpActiveDevice(device);
                    if (!Utils.isDualModeAudioEnabled()) {
                    boolean a2dpMadeActive = setA2dpActiveDevice(device);
                    if (a2dpMadeActive && !Utils.isDualModeAudioEnabled()) {
                        setLeAudioActiveDevice(null, true);
                    }
                }
@@ -306,9 +306,12 @@ class ActiveDeviceManager {
                // 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);
                    if (!Utils.isDualModeAudioEnabled()) {
                    boolean a2dpMadeActive = setA2dpActiveDevice(device);
                    boolean hfpMadeActive = setHfpActiveDevice(device);

                    /* Make LEA inactive if device is made active for any classic audio profile
                    and dual mode is disabled */
                    if ((a2dpMadeActive || hfpMadeActive) && !Utils.isDualModeAudioEnabled()) {
                        setLeAudioActiveDevice(null, true);
                    }
                    return;
@@ -317,8 +320,11 @@ class ActiveDeviceManager {
                // Activate HFP, if A2DP is not supported or enabled.
                if (dbManager.getProfileConnectionPolicy(device, BluetoothProfile.A2DP)
                        != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                    setHfpActiveDevice(device);
                    if (!Utils.isDualModeAudioEnabled()) {
                    // Tries to make the device active for HFP
                    boolean hfpMadeActive = setHfpActiveDevice(device);

                    // Makes LEA inactive if device is made active for HFP & dual mode is disabled
                    if (hfpMadeActive && !Utils.isDualModeAudioEnabled()) {
                        setLeAudioActiveDevice(null, true);
                    }
                }
@@ -336,12 +342,13 @@ class ActiveDeviceManager {
            }
            mHearingAidConnectedDevices.add(device);
            // New connected device: select it as active
            setHearingAidActiveDevice(device);
            if (setHearingAidActiveDevice(device)) {
                setA2dpActiveDevice(null, true);
                setHfpActiveDevice(null);
                setLeAudioActiveDevice(null, true);
            }
        }
    }

    private void handleLeAudioConnected(BluetoothDevice device) {
        synchronized (mLock) {
@@ -364,19 +371,20 @@ class ActiveDeviceManager {
                    && mLeHearingAidActiveDevice == null
                    && mPendingLeHearingAidActiveDevice.isEmpty()) {
                // New connected device: select it as active
                setLeAudioActiveDevice(device);
                if (!Utils.isDualModeAudioEnabled()) {
                boolean leAudioMadeActive = setLeAudioActiveDevice(device);
                if (leAudioMadeActive && !Utils.isDualModeAudioEnabled()) {
                    setA2dpActiveDevice(null, true);
                    setHfpActiveDevice(null);
                }
            } else if (mPendingLeHearingAidActiveDevice.contains(device)) {
                setLeHearingAidActiveDevice(device);
                if (setLeHearingAidActiveDevice(device)) {
                    setHearingAidActiveDevice(null, true);
                    setA2dpActiveDevice(null, true);
                    setHfpActiveDevice(null);
                }
            }
        }
    }

    private void handleHapConnected(BluetoothDevice device) {
        synchronized (mLock) {
@@ -393,13 +401,14 @@ class ActiveDeviceManager {
                mLeHearingAidActiveDevice = device;
            } else {
                // New connected device: select it as active
                setLeHearingAidActiveDevice(device);
                if (setLeHearingAidActiveDevice(device)) {
                    setHearingAidActiveDevice(null, true);
                    setA2dpActiveDevice(null, true);
                    setHfpActiveDevice(null);
                }
            }
        }
    }

    private void handleA2dpDisconnected(BluetoothDevice device) {
        synchronized (mLock) {
@@ -701,11 +710,12 @@ class ActiveDeviceManager {
        return mHandlerThread.getLooper();
    }

    private void setA2dpActiveDevice(@NonNull BluetoothDevice device) {
        setA2dpActiveDevice(device, false);
    private boolean setA2dpActiveDevice(@NonNull BluetoothDevice device) {
        return setA2dpActiveDevice(device, false);
    }

    private void setA2dpActiveDevice(@Nullable BluetoothDevice device, boolean hasFallbackDevice) {
    private boolean setA2dpActiveDevice(@Nullable BluetoothDevice device,
            boolean hasFallbackDevice) {
        if (DBG) {
            Log.d(TAG, "setA2dpActiveDevice(" + device + ")"
                    + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : ""));
@@ -713,7 +723,7 @@ class ActiveDeviceManager {

        final A2dpService a2dpService = mFactory.getA2dpService();
        if (a2dpService == null) {
            return;
            return false;
        }

        boolean success = false;
@@ -724,40 +734,43 @@ class ActiveDeviceManager {
        }

        if (!success) {
            return;
            return false;
        }

        synchronized (mLock) {
            mA2dpActiveDevice = device;
        }
        return true;
    }

    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    private void setHfpActiveDevice(BluetoothDevice device) {
    private boolean setHfpActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (DBG) {
                Log.d(TAG, "setHfpActiveDevice(" + device + ")");
            }
            final HeadsetService headsetService = mFactory.getHeadsetService();
            if (headsetService == null) {
                return;
                return false;
            }
            BluetoothSinkAudioPolicy audioPolicy = headsetService.getHfpCallAudioPolicy(device);
            if (audioPolicy == null || audioPolicy.getActiveDevicePolicyAfterConnection()
                    != BluetoothSinkAudioPolicy.POLICY_NOT_ALLOWED) {
            if (audioPolicy != null && audioPolicy.getActiveDevicePolicyAfterConnection()
                    == BluetoothSinkAudioPolicy.POLICY_NOT_ALLOWED) {
                return false;
            }
            if (!headsetService.setActiveDevice(device)) {
                    return;
                return false;
            }
            mHfpActiveDevice = device;
        }
        }
        return true;
    }

    private void setHearingAidActiveDevice(@NonNull BluetoothDevice device) {
        setHearingAidActiveDevice(device, false);
    private boolean setHearingAidActiveDevice(@NonNull BluetoothDevice device) {
        return setHearingAidActiveDevice(device, false);
    }

    private void setHearingAidActiveDevice(@Nullable BluetoothDevice device,
    private boolean setHearingAidActiveDevice(@Nullable BluetoothDevice device,
            boolean hasFallbackDevice) {
        if (DBG) {
            Log.d(TAG, "setHearingAidActiveDevice(" + device + ")"
@@ -766,34 +779,37 @@ class ActiveDeviceManager {
        synchronized (mLock) {
            final HearingAidService hearingAidService = mFactory.getHearingAidService();
            if (hearingAidService == null) {
                return;
                return false;
            }

            if (device == null) {
                hearingAidService.removeActiveDevice(!hasFallbackDevice);
                if (!hearingAidService.removeActiveDevice(!hasFallbackDevice)) {
                    return false;
                }
                mHearingAidActiveDevices.clear();
                return;
                return true;
            }

            long hiSyncId = hearingAidService.getHiSyncId(device);
            if (getHearingAidActiveHiSyncIdLocked() == hiSyncId) {
                mHearingAidActiveDevices.add(device);
                return;
                return true;
            }

            if (!hearingAidService.setActiveDevice(device)) {
                return;
                return false;
            }
            mHearingAidActiveDevices.clear();
            mHearingAidActiveDevices.addAll(hearingAidService.getConnectedPeerDevices(hiSyncId));
        }
        return true;
    }

    private void setLeAudioActiveDevice(@NonNull BluetoothDevice device) {
        setLeAudioActiveDevice(device, false);
    private boolean setLeAudioActiveDevice(@NonNull BluetoothDevice device) {
        return setLeAudioActiveDevice(device, false);
    }

    private void setLeAudioActiveDevice(@Nullable BluetoothDevice device,
    private boolean setLeAudioActiveDevice(@Nullable BluetoothDevice device,
            boolean hasFallbackDevice) {
        if (DBG) {
            Log.d(TAG, "setLeAudioActiveDevice(" + device + ")"
@@ -802,7 +818,7 @@ class ActiveDeviceManager {
        synchronized (mLock) {
            final LeAudioService leAudioService = mFactory.getLeAudioService();
            if (leAudioService == null) {
                return;
                return false;
            }
            boolean success;
            if (device == null) {
@@ -812,7 +828,7 @@ class ActiveDeviceManager {
            }

            if (!success) {
                return;
                return false;
            }

            mLeAudioActiveDevice = device;
@@ -821,19 +837,24 @@ class ActiveDeviceManager {
                mPendingLeHearingAidActiveDevice.remove(device);
            }
        }
        return true;
    }

    private void setLeHearingAidActiveDevice(BluetoothDevice device) {
    private boolean setLeHearingAidActiveDevice(BluetoothDevice device) {
        synchronized (mLock) {
            if (!Objects.equals(mLeAudioActiveDevice, device)) {
                setLeAudioActiveDevice(device);
                if (!setLeAudioActiveDevice(device)) {
                    return false;
                }
            }
            if (Objects.equals(mLeAudioActiveDevice, device)) {
                // setLeAudioActiveDevice succeed
                mLeHearingAidActiveDevice = device;
                mPendingLeHearingAidActiveDevice.remove(device);
                return true;
            }
        }
        return false;
    }

    /**
+64 −0
Original line number Diff line number Diff line
@@ -393,6 +393,8 @@ public class ActiveDeviceManagerTest {
     */
    @Test
    public void hearingAidActive_setA2dpActiveExplicitly() {
        when(mHearingAidService.removeActiveDevice(anyBoolean())).thenReturn(true);

        hearingAidActiveDeviceChanged(mHearingAidDevice);
        a2dpConnected(mA2dpDevice, false);
        a2dpActiveDeviceChanged(mA2dpDevice);
@@ -410,6 +412,8 @@ public class ActiveDeviceManagerTest {
     */
    @Test
    public void hearingAidActive_setHeadsetActiveExplicitly() {
        when(mHearingAidService.removeActiveDevice(anyBoolean())).thenReturn(true);

        hearingAidActiveDeviceChanged(mHearingAidDevice);
        headsetConnected(mHeadsetDevice, false);
        headsetActiveDeviceChanged(mHeadsetDevice);
@@ -623,6 +627,10 @@ public class ActiveDeviceManagerTest {
    @Test
    public void activeDeviceDisconnected_fallbackToHearingAid() {
        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
        when(mA2dpService.setActiveDevice(any())).thenReturn(true);
        when(mLeAudioService.setActiveDevice(any())).thenReturn(true);
        when(mHearingAidService.setActiveDevice(any())).thenReturn(true);
        when(mHearingAidService.removeActiveDevice(anyBoolean())).thenReturn(true);

        hearingAidConnected(mHearingAidDevice);
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mHearingAidDevice);
@@ -678,6 +686,7 @@ public class ActiveDeviceManagerTest {
    @Test
    public void activeDeviceChange_withHearingAidLeHearingAidAndA2dpDevices() {
        when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
        when(mHearingAidService.removeActiveDevice(anyBoolean())).thenReturn(true);

        hearingAidConnected(mHearingAidDevice);
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mHearingAidDevice);
@@ -768,6 +777,61 @@ public class ActiveDeviceManagerTest {
        Assert.assertEquals(null, mActiveDeviceManager.getLeAudioActiveDevice());
    }

    /**
     * Verifies that other profiles do not have their active device cleared when we fail to make
     * a newly connected device active.
     */
    @Test
    public void setActiveDeviceFailsUponConnection() {
        Utils.setDualModeAudioStateForTesting(false);
        when(mHeadsetService.setActiveDevice(any())).thenReturn(false);
        when(mA2dpService.setActiveDevice(any())).thenReturn(false);
        when(mHearingAidService.setActiveDevice(any())).thenReturn(false);
        when(mLeAudioService.setActiveDevice(any())).thenReturn(false);

        leAudioConnected(mDualModeAudioDevice);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mDualModeAudioDevice);

        leAudioActiveDeviceChanged(mDualModeAudioDevice);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mA2dpService, times(1)).removeActiveDevice(anyBoolean());
        verify(mHeadsetService, times(1)).setActiveDevice(null);
        verify(mHearingAidService, times(1)).removeActiveDevice(anyBoolean());

        a2dpConnected(mA2dpDevice, false);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mA2dpService, timeout(TIMEOUT_MS)).setActiveDevice(mA2dpDevice);
        verify(mLeAudioService, never()).removeActiveDevice(anyBoolean());

        a2dpConnected(mA2dpHeadsetDevice, true);
        headsetConnected(mA2dpHeadsetDevice, true);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mA2dpService, timeout(TIMEOUT_MS)).setActiveDevice(mA2dpHeadsetDevice);
        verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mA2dpHeadsetDevice);
        verify(mLeAudioService, never()).removeActiveDevice(anyBoolean());

        headsetConnected(mHeadsetDevice, false);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice);
        verify(mLeAudioService, never()).removeActiveDevice(anyBoolean());

        hearingAidConnected(mHearingAidDevice);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mHearingAidDevice);
        verify(mLeAudioService, never()).removeActiveDevice(anyBoolean());
        verify(mA2dpService, times(1)).removeActiveDevice(anyBoolean());
        verify(mHeadsetService, times(1)).setActiveDevice(null);

        leAudioConnected(mLeHearingAidDevice);
        leHearingAidConnected(mLeHearingAidDevice);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mLeAudioService, times(2)).setActiveDevice(mLeHearingAidDevice);
        verify(mA2dpService, times(1)).removeActiveDevice(anyBoolean());
        verify(mHeadsetService, times(1)).setActiveDevice(null);
        verify(mHearingAidService, times(1)).removeActiveDevice(anyBoolean());
    }

    /**
     * A wired audio device is connected. Then all active devices are set to null.
     */