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

Commit 8c5f65ca authored by William Escande's avatar William Escande
Browse files

Autoconnect fallback on second audio profil

Some BT device try to auto-connect only with HFP. Some Other only with
A2DP.
On a incoming connection to HFP/A2DP when the user as disallowed the
profil, connect to the A2DP/HFP if this other profil is allowed.

* Pair & connect a device
* Enable both phone call and media audio
* Shutdown the device
* Disable one of phone call / media audio
* Turn on the device to trigger it's auto-connect
* Test again with the other profil

Expected result: device is connected in both situation
previous result: device is only connected in one of the two situation

Fix: 206539530
Test: Above step tested with mini soundlink 2
Tag: #feature
Change-Id: I8a7da9f31ae4bba64256cd835326f51f7a62a3a5
parent 0e8f01bf
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.SynchronousResultReceiver;
@@ -404,6 +405,14 @@ public class A2dpService extends ProfileService {
            return false;
        } else if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_UNKNOWN
                && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
            if (!isOutgoingRequest) {
                HeadsetService headsetService = HeadsetService.getHeadsetService();
                if (headsetService != null && headsetService.okToAcceptConnection(device, true)) {
                    Log.d(TAG, "okToConnect: Fallback connection to allowed HFP profile");
                    headsetService.connect(device);
                    return true;
                }
            }
            // Otherwise, reject the connection if connectionPolicy is not valid.
            Log.w(TAG, "okToConnect: return false, connectionPolicy=" + connectionPolicy);
            return false;
+11 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.util.Log;
import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
@@ -2032,7 +2033,7 @@ public class HeadsetService extends ProfileService {
     * @param device remote device that initiates the connection
     * @return true if the connection is acceptable
     */
    public boolean okToAcceptConnection(BluetoothDevice device) {
    public boolean okToAcceptConnection(BluetoothDevice device, boolean isOutgoingRequest) {
        // Check if this is an incoming connection in Quiet mode.
        if (mAdapterService.isQuietModeEnabled()) {
            Log.w(TAG, "okToAcceptConnection: return false as quiet mode enabled");
@@ -2049,6 +2050,15 @@ public class HeadsetService extends ProfileService {
        } else if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_UNKNOWN
                && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
            // Otherwise, reject the connection if connection policy is not valid.
            if (!isOutgoingRequest) {
                A2dpService a2dpService = A2dpService.getA2dpService();
                if (a2dpService != null && a2dpService.okToConnect(device, true)) {
                    Log.d(TAG, "okToAcceptConnection: return temporary true,"
                            + " Fallback connection to allowed A2DP profile");
                    a2dpService.connect(device);
                    return true;
                }
            }
            Log.w(TAG, "okToAcceptConnection: return false, connectionPolicy=" + connectionPolicy);
            return false;
        }
+1 −1
Original line number Diff line number Diff line
@@ -525,7 +525,7 @@ public class HeadsetStateMachine extends StateMachine {
                // Both events result in Connecting state as SLC establishment is still required
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTED:
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTING:
                    if (mHeadsetService.okToAcceptConnection(mDevice)) {
                    if (mHeadsetService.okToAcceptConnection(mDevice, false)) {
                        stateLogI("accept incoming connection");
                        transitionTo(mConnecting);
                    } else {
+1 −1
Original line number Diff line number Diff line
@@ -951,7 +951,7 @@ public class HeadsetServiceTest {
        doReturn(bondState).when(mAdapterService).getBondState(device);
        when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET))
                .thenReturn(priority);
        Assert.assertEquals(expected, mHeadsetService.okToAcceptConnection(device));
        Assert.assertEquals(expected, mHeadsetService.okToAcceptConnection(device, false));
    }

}
+2 −1
Original line number Diff line number Diff line
@@ -123,7 +123,8 @@ public class HeadsetStateMachineTest {
        when(mHeadsetService.getConnectionPolicy(any(BluetoothDevice.class))).thenReturn(
                BluetoothProfile.CONNECTION_POLICY_ALLOWED);
        when(mHeadsetService.getForceScoAudio()).thenReturn(true);
        when(mHeadsetService.okToAcceptConnection(any(BluetoothDevice.class))).thenReturn(true);
        when(mHeadsetService.okToAcceptConnection(any(BluetoothDevice.class), anyBoolean()))
                .thenReturn(true);
        when(mHeadsetService.isScoAcceptable(any(BluetoothDevice.class))).thenReturn(
                BluetoothStatusCodes.SUCCESS);
        // Setup thread and looper