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

Commit 9903e6c8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "PhonePolicy: Stop auto connecting to devices that failed to connect"

parents 766f13c6 edbd2da0
Loading
Loading
Loading
Loading
+45 −30
Original line number Diff line number Diff line
@@ -258,8 +258,8 @@ class PhonePolicy {
            int prevState) {
        debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", "
                + prevState + " -> " + nextState);
        if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)) && (
                nextState == BluetoothProfile.STATE_CONNECTED)) {
        if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))) {
            if (nextState == BluetoothProfile.STATE_CONNECTED) {
                switch (profileId) {
                    case BluetoothProfile.A2DP:
                        mA2dpRetrySet.remove(device);
@@ -269,7 +269,13 @@ class PhonePolicy {
                        break;
                }
                connectOtherProfile(device);
            setProfileAutoConnectionPriority(device, profileId);
                setProfileAutoConnectionPriority(device, profileId, true);
            }
            if (prevState == BluetoothProfile.STATE_CONNECTING
                    && nextState == BluetoothProfile.STATE_DISCONNECTED) {
                setProfileAutoConnectionPriority(device, profileId, false);
            }

        }
    }

@@ -430,51 +436,60 @@ class PhonePolicy {
        }
    }

    private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) {
    private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId,
            boolean autoConnect) {
        debugLog("setProfileAutoConnectionPriority: device=" + device + ", profile=" + profileId
                + ", autoConnect=" + autoConnect);
        switch (profileId) {
            case BluetoothProfile.HEADSET:
            case BluetoothProfile.HEADSET: {
                HeadsetService hsService = mFactory.getHeadsetService();
                if ((hsService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT
                        != hsService.getPriority(device))) {
                    List<BluetoothDevice> deviceList = hsService.getConnectedDevices();
                    adjustOtherHeadsetPriorities(hsService, deviceList);
                if (hsService == null) {
                    warnLog("setProfileAutoConnectionPriority: HEADSET service is null");
                    break;
                }
                removeAutoConnectFromDisconnectedHeadsets(hsService);
                if (autoConnect) {
                    hsService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT);
                }
                break;

            case BluetoothProfile.A2DP:
            }
            case BluetoothProfile.A2DP: {
                A2dpService a2dpService = mFactory.getA2dpService();
                if ((a2dpService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT
                        != a2dpService.getPriority(device))) {
                    List<BluetoothDevice> deviceList = a2dpService.getConnectedDevices();
                    adjustOtherSinkPriorities(a2dpService, deviceList);
                if (a2dpService == null) {
                    warnLog("setProfileAutoConnectionPriority: A2DP service is null");
                    break;
                }
                removeAutoConnectFromDisconnectedA2dpSinks(a2dpService);
                if (autoConnect) {
                    a2dpService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT);
                }
                break;

            }
            default:
                Log.w(TAG, "Tried to set AutoConnect priority on invalid profile " + profileId);
                break;
        }
    }

    private void adjustOtherHeadsetPriorities(HeadsetService hsService,
            List<BluetoothDevice> connectedDeviceList) {
    private void removeAutoConnectFromDisconnectedHeadsets(HeadsetService hsService) {
        List<BluetoothDevice> connectedDeviceList = hsService.getConnectedDevices();
        for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT
                    && !connectedDeviceList.contains(device)) {
                debugLog("adjustOtherHeadsetPriorities, device " + device + " PRIORITY_ON");
                debugLog("removeAutoConnectFromDisconnectedHeadsets, device " + device
                        + " PRIORITY_ON");
                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
            }
        }
    }

    private void adjustOtherSinkPriorities(A2dpService a2dpService,
            List<BluetoothDevice> connectedDeviceList) {
    private void removeAutoConnectFromDisconnectedA2dpSinks(A2dpService a2dpService) {
        List<BluetoothDevice> connectedDeviceList = a2dpService.getConnectedDevices();
        for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
            if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT
                    && !connectedDeviceList.contains(device)) {
                debugLog("adjustOtherSinkPriorities, device " + device + " PRIORITY_ON");
                debugLog("removeAutoConnectFromDisconnectedA2dpSinks, device " + device
                        + " PRIORITY_ON");
                a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
            }
        }
+104 −1
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ public class PhonePolicyTest {
        doReturn(true).when(mAdapterService).isMock();
        // Must be called to initialize services
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mTestDevice = TestUtils.getTestDevice(mAdapter, 1);
        mTestDevice = TestUtils.getTestDevice(mAdapter, 99);
        PhonePolicy.sConnectOtherProfilesTimeoutMillis = CONNECT_OTHER_PROFILES_TIMEOUT_MILLIS;
        mPhonePolicy = new PhonePolicy(mAdapterService, mServiceFactory);
    }
@@ -156,6 +156,109 @@ public class PhonePolicyTest {
        verify(mA2dpService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connect(eq(mTestDevice));
    }

    /**
     * Test that when an auto connect device is disconnected, its priority is set to ON if its
     * original priority is auto connect
     */
    @Test
    public void testDisconnectNoAutoConnect() {
        // Return desired values from the mocked object(s)
        when(mAdapterService.getState()).thenReturn(BluetoothAdapter.STATE_ON);
        when(mAdapterService.isQuietModeEnabled()).thenReturn(false);

        // Return a list of bonded devices (just one)
        BluetoothDevice[] bondedDevices = new BluetoothDevice[4];
        bondedDevices[0] = TestUtils.getTestDevice(mAdapter, 0);
        bondedDevices[1] = TestUtils.getTestDevice(mAdapter, 1);
        bondedDevices[2] = TestUtils.getTestDevice(mAdapter, 2);
        bondedDevices[3] = TestUtils.getTestDevice(mAdapter, 3);
        when(mAdapterService.getBondedDevices()).thenReturn(bondedDevices);

        ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
        doAnswer(invocation -> connectedDevices).when(mHeadsetService).getConnectedDevices();

        // Make all devices auto connect
        when(mHeadsetService.getPriority(bondedDevices[0])).thenReturn(
                BluetoothProfile.PRIORITY_AUTO_CONNECT);
        when(mHeadsetService.getPriority(bondedDevices[1])).thenReturn(
                BluetoothProfile.PRIORITY_AUTO_CONNECT);
        when(mHeadsetService.getPriority(bondedDevices[2])).thenReturn(
                BluetoothProfile.PRIORITY_AUTO_CONNECT);
        when(mHeadsetService.getPriority(bondedDevices[3])).thenReturn(
                BluetoothProfile.PRIORITY_OFF);

        // Make one of the device connected
        connectedDevices.add(bondedDevices[0]);
        when(mHeadsetService.getConnectionState(bondedDevices[0])).thenReturn(
                BluetoothProfile.STATE_CONNECTED);
        Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bondedDevices[0]);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mPhonePolicy.getBroadcastReceiver().onReceive(null /* context */, intent);

        // All other disconnected device's priority is set to ON, except disabled ones
        verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setPriority(bondedDevices[0],
                BluetoothProfile.PRIORITY_AUTO_CONNECT);
        verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setPriority(bondedDevices[1],
                BluetoothProfile.PRIORITY_ON);
        verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setPriority(bondedDevices[2],
                BluetoothProfile.PRIORITY_ON);
        verify(mHeadsetService, never()).setPriority(eq(bondedDevices[3]), anyInt());
        when(mHeadsetService.getPriority(bondedDevices[1])).thenReturn(
                BluetoothProfile.PRIORITY_ON);
        when(mHeadsetService.getPriority(bondedDevices[2])).thenReturn(
                BluetoothProfile.PRIORITY_ON);

        // Make another device connected
        connectedDevices.add(bondedDevices[1]);
        when(mHeadsetService.getConnectionState(bondedDevices[1])).thenReturn(
                BluetoothProfile.STATE_CONNECTED);
        intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bondedDevices[1]);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mPhonePolicy.getBroadcastReceiver().onReceive(null /* context */, intent);

        // This device should be set to auto connect
        verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setPriority(bondedDevices[1],
                BluetoothProfile.PRIORITY_AUTO_CONNECT);
        verify(mHeadsetService, never()).setPriority(eq(bondedDevices[3]), anyInt());
        when(mHeadsetService.getPriority(bondedDevices[1])).thenReturn(
                BluetoothProfile.PRIORITY_AUTO_CONNECT);

        // Make one of the device disconnect
        connectedDevices.remove(bondedDevices[0]);
        when(mHeadsetService.getConnectionState(bondedDevices[0])).thenReturn(
                BluetoothProfile.STATE_DISCONNECTED);
        intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bondedDevices[0]);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mPhonePolicy.getBroadcastReceiver().onReceive(null /* context */, intent);

        // This should not have any effect
        verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).never())
                .setPriority(bondedDevices[0], BluetoothProfile.PRIORITY_ON);

        intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bondedDevices[0]);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mPhonePolicy.getBroadcastReceiver().onReceive(null /* context */, intent);

        // This device should be set to ON
        verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setPriority(bondedDevices[0],
                BluetoothProfile.PRIORITY_ON);

        // Verify that we are not setting priorities to random devices and values
        verify(mHeadsetService, times(5)).setPriority(any(BluetoothDevice.class), anyInt());
    }

    /**
     * Test that we will try to re-connect to a profile on a device if an attempt failed previously.
     * This is to add robustness to the connection mechanism