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

Commit 4748279d authored by Rahul Sabnis's avatar Rahul Sabnis Committed by Automerger Merge Worker
Browse files

Merge changes Ic7aaa7ed,I6edac61f am: 0a912f16

parents 6a08d728 0a912f16
Loading
Loading
Loading
Loading
+106 −52
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHeadset;
@@ -262,9 +263,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 +274,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 +307,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 +321,15 @@ 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()) {
                    if (isWatch(device)) {
                        Log.i(TAG, "Do not set hfp active for watch device " + device);
                        return;
                    }
                    // 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 +347,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 +376,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 +406,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 +715,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 +728,7 @@ class ActiveDeviceManager {

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

        boolean success = false;
@@ -724,40 +739,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 +784,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 +823,7 @@ class ActiveDeviceManager {
        synchronized (mLock) {
            final LeAudioService leAudioService = mFactory.getLeAudioService();
            if (leAudioService == null) {
                return;
                return false;
            }
            boolean success;
            if (device == null) {
@@ -812,7 +833,7 @@ class ActiveDeviceManager {
            }

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

            mLeAudioActiveDevice = device;
@@ -821,19 +842,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;
    }

    /**
@@ -1030,6 +1056,34 @@ class ActiveDeviceManager {
        return BluetoothHearingAid.HI_SYNC_ID_INVALID;
    }

    /**
     * Checks CoD and metadata to determine if the device is a watch
     * @param device the remote device
     * @return {@code true} if it's a watch, {@code false} otherwise
     */
    private boolean isWatch(BluetoothDevice device) {
        // Check CoD
        BluetoothClass deviceClass = device.getBluetoothClass();
        if (deviceClass != null && deviceClass.getDeviceClass()
                == BluetoothClass.Device.WEARABLE_WRIST_WATCH) {
            return true;
        }

        // Check metadata
        DatabaseManager dbManager = mAdapterService.getDatabase();
        byte[] deviceType = dbManager.getCustomMeta(device,
            BluetoothDevice.METADATA_DEVICE_TYPE);
        if (deviceType == null) {
            return false;
        }
        String deviceTypeStr = new String(deviceType);
        if (deviceTypeStr.equals(BluetoothDevice.DEVICE_TYPE_WATCH)) {
            return true;
        }

        return false;
    }

    /**
     * Called when a wired audio device is connected.
     * It might be called multiple times each time a wired audio device is connected.
+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.
     */