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

Commit f6d79936 authored by Kihong Seong's avatar Kihong Seong Committed by Gerrit Code Review
Browse files

Merge "Add additional tests to HeadsetClientStateMachineTest"

parents 9a45b114 3203209b
Loading
Loading
Loading
Loading
+38 −19
Original line number Diff line number Diff line
@@ -110,10 +110,14 @@ public class HeadsetClientStateMachine extends StateMachine {
    public static final int SEND_BIEV = 22;

    // internal actions
    private static final int QUERY_CURRENT_CALLS = 50;
    private static final int QUERY_OPERATOR_NAME = 51;
    private static final int SUBSCRIBER_INFO = 52;
    private static final int CONNECTING_TIMEOUT = 53;
    @VisibleForTesting
    static final int QUERY_CURRENT_CALLS = 50;
    @VisibleForTesting
    static final int QUERY_OPERATOR_NAME = 51;
    @VisibleForTesting
    static final int SUBSCRIBER_INFO = 52;
    @VisibleForTesting
    static final int CONNECTING_TIMEOUT = 53;

    // special action to handle terminating specific call from multiparty call
    static final int TERMINATE_SPECIFIC_CALL = 53;
@@ -144,7 +148,8 @@ public class HeadsetClientStateMachine extends StateMachine {

    // 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.
    private final Hashtable<Integer, HfpClientCall> mCalls = new Hashtable<>();
    @VisibleForTesting
    final Hashtable<Integer, HfpClientCall> mCalls = new Hashtable<>();
    // Set of calls received from AG via the AT+CLCC command. We use this map to update the mCalls
    // which is eventually used to inform the telephony stack of any changes to call on HF.
    private final Hashtable<Integer, HfpClientCall> mCallsUpdate = new Hashtable<>();
@@ -156,19 +161,22 @@ public class HeadsetClientStateMachine extends StateMachine {
    private boolean mInBandRing;

    private String mOperatorName;
    private String mSubscriberInfo;
    @VisibleForTesting
    String mSubscriberInfo;

    private static int sMaxAmVcVol;
    private static int sMinAmVcVol;

    // queue of send actions (pair action, action_data)
    private Queue<Pair<Integer, Object>> mQueuedActions;
    @VisibleForTesting
    Queue<Pair<Integer, Object>> mQueuedActions;

    // last executed command, before action is complete e.g. waiting for some
    // indicator
    private Pair<Integer, Object> mPendingAction;

    private int mAudioState;
    @VisibleForTesting
    int mAudioState;
    // Indicates whether audio can be routed to the device
    private boolean mAudioRouteAllowed;
    private boolean mAudioWbs;
@@ -176,11 +184,14 @@ public class HeadsetClientStateMachine extends StateMachine {
    private final BluetoothAdapter mAdapter;

    // currently connected device
    private BluetoothDevice mCurrentDevice = null;
    @VisibleForTesting
    BluetoothDevice mCurrentDevice = null;

    // general peer features and call handling features
    private int mPeerFeatures;
    private int mChldFeatures;
    @VisibleForTesting
    int mPeerFeatures;
    @VisibleForTesting
    int mChldFeatures;

    // This is returned when requesting focus from AudioManager
    private AudioFocusRequest mAudioFocusRequest;
@@ -257,7 +268,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        return builder.toString();
    }

    private static String getMessageName(int what) {
    @VisibleForTesting
    static String getMessageName(int what) {
        switch (what) {
            case StackEvent.STACK_EVENT:
                return "STACK_EVENT";
@@ -328,7 +340,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        mQueuedActions.add(new Pair<Integer, Object>(action, data));
    }

    private HfpClientCall getCall(int... states) {
    @VisibleForTesting
    HfpClientCall getCall(int... states) {
        logD("getFromCallsWithStates states:" + Arrays.toString(states));
        for (HfpClientCall c : mCalls.values()) {
            for (int s : states) {
@@ -340,7 +353,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        return null;
    }

    private int callsInState(int state) {
    @VisibleForTesting
    int callsInState(int state) {
        int i = 0;
        for (HfpClientCall c : mCalls.values()) {
            if (c.getState() == state) {
@@ -708,7 +722,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        }
    }

    private void enterPrivateMode(int idx) {
    @VisibleForTesting
    void enterPrivateMode(int idx) {
        logD("enterPrivateMode: " + idx);

        HfpClientCall c = mCalls.get(idx);
@@ -726,7 +741,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        }
    }

    private void explicitCallTransfer() {
    @VisibleForTesting
    void explicitCallTransfer() {
        logD("explicitCallTransfer");

        // can't transfer call if there is not enough call parties
@@ -1879,7 +1895,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        return BluetoothProfile.STATE_DISCONNECTED;
    }

    private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
    @VisibleForTesting
    void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
        BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_SCO_CONNECTION_STATE_CHANGED,
                AdapterService.getAdapterService().obfuscateAddress(device),
                getConnectionStateFromAudioState(newState), mAudioWbs
@@ -2028,7 +2045,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        return devices;
    }

    private byte[] getByteAddress(BluetoothDevice device) {
    @VisibleForTesting
    byte[] getByteAddress(BluetoothDevice device) {
        return Utils.getBytesFromAddress(device.getAddress());
    }

@@ -2047,7 +2065,8 @@ public class HeadsetClientStateMachine extends StateMachine {
        return b;
    }

    private static int getConnectionStateFromAudioState(int audioState) {
    @VisibleForTesting
    static int getConnectionStateFromAudioState(int audioState) {
        switch (audioState) {
            case BluetoothHeadsetClient.STATE_AUDIO_CONNECTED:
                return BluetoothAdapter.STATE_CONNECTED;
+285 −0
Original line number Diff line number Diff line
package com.android.bluetooth.hfpclient;

import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.AT_OK;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.ENTER_PRIVATE_MODE;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.VOICE_RECOGNITION_START;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.VOICE_RECOGNITION_STOP;

@@ -19,6 +21,7 @@ import android.media.AudioManager;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.intent.matcher.IntentMatchers;
@@ -46,6 +49,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.hamcrest.MockitoHamcrest;

import java.util.List;
import java.util.Set;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class HeadsetClientStateMachineTest {
@@ -706,4 +712,283 @@ public class HeadsetClientStateMachineTest {
        verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(1))
                .updateBatteryLevel();
    }

    @Test
    public void testBroadcastAudioState() {
        mHeadsetClientStateMachine.broadcastAudioState(mTestDevice,
                BluetoothHeadsetClient.STATE_AUDIO_CONNECTED,
                BluetoothHeadsetClient.STATE_AUDIO_CONNECTING);

        verify(mHeadsetClientService).sendBroadcast(any(), any(), any());
    }

    @Test
    public void testCallsInState() {
        HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_WAITING,
                "1", false, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, call);

        Assert.assertEquals(
                mHeadsetClientStateMachine.callsInState(HfpClientCall.CALL_STATE_WAITING), 1);
    }

    @Test
    public void testEnterPrivateMode() {
        HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_ACTIVE,
                "1", true, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, call);
        doReturn(true).when(mNativeInterface).handleCallAction(null,
                HeadsetClientHalConstants.CALL_ACTION_CHLD_2X, 0);

        mHeadsetClientStateMachine.enterPrivateMode(0);

        Pair expectedPair = new Pair<Integer, Object>(ENTER_PRIVATE_MODE, call);
        Assert.assertEquals(mHeadsetClientStateMachine.mQueuedActions.peek(), expectedPair);
    }

    @Test
    public void testExplicitCallTransfer() {
        HfpClientCall callOne = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_ACTIVE,
                "1", true, false, false);
        HfpClientCall callTwo = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_ACTIVE,
                "1", true, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, callOne);
        mHeadsetClientStateMachine.mCalls.put(1, callTwo);
        doReturn(true).when(mNativeInterface).handleCallAction(null,
                HeadsetClientHalConstants.CALL_ACTION_CHLD_4, -1);

        mHeadsetClientStateMachine.explicitCallTransfer();

        Pair expectedPair = new Pair<Integer, Object>(EXPLICIT_CALL_TRANSFER, 0);
        Assert.assertEquals(mHeadsetClientStateMachine.mQueuedActions.peek(), expectedPair);
    }

    @Test
    public void testSetAudioRouteAllowed() {
        mHeadsetClientStateMachine.setAudioRouteAllowed(true);

        Assert.assertTrue(mHeadsetClientStateMachine.getAudioRouteAllowed());
    }

    @Test
    public void testGetAudioState_withCurrentDeviceNull() {
        Assert.assertNull(mHeadsetClientStateMachine.mCurrentDevice);

        Assert.assertEquals(mHeadsetClientStateMachine.getAudioState(mTestDevice),
                BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
    }

    @Test
    public void testGetAudioState_withCurrentDeviceNotNull() {
        int audioState = 1;
        mHeadsetClientStateMachine.mAudioState = audioState;
        mHeadsetClientStateMachine.mCurrentDevice = mTestDevice;

        Assert.assertEquals(mHeadsetClientStateMachine.getAudioState(mTestDevice), audioState);
    }

    @Test
    public void testGetCall_withMatchingState() {
        HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_ACTIVE,
                "1", true, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, call);
        int[] states = new int[1];
        states[0] = HfpClientCall.CALL_STATE_ACTIVE;

        Assert.assertEquals(mHeadsetClientStateMachine.getCall(states), call);
    }

    @Test
    public void testGetCall_withNoMatchingState() {
        HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_WAITING,
                "1", true, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, call);
        int[] states = new int[1];
        states[0] = HfpClientCall.CALL_STATE_ACTIVE;

        Assert.assertNull(mHeadsetClientStateMachine.getCall(states));
    }

    @Test
    public void testGetConnectionState_withNullDevice() {
        Assert.assertEquals(mHeadsetClientStateMachine.getConnectionState(null),
                BluetoothProfile.STATE_DISCONNECTED);
    }

    @Test
    public void testGetConnectionState_withNonNullDevice() {
        mHeadsetClientStateMachine.mCurrentDevice = mTestDevice;

        Assert.assertEquals(mHeadsetClientStateMachine.getConnectionState(mTestDevice),
                BluetoothProfile.STATE_DISCONNECTED);
    }

    @Test
    public void testGetConnectionStateFromAudioState() {
        Assert.assertEquals(HeadsetClientStateMachine.getConnectionStateFromAudioState(
                BluetoothHeadsetClient.STATE_AUDIO_CONNECTED), BluetoothAdapter.STATE_CONNECTED);
        Assert.assertEquals(HeadsetClientStateMachine.getConnectionStateFromAudioState(
                BluetoothHeadsetClient.STATE_AUDIO_CONNECTING), BluetoothAdapter.STATE_CONNECTING);
        Assert.assertEquals(HeadsetClientStateMachine.getConnectionStateFromAudioState(
                        BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED),
                BluetoothAdapter.STATE_DISCONNECTED);
        int invalidAudioState = 3;
        Assert.assertEquals(
                HeadsetClientStateMachine.getConnectionStateFromAudioState(invalidAudioState),
                BluetoothAdapter.STATE_DISCONNECTED);
    }

    @Test
    public void testGetCurrentAgEvents() {
        Bundle bundle = mHeadsetClientStateMachine.getCurrentAgEvents();

        Assert.assertEquals(bundle.getString(BluetoothHeadsetClient.EXTRA_SUBSCRIBER_INFO),
                mHeadsetClientStateMachine.mSubscriberInfo);
    }

    @Test
    public void testGetCurrentAgFeatures() {
        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_3WAY;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC;
        Set<Integer> features = mHeadsetClientStateMachine.getCurrentAgFeatures();
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_3WAY));
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_VREC;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL;
        features = mHeadsetClientStateMachine.getCurrentAgFeatures();
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_VREC));
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_REJECT;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL_ACC;
        features = mHeadsetClientStateMachine.getCurrentAgFeatures();
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_REJECT));
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL_ACC));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_ECC;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE;
        features = mHeadsetClientStateMachine.getCurrentAgFeatures();
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_ECC));
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE));

        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH;
        features = mHeadsetClientStateMachine.getCurrentAgFeatures();
        Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH));
    }

    @Test
    public void testGetCurrentAgFeaturesBundle() {
        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_3WAY;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC;
        Bundle bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle();
        Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_3WAY_CALLING));
        Assert.assertTrue(bundle.getBoolean(
                BluetoothHeadsetClient.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_VREC;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL;
        bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle();
        Assert.assertTrue(
                bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_VOICE_RECOGNITION));
        Assert.assertTrue(bundle.getBoolean(
                BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_REJECT;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL_ACC;
        bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle();
        Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_REJECT_CALL));
        Assert.assertTrue(
                bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT));

        mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_ECC;
        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE;
        bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle();
        Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ECC));
        Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE));

        mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH;
        bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle();
        Assert.assertTrue(
                bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE_AND_DETACH));
    }

    @Test
    public void testGetCurrentCalls() {
        HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_WAITING,
                "1", true, false, false);
        mHeadsetClientStateMachine.mCalls.put(0, call);

        List<HfpClientCall> currentCalls = mHeadsetClientStateMachine.getCurrentCalls();

        Assert.assertEquals(currentCalls.get(0), call);
    }

    @Test
    public void testGetMessageName() {
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(StackEvent.STACK_EVENT),
                "STACK_EVENT");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT),
                "CONNECT");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISCONNECT),
                "DISCONNECT");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT_AUDIO),
                "CONNECT_AUDIO");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.DISCONNECT_AUDIO), "DISCONNECT_AUDIO");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_START),
                "VOICE_RECOGNITION_START");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_STOP),
                "VOICE_RECOGNITION_STOP");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SET_MIC_VOLUME),
                "SET_MIC_VOLUME");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.SET_SPEAKER_VOLUME), "SET_SPEAKER_VOLUME");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DIAL_NUMBER),
                "DIAL_NUMBER");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.ACCEPT_CALL),
                "ACCEPT_CALL");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.REJECT_CALL),
                "REJECT_CALL");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.HOLD_CALL),
                "HOLD_CALL");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.TERMINATE_CALL),
                "TERMINATE_CALL");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(ENTER_PRIVATE_MODE),
                "ENTER_PRIVATE_MODE");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_DTMF),
                "SEND_DTMF");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(EXPLICIT_CALL_TRANSFER),
                "EXPLICIT_CALL_TRANSFER");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISABLE_NREC),
                "DISABLE_NREC");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND), "SEND_VENDOR_AT_COMMAND");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_BIEV),
                "SEND_BIEV");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.QUERY_CURRENT_CALLS), "QUERY_CURRENT_CALLS");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.QUERY_OPERATOR_NAME), "QUERY_OPERATOR_NAME");
        Assert.assertEquals(
                HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SUBSCRIBER_INFO),
                "SUBSCRIBER_INFO");
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(
                HeadsetClientStateMachine.CONNECTING_TIMEOUT), "CONNECTING_TIMEOUT");
        int unknownMessageInt = 54;
        Assert.assertEquals(HeadsetClientStateMachine.getMessageName(unknownMessageInt),
                "UNKNOWN(" + unknownMessageInt + ")");
    }
}