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

Commit 232fd198 authored by William Escande's avatar William Escande Committed by Android (Google) Code Review
Browse files

Merge "[HFP] Broadcast inband ringing status to HF" into tm-qpr-dev

parents 0c7129a0 037ac0a7
Loading
Loading
Loading
Loading
+45 −21
Original line number Diff line number Diff line
@@ -2017,31 +2017,55 @@ public class HeadsetService extends ProfileService {
    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    public void onConnectionStateChangedFromStateMachine(BluetoothDevice device, int fromState,
            int toState) {
        synchronized (mStateMachines) {
            List<BluetoothDevice> audioConnectableDevices = getConnectedDevices();
        if (fromState != BluetoothProfile.STATE_CONNECTED
                && toState == BluetoothProfile.STATE_CONNECTED) {
                if (audioConnectableDevices.size() > 1) {
                    mInbandRingingRuntimeDisable = true;
                    doForEachConnectedStateMachine(
                            stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.SEND_BSIR,
                                    0));
                }
            updateInbandRinging(device, true);
            MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.HEADSET);
        }
        if (fromState != BluetoothProfile.STATE_DISCONNECTED
                && toState == BluetoothProfile.STATE_DISCONNECTED) {
                if (audioConnectableDevices.size() <= 1) {
                    mInbandRingingRuntimeDisable = false;
                    doForEachConnectedStateMachine(
                            stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.SEND_BSIR,
                                    1));
                }
            updateInbandRinging(device, false);
            if (device.equals(mActiveDevice)) {
                setActiveDevice(null);
            }
        }
    }

    /**
     * Called from {@link HeadsetClientStateMachine} to update inband ringing status.
     */
    public void updateInbandRinging(BluetoothDevice device, boolean connected) {
        synchronized (mStateMachines) {
            List<BluetoothDevice> audioConnectableDevices = getConnectedDevices();
            final int enabled;
            final boolean inbandRingingRuntimeDisable = mInbandRingingRuntimeDisable;

            if (audioConnectableDevices.size() > 1 || isHeadsetClientConnected()) {
                mInbandRingingRuntimeDisable = true;
                enabled = 0;
            } else {
                mInbandRingingRuntimeDisable = false;
                enabled = 1;
            }

            final boolean updateAll = inbandRingingRuntimeDisable != mInbandRingingRuntimeDisable;

            Log.i(TAG, "updateInbandRinging():"
                    + " Device=" + device
                    + " enabled=" + enabled
                    + " connected=" + connected
                    + " Update all=" + updateAll);

            StateMachineTask sendBsirTask = stateMachine -> stateMachine
                            .sendMessage(HeadsetStateMachine.SEND_BSIR, enabled);

            if (updateAll) {
                doForEachConnectedStateMachine(sendBsirTask);
            } else if (connected) {
                // Same Inband ringing status, send +BSIR only to the new connected device
                doForStateMachine(device, sendBsirTask);
            }
        }
    }

    /**
+16 −6
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IState;
import com.android.internal.util.State;
@@ -148,6 +149,7 @@ public class HeadsetClientStateMachine extends StateMachine {
    private long mClccTimer = 0;

    private final HeadsetClientService mService;
    private final HeadsetService mHeadsetService;

    // Set of calls that represent the accurate state of calls that exists on AG and the calls that
    // are currently in process of being notified to the AG from HF.
@@ -860,12 +862,13 @@ public class HeadsetClientStateMachine extends StateMachine {
        return (bitfield & mask) == mask;
    }

    HeadsetClientStateMachine(HeadsetClientService context, Looper looper,
                              NativeInterface nativeInterface) {
    HeadsetClientStateMachine(HeadsetClientService context, HeadsetService headsetService,
                              Looper looper, NativeInterface nativeInterface) {
        super(TAG, looper);
        mService = context;
        mNativeInterface = nativeInterface;
        mAudioManager = mService.getAudioManager();
        mHeadsetService = headsetService;

        mVendorProcessor = new VendorCommandResponseProcessor(mService, mNativeInterface);

@@ -909,11 +912,12 @@ public class HeadsetClientStateMachine extends StateMachine {
        setInitialState(mDisconnected);
    }

    static HeadsetClientStateMachine make(HeadsetClientService context, Looper looper,
                                          NativeInterface nativeInterface) {
    static HeadsetClientStateMachine make(HeadsetClientService context,
                                          HeadsetService headsetService,
                                          Looper looper, NativeInterface nativeInterface) {
        logD("make");
        HeadsetClientStateMachine hfcsm = new HeadsetClientStateMachine(context, looper,
                                                                        nativeInterface);
        HeadsetClientStateMachine hfcsm = new HeadsetClientStateMachine(context, headsetService,
                                                                        looper, nativeInterface);
        hfcsm.start();
        return hfcsm;
    }
@@ -1022,6 +1026,9 @@ public class HeadsetClientStateMachine extends StateMachine {
                Log.e(TAG, "Disconnected: Illegal state transition from " + mPrevState.getName()
                        + " to Disconnected, mCurrentDevice=" + mCurrentDevice);
            }
            if (mHeadsetService != null && mCurrentDevice != null) {
                mHeadsetService.updateInbandRinging(mCurrentDevice, false);
            }
            mCurrentDevice = null;
        }

@@ -1309,6 +1316,9 @@ public class HeadsetClientStateMachine extends StateMachine {
            if (mPrevState == mConnecting) {
                broadcastConnectionState(mCurrentDevice, BluetoothProfile.STATE_CONNECTED,
                        BluetoothProfile.STATE_CONNECTING);
                if (mHeadsetService != null) {
                    mHeadsetService.updateInbandRinging(mCurrentDevice, true);
                }
                MetricsLogger.logProfileConnectionEvent(
                        BluetoothMetricsProto.ProfileId.HEADSET_CLIENT);
            } else if (mPrevState != mAudioOn) {
+4 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.bluetooth.hfpclient;

import android.os.HandlerThread;

import com.android.bluetooth.hfp.HeadsetService;

// Factory so that StateMachine objected can be mocked
public class HeadsetClientStateMachineFactory {
    /**
@@ -26,6 +28,7 @@ public class HeadsetClientStateMachineFactory {
     */
    public HeadsetClientStateMachine make(HeadsetClientService context, HandlerThread t,
            NativeInterface nativeInterface) {
        return HeadsetClientStateMachine.make(context, t.getLooper(), nativeInterface);
        return HeadsetClientStateMachine.make(context, HeadsetService.getHeadsetService(),
                t.getLooper(), nativeInterface);
    }
}
+23 −8
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.InOrder;

import java.lang.reflect.Method;
import java.util.Collections;
@@ -666,6 +667,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        startVoiceRecognitionFromHf(device);
    }
@@ -689,6 +691,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        startVoiceRecognitionFromHf(device);
        // Stop voice recognition
@@ -723,6 +726,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        HeadsetStackEvent startVrEvent =
                new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_VR_STATE_CHANGED,
@@ -755,6 +759,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        HeadsetStackEvent startVrEvent =
                new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_VR_STATE_CHANGED,
@@ -787,6 +792,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        startVoiceRecognitionFromAg();
    }
@@ -860,6 +866,7 @@ public class HeadsetServiceAndStateMachineTest {
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));
        verify(mNativeInterface).setActiveDevice(device);
        Assert.assertEquals(device, mHeadsetService.getActiveDevice());
        verify(mNativeInterface).sendBsir(eq(device), eq(true));
        // Start voice recognition
        startVoiceRecognitionFromAg();
        // Stop voice recognition
@@ -908,8 +915,10 @@ public class HeadsetServiceAndStateMachineTest {
        connectTestDevice(deviceA);
        BluetoothDevice deviceB = TestUtils.getTestDevice(mAdapter, 1);
        connectTestDevice(deviceB);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceA, false);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceB, false);
        InOrder inOrder = inOrder(mNativeInterface);
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(true));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceB), eq(false));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(false));
        // Set active device to device B
        Assert.assertTrue(mHeadsetService.setActiveDevice(deviceB));
        verify(mNativeInterface).setActiveDevice(deviceB);
@@ -960,8 +969,10 @@ public class HeadsetServiceAndStateMachineTest {
        connectTestDevice(deviceA);
        BluetoothDevice deviceB = TestUtils.getTestDevice(mAdapter, 1);
        connectTestDevice(deviceB);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceA, false);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceB, false);
        InOrder inOrder = inOrder(mNativeInterface);
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(true));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceB), eq(false));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(false));
        // Set active device to device B
        Assert.assertTrue(mHeadsetService.setActiveDevice(deviceB));
        verify(mNativeInterface).setActiveDevice(deviceB);
@@ -1012,8 +1023,10 @@ public class HeadsetServiceAndStateMachineTest {
        connectTestDevice(deviceA);
        BluetoothDevice deviceB = TestUtils.getTestDevice(mAdapter, 1);
        connectTestDevice(deviceB);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceA, false);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceB, false);
        InOrder inOrder = inOrder(mNativeInterface);
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(true));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceB), eq(false));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(false));
        // Set active device to device B
        Assert.assertTrue(mHeadsetService.setActiveDevice(deviceB));
        verify(mNativeInterface).setActiveDevice(deviceB);
@@ -1051,8 +1064,10 @@ public class HeadsetServiceAndStateMachineTest {
        connectTestDevice(deviceA);
        BluetoothDevice deviceB = TestUtils.getTestDevice(mAdapter, 1);
        connectTestDevice(deviceB);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceA, false);
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(deviceB, false);
        InOrder inOrder = inOrder(mNativeInterface);
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(true));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceB), eq(false));
        inOrder.verify(mNativeInterface).sendBsir(eq(deviceA), eq(false));
        // Set active device to device B
        Assert.assertTrue(mHeadsetService.setActiveDevice(deviceB));
        verify(mNativeInterface).setActiveDevice(deviceB);
+20 −5
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hfp.HeadsetStackEvent;

import org.hamcrest.core.AllOf;
@@ -94,6 +95,8 @@ public class HeadsetClientStateMachineTest {
    @Mock
    private Resources mMockHfpResources;
    @Mock
    private HeadsetService mHeadsetService;
    @Mock
    private HeadsetClientService mHeadsetClientService;
    @Mock
    private AudioManager mAudioManager;
@@ -138,7 +141,7 @@ public class HeadsetClientStateMachineTest {
        mHandlerThread.start();
        // Manage looper execution in main test thread explicitly to guarantee timing consistency
        mHeadsetClientStateMachine = new TestHeadsetClientStateMachine(mHeadsetClientService,
                mHandlerThread.getLooper(), mNativeInterface);
                mHeadsetService, mHandlerThread.getLooper(), mNativeInterface);
        mHeadsetClientStateMachine.start();
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
    }
@@ -149,10 +152,12 @@ public class HeadsetClientStateMachineTest {
            return;
        }
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        TestUtils.clearAdapterService(mAdapterService);
        mHeadsetClientStateMachine.allowConnect = null;
        mHeadsetClientStateMachine.doQuit();
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        mHandlerThread.quit();
        TestUtils.clearAdapterService(mAdapterService);
        verifyNoMoreInteractions(mHeadsetService);
    }

    /**
@@ -245,6 +250,7 @@ public class HeadsetClientStateMachineTest {
        // Check we are in connecting state now.
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true));
    }

    /**
@@ -287,6 +293,7 @@ public class HeadsetClientStateMachineTest {
        // Check we are in connecting state now.
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false));
    }

    /**
@@ -338,6 +345,8 @@ public class HeadsetClientStateMachineTest {
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));

        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true));

        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_IN_BAND_RINGTONE);
        event.valueInt = 0;
        event.device = mTestDevice;
@@ -455,6 +464,7 @@ public class HeadsetClientStateMachineTest {
                intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true));

        startBroadcastIndex++;
        return startBroadcastIndex;
@@ -1164,6 +1174,7 @@ public class HeadsetClientStateMachineTest {
        sendMessageAndVerifyTransition(
                mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event),
                HeadsetClientStateMachine.Disconnected.class);
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false));
    }

    @Test
@@ -1228,6 +1239,7 @@ public class HeadsetClientStateMachineTest {
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true));
    }

    @Test
@@ -1236,6 +1248,7 @@ public class HeadsetClientStateMachineTest {
        Message msg = mHeadsetClientStateMachine
                .obtainMessage(HeadsetClientStateMachine.CONNECTING_TIMEOUT);
        sendMessageAndVerifyTransition(msg, HeadsetClientStateMachine.Disconnected.class);
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false));
    }

    @Test
@@ -1324,6 +1337,7 @@ public class HeadsetClientStateMachineTest {
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false));
    }

    @Test
@@ -1369,6 +1383,7 @@ public class HeadsetClientStateMachineTest {
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
        verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true));
    }

    private void initToAudioOnState() {
@@ -1399,9 +1414,9 @@ public class HeadsetClientStateMachineTest {

        Boolean allowConnect = null;

        TestHeadsetClientStateMachine(HeadsetClientService context, Looper looper,
                NativeInterface nativeInterface) {
            super(context, looper, nativeInterface);
        TestHeadsetClientStateMachine(HeadsetClientService context, HeadsetService headsetService,
                Looper looper, NativeInterface nativeInterface) {
            super(context, headsetService, looper, nativeInterface);
        }

        public boolean doesSuperHaveDeferredMessages(int what) {