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

Commit e63bdffe authored by David Duarte's avatar David Duarte Committed by Gerrit Code Review
Browse files

Merge "HapClientTest: Remove dependency to broadcasts" into main

parents 41375c8c ccda09b9
Loading
Loading
Loading
Loading
+112 −111
Original line number Original line Diff line number Diff line
@@ -17,15 +17,31 @@


package com.android.bluetooth.hap;
package com.android.bluetooth.hap;


import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;

import static org.mockito.Mockito.after;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import static org.hamcrest.core.AllOf.allOf;

import static android.bluetooth.BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED;
import static android.bluetooth.BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE;

import static android.bluetooth.BluetoothProfile.EXTRA_STATE;
import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
@@ -36,10 +52,7 @@ import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothHapClientCallback;
import android.bluetooth.IBluetoothHapClientCallback;
import android.content.AttributionSource;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Binder;
import android.os.Looper;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.ParcelUuid;
@@ -63,6 +76,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;
@@ -74,7 +88,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Optional;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeoutException;


@MediumTest
@MediumTest
@@ -87,13 +100,11 @@ public class HapClientTest {
    private BluetoothDevice mDevice;
    private BluetoothDevice mDevice;
    private BluetoothDevice mDevice2;
    private BluetoothDevice mDevice2;
    private BluetoothDevice mDevice3;
    private BluetoothDevice mDevice3;
    private Context mTargetContext;
    private HapClientService mService;
    private HapClientService mService;
    private HapClientService.BluetoothHapClientBinder mServiceBinder;
    private HapClientService.BluetoothHapClientBinder mServiceBinder;
    private AttributionSource mAttributionSource;
    private AttributionSource mAttributionSource;
    private HasIntentReceiver mHasIntentReceiver;
    private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mIntentQueue;


    @Mock private Context mContext;
    @Mock private AdapterService mAdapterService;
    @Mock private AdapterService mAdapterService;
    @Mock private DatabaseManager mDatabaseManager;
    @Mock private DatabaseManager mDatabaseManager;
    @Mock private HapClientNativeInterface mNativeInterface;
    @Mock private HapClientNativeInterface mNativeInterface;
@@ -108,7 +119,6 @@ public class HapClientTest {
            System.setProperty("dexmaker.share_classloader", "true");
            System.setProperty("dexmaker.share_classloader", "true");
        }
        }


        mTargetContext = InstrumentationRegistry.getTargetContext();
        // Set up mocks and test assets
        // Set up mocks and test assets
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);


@@ -131,18 +141,9 @@ public class HapClientTest {
        mServiceBinder = (HapClientService.BluetoothHapClientBinder) mService.initBinder();
        mServiceBinder = (HapClientService.BluetoothHapClientBinder) mService.initBinder();
        mServiceBinder.mIsTesting = true;
        mServiceBinder.mIsTesting = true;


        // Set up the State Changed receiver
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE);

        when(mCallback.asBinder()).thenReturn(mBinder);
        when(mCallback.asBinder()).thenReturn(mBinder);
        mService.mCallbacks.register(mCallback);
        mService.mCallbacks.register(mCallback);


        mHasIntentReceiver = new HasIntentReceiver();
        mTargetContext.registerReceiver(mHasIntentReceiver, filter, Context.RECEIVER_EXPORTED);

        mDevice = TestUtils.getTestDevice(mAdapter, 0);
        mDevice = TestUtils.getTestDevice(mAdapter, 0);
        when(mNativeInterface.getDevice(getByteAddress(mDevice))).thenReturn(mDevice);
        when(mNativeInterface.getDevice(getByteAddress(mDevice))).thenReturn(mDevice);
        mDevice2 = TestUtils.getTestDevice(mAdapter, 1);
        mDevice2 = TestUtils.getTestDevice(mAdapter, 1);
@@ -192,11 +193,6 @@ public class HapClientTest {
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
        doReturn(mDatabaseManager).when(mAdapterService).getDatabase();

        mIntentQueue = new HashMap<>();
        mIntentQueue.put(mDevice, new LinkedBlockingQueue<>());
        mIntentQueue.put(mDevice2, new LinkedBlockingQueue<>());
        mIntentQueue.put(mDevice3, new LinkedBlockingQueue<>());
    }
    }


    @After
    @After
@@ -214,22 +210,15 @@ public class HapClientTest {
        stopService();
        stopService();
        HapClientNativeInterface.setInstance(null);
        HapClientNativeInterface.setInstance(null);


        if (mHasIntentReceiver != null) {
            mTargetContext.unregisterReceiver(mHasIntentReceiver);
        }

        mAdapter = null;
        mAdapter = null;


        if (mAdapterService != null) {
        if (mAdapterService != null) {
            TestUtils.clearAdapterService(mAdapterService);
            TestUtils.clearAdapterService(mAdapterService);
        }
        }

        if (mIntentQueue != null)
            mIntentQueue.clear();
    }
    }


    private void startService() throws TimeoutException {
    private void startService() throws TimeoutException {
        mService = new HapClientService(mTargetContext);
        mService = new HapClientService(mContext);
        mService.doStart();
        mService.doStart();
    }
    }


@@ -381,7 +370,7 @@ public class HapClientTest {
        // Send a connect request
        // Send a connect request
        Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice));
        Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice));


        TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice));
        verify(mContext, timeout(TIMEOUT_MS)).sendBroadcast(any(), any());
    }
    }


    /**
    /**
@@ -406,6 +395,8 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testOutgoingConnectTimeout() throws Exception {
    public void testOutgoingConnectTimeout() throws Exception {
        InOrder order = inOrder(mContext);

        // Update the device policy so okToConnect() returns true
        // Update the device policy so okToConnect() returns true
        when(mDatabaseManager
        when(mDatabaseManager
                .getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
                .getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
@@ -416,15 +407,30 @@ public class HapClientTest {
        // Send a connect request
        // Send a connect request
        Assert.assertTrue("Connect failed", mService.connect(mDevice));
        Assert.assertTrue("Connect failed", mService.connect(mDevice));


        // Verify the connection state broadcast, and that we are in Connecting state
        order.verify(mContext, timeout(TIMEOUT_MS))
        verifyConnectionStateIntent(TIMEOUT_MS, mDevice, BluetoothProfile.STATE_CONNECTING,
                .sendBroadcast(
                BluetoothProfile.STATE_DISCONNECTED);
                        argThat(
                                allOf(
                                        hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
                                        hasExtra(EXTRA_STATE, STATE_CONNECTING),
                                        hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))),
                        any());

        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mDevice));
                mService.getConnectionState(mDevice));


        // Verify the connection state broadcast, and that we are in Disconnected state via binder
        // Verify the connection state broadcast, and that we are in Disconnected state via binder
        verifyConnectionStateIntent(HapClientStateMachine.sConnectTimeoutMs * 2,
        order.verify(mContext, timeout(HapClientStateMachine.sConnectTimeoutMs * 2))
                mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
                .sendBroadcast(
                        argThat(
                                allOf(
                                        hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
                                        hasExtra(EXTRA_STATE, STATE_DISCONNECTED),
                                        hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))),
                        any());

        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        int defaultRecvValue = -1000;
        mServiceBinder.getConnectionState(mDevice, mAttributionSource, recv);
        mServiceBinder.getConnectionState(mDevice, mAttributionSource, recv);
@@ -438,15 +444,16 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testConnectTwo() throws Exception {
    public void testConnectTwo() throws Exception {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));


        // Send a connect request for the 1st device
        // Send a connect request for the 1st device
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        // Send a connect request for the 2nd device
        // Send a connect request for the 2nd device
        BluetoothDevice Device2 = TestUtils.getTestDevice(mAdapter, 1);
        BluetoothDevice Device2 = TestUtils.getTestDevice(mAdapter, 1);
        testConnectingDevice(Device2);
        testConnectingDevice(order, Device2);


        // indirect call of mService.getConnectedDevices to test BluetoothHearingAidBinder
        // indirect call of mService.getConnectedDevices to test BluetoothHearingAidBinder
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
@@ -473,11 +480,12 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testGetHapGroupCoordinatedOps() throws Exception {
    public void testGetHapGroupCoordinatedOps() throws Exception {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);
        testConnectingDevice(mDevice2);
        testConnectingDevice(order, mDevice2);
        testConnectingDevice(mDevice3);
        testConnectingDevice(order, mDevice3);


        int flags = 0x04;
        int flags = 0x04;
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);
@@ -510,9 +518,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSelectPresetNative() {
    public void testSelectPresetNative() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        // Verify Native Interface call
        // Verify Native Interface call
        mService.selectPreset(mDevice, 0x00);
        mService.selectPreset(mDevice, 0x00);
@@ -535,9 +544,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testGroupSelectActivePresetNative() {
    public void testGroupSelectActivePresetNative() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice3);
        testConnectingDevice(order, mDevice3);


        int flags = 0x01;
        int flags = 0x01;
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags);
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags);
@@ -561,9 +571,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSwitchToNextPreset() {
    public void testSwitchToNextPreset() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        // Verify Native Interface call
        // Verify Native Interface call
        mServiceBinder.switchToNextPreset(mDevice, mAttributionSource);
        mServiceBinder.switchToNextPreset(mDevice, mAttributionSource);
@@ -576,9 +587,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSwitchToNextPresetForGroup() {
    public void testSwitchToNextPresetForGroup() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice3);
        testConnectingDevice(order, mDevice3);
        int flags = 0x01;
        int flags = 0x01;
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags);
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags);


@@ -592,9 +604,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSwitchToPreviousPreset() {
    public void testSwitchToPreviousPreset() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        // Verify Native Interface call
        // Verify Native Interface call
        mServiceBinder.switchToPreviousPreset(mDevice, mAttributionSource);
        mServiceBinder.switchToPreviousPreset(mDevice, mAttributionSource);
@@ -607,10 +620,11 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSwitchToPreviousPresetForGroup() {
    public void testSwitchToPreviousPresetForGroup() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);
        testConnectingDevice(mDevice2);
        testConnectingDevice(order, mDevice2);


        int flags = 0x01;
        int flags = 0x01;
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);
@@ -625,9 +639,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testGetActivePresetIndex() throws Exception {
    public void testGetActivePresetIndex() throws Exception {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);
        testOnPresetSelected(mDevice, 0x01);
        testOnPresetSelected(mDevice, 0x01);


        // Verify cached value via binder
        // Verify cached value via binder
@@ -644,9 +659,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testGetPresetInfoAndActivePresetInfo() throws Exception {
    public void testGetPresetInfoAndActivePresetInfo() throws Exception {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice2);
        testConnectingDevice(order, mDevice2);


        // Check when active preset is not known yet
        // Check when active preset is not known yet
        final SynchronousResultReceiver<List<BluetoothHapPresetInfo>> presetListRecv =
        final SynchronousResultReceiver<List<BluetoothHapPresetInfo>> presetListRecv =
@@ -686,9 +702,10 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSetPresetNameNative() {
    public void testSetPresetNameNative() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        mServiceBinder.setPresetName(mDevice, 0x00, "ExamplePresetName", mAttributionSource);
        mServiceBinder.setPresetName(mDevice, 0x00, "ExamplePresetName", mAttributionSource);
        verify(mNativeInterface, times(0))
        verify(mNativeInterface, times(0))
@@ -711,11 +728,12 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testSetPresetNameForGroup() {
    public void testSetPresetNameForGroup() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));
        int test_group = 0x02;
        int test_group = 0x02;
        for (BluetoothDevice device : mCsipService.getGroupDevicesOrdered(test_group)) {
        for (BluetoothDevice device : mCsipService.getGroupDevicesOrdered(test_group)) {
            testConnectingDevice(device);
            testConnectingDevice(order, device);
        }
        }


        int flags = 0x21;
        int flags = 0x21;
@@ -757,12 +775,14 @@ public class HapClientTest {
                .onDeviceAvailable(any(byte[].class), anyInt());
                .onDeviceAvailable(any(byte[].class), anyInt());
        mNativeInterface.onDeviceAvailable(getByteAddress(mDevice), 0x03);
        mNativeInterface.onDeviceAvailable(getByteAddress(mDevice), 0x03);


        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice));
        verify(mContext, timeout(TIMEOUT_MS))
        Assert.assertNotNull(intent);
                .sendBroadcast(
        Assert.assertEquals(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE, intent.getAction());
                        argThat(
        Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
                                allOf(
        Assert.assertEquals(0x03,
                                        hasAction(ACTION_HAP_DEVICE_AVAILABLE),
                intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x00));
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
                                        hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x03))),
                        any());
    }
    }


    /**
    /**
@@ -817,11 +837,12 @@ public class HapClientTest {
     */
     */
    @Test
    @Test
    public void testStackEventOnPresetInfo() {
    public void testStackEventOnPresetInfo() {
        InOrder order = inOrder(mContext);
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
                .getRemoteUuids(any(BluetoothDevice.class));


        // Connect and inject initial presets
        // Connect and inject initial presets
        testConnectingDevice(mDevice);
        testConnectingDevice(order, mDevice);


        int info_reason = HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE;
        int info_reason = HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE;
        BluetoothHapPresetInfo[] info =
        BluetoothHapPresetInfo[] info =
@@ -1047,7 +1068,7 @@ public class HapClientTest {
        // Add state machine for testing dump()
        // Add state machine for testing dump()
        mService.connect(mDevice);
        mService.connect(mDevice);


        TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice));
        verify(mContext, timeout(TIMEOUT_MS)).sendBroadcast(any(), any());


        mService.dump(new StringBuilder());
        mService.dump(new StringBuilder());
    }
    }
@@ -1057,7 +1078,6 @@ public class HapClientTest {
     */
     */
    private void prepareConnectingDevice(BluetoothDevice device) {
    private void prepareConnectingDevice(BluetoothDevice device) {
        // Prepare intent queue and all the mocks
        // Prepare intent queue and all the mocks
        mIntentQueue.put(device, new LinkedBlockingQueue<>());
        when(mNativeInterface.getDevice(getByteAddress(device))).thenReturn(device);
        when(mNativeInterface.getDevice(getByteAddress(device))).thenReturn(device);
        when(mDatabaseManager
        when(mDatabaseManager
                .getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT))
                .getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT))
@@ -1066,23 +1086,26 @@ public class HapClientTest {
        doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
        doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
    }
    }


    /**
    /** Helper function to test device connecting */
     * Helper function to test device connecting
    private void testConnectingDevice(InOrder order, BluetoothDevice device) {
     */
    private void testConnectingDevice(BluetoothDevice device) {
        prepareConnectingDevice(device);
        prepareConnectingDevice(device);
        // Send a connect request
        // Send a connect request
        Assert.assertTrue("Connect expected to succeed", mService.connect(device));
        Assert.assertTrue("Connect expected to succeed", mService.connect(device));
        verifyConnectingDevice(device);
        verifyConnectingDevice(order, device);
    }
    }


    /**
    /** Helper function to test device connecting */
     * Helper function to test device connecting
    private void verifyConnectingDevice(InOrder order, BluetoothDevice device) {
     */
    private void verifyConnectingDevice(BluetoothDevice device) {
        // Verify the connection state broadcast, and that we are in Connecting state
        // Verify the connection state broadcast, and that we are in Connecting state
        verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTING,
        order.verify(mContext, timeout(TIMEOUT_MS))
                BluetoothProfile.STATE_DISCONNECTED);
                .sendBroadcast(
                        argThat(
                                allOf(
                                        hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
                                        hasExtra(EXTRA_STATE, STATE_CONNECTING),
                                        hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))),
                        any());
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device));


        // Send a message to trigger connection completed
        // Send a message to trigger connection completed
@@ -1093,8 +1116,15 @@ public class HapClientTest {
        mService.messageFromNative(evt);
        mService.messageFromNative(evt);


        // Verify the connection state broadcast, and that we are in Connected state
        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTED,
        order.verify(mContext, timeout(TIMEOUT_MS))
                BluetoothProfile.STATE_CONNECTING);
                .sendBroadcast(
                        argThat(
                                allOf(
                                        hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
                                        hasExtra(EXTRA_STATE, STATE_CONNECTED),
                                        hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))),
                        any());
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device));


        evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
@@ -1102,12 +1132,14 @@ public class HapClientTest {
        evt.valueInt1 = 0x01;   // features
        evt.valueInt1 = 0x01;   // features
        mService.messageFromNative(evt);
        mService.messageFromNative(evt);


        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(device));
        order.verify(mContext, timeout(TIMEOUT_MS))
        Assert.assertNotNull(intent);
                .sendBroadcast(
        Assert.assertEquals(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE, intent.getAction());
                        argThat(
        Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
                                allOf(
        Assert.assertEquals(evt.valueInt1,
                                        hasAction(ACTION_HAP_DEVICE_AVAILABLE),
                intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, -1));
                                        hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
                                        hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x01))),
                        any());


        evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_FEATURES);
        evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_FEATURES);
        evt.device = device;
        evt.device = device;
@@ -1148,21 +1180,6 @@ public class HapClientTest {
        }
        }
    }
    }


    /**
     * Helper function to test ConnectionStateIntent() method
     */
    private void verifyConnectionStateIntent(int timeoutMs, BluetoothDevice device,
                                             int newState, int prevState) {
        Intent intent = TestUtils.waitForIntent(timeoutMs, mIntentQueue.get(device));
        Assert.assertNotNull(intent);
        Assert.assertEquals(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED,
                intent.getAction());
        Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
        Assert.assertEquals(newState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
        Assert.assertEquals(prevState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE,
                -1));
    }

    /**
    /**
     * Helper function to test okToConnect() method
     * Helper function to test okToConnect() method
     */
     */
@@ -1183,20 +1200,4 @@ public class HapClientTest {
        }
        }
        return Utils.getBytesFromAddress(device.getAddress());
        return Utils.getBytesFromAddress(device.getAddress());
    }
    }

    private class HasIntentReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                BluetoothDevice device = intent.getParcelableExtra(
                        BluetoothDevice.EXTRA_DEVICE);
                Assert.assertNotNull(device);
                LinkedBlockingQueue<Intent> queue = mIntentQueue.get(device);
                Assert.assertNotNull(queue);
                queue.put(intent);
            } catch (InterruptedException e) {
                Assert.fail("Cannot add Intent to the queue: " + e.getMessage());
            }
        }
    }
}
}