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

Commit a9690587 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4754571 from 2eb9e49a to pi-release

Change-Id: I00354df2896f39c22e7a1c5ec7cdf2a60c373cfd
parents 9cd88d6a 2eb9e49a
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -111,6 +111,10 @@ public class HearingAidService extends ProfileService {
        mStateMachinesThread = new HandlerThread("HearingAidService.StateMachines");
        mStateMachinesThread.start();

        // Clear HiSyncId map and capabilities map
        mDeviceHiSyncIdMap.clear();
        mDeviceCapabilitiesMap.clear();

        // Setup broadcast receivers
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
@@ -162,6 +166,10 @@ public class HearingAidService extends ProfileService {
            mStateMachines.clear();
        }

        // Clear HiSyncId map and capabilities map
        mDeviceHiSyncIdMap.clear();
        mDeviceCapabilitiesMap.clear();

        if (mStateMachinesThread != null) {
            mStateMachinesThread.quitSafely();
            mStateMachinesThread = null;
@@ -227,13 +235,26 @@ public class HearingAidService extends ProfileService {
        long hiSyncId = mDeviceHiSyncIdMap.getOrDefault(device,
                BluetoothHearingAid.HI_SYNC_ID_INVALID);

        if (hiSyncId != mActiveDeviceHiSyncId) {
        if (hiSyncId != mActiveDeviceHiSyncId
                && hiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID
                && mActiveDeviceHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
            for (BluetoothDevice connectedDevice : getConnectedDevices()) {
                disconnect(connectedDevice);
            }
        }

        synchronized (mStateMachines) {
            HearingAidStateMachine smConnect = getOrCreateStateMachine(device);
            if (smConnect == null) {
                Log.e(TAG, "Cannot connect to " + device + " : no state machine");
            }
            smConnect.sendMessage(HearingAidStateMachine.CONNECT);
        }

        for (BluetoothDevice storedDevice : mDeviceHiSyncIdMap.keySet()) {
            if (device.equals(storedDevice)) {
                continue;
            }
            if (mDeviceHiSyncIdMap.getOrDefault(storedDevice,
                    BluetoothHearingAid.HI_SYNC_ID_INVALID) == hiSyncId) {
                synchronized (mStateMachines) {
@@ -243,7 +264,6 @@ public class HearingAidService extends ProfileService {
                        continue;
                    }
                    sm.sendMessage(HearingAidStateMachine.CONNECT);

                }
                if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID
                        && !device.equals(storedDevice)) {
@@ -511,6 +531,10 @@ public class HearingAidService extends ProfileService {
            BluetoothDevice device = stackEvent.device;
            int capabilities = stackEvent.valueInt1;
            long hiSyncId = stackEvent.valueLong2;
            if (DBG) {
                Log.d(TAG, "Device available: device=" + device + " capabilities="
                        + capabilities + " hiSyncId=" + hiSyncId);
            }
            mDeviceCapabilitiesMap.put(device, capabilities);
            mDeviceHiSyncIdMap.put(device, hiSyncId);
            return;
+3 −0
Original line number Diff line number Diff line
@@ -186,11 +186,13 @@ public class AvrcpNativeInterface {
    }

    void setActiveDevice(String bdaddr) {
        bdaddr = bdaddr.toUpperCase();
        d("setActiveDevice: bdaddr=" + bdaddr);
        mAvrcpService.setActiveDevice(bdaddr);
    }

    void deviceConnected(String bdaddr, boolean absoluteVolume) {
        bdaddr = bdaddr.toUpperCase();
        d("deviceConnected: bdaddr=" + bdaddr + " absoluteVolume=" + absoluteVolume);
        if (mAvrcpService == null) {
            Log.w(TAG, "deviceConnected: AvrcpTargetService is null");
@@ -201,6 +203,7 @@ public class AvrcpNativeInterface {
    }

    void deviceDisconnected(String bdaddr) {
        bdaddr = bdaddr.toUpperCase();
        d("deviceDisconnected: bdaddr=" + bdaddr);
        if (mAvrcpService == null) {
            Log.w(TAG, "deviceDisconnected: AvrcpTargetService is null");
+1 −2
Original line number Diff line number Diff line
@@ -296,7 +296,7 @@ public class AvrcpTargetService extends ProfileService {
    void setActiveDevice(String address) {
        Log.i(TAG, "setActiveDevice: address=" + address);
        BluetoothDevice d =
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address.toUpperCase());
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
        if (d == null) {
            Log.wtfStack(TAG, "setActiveDevice: could not find device with address " + address);
        }
@@ -320,7 +320,6 @@ public class AvrcpTargetService extends ProfileService {
        }

        mVolumeManager.dump(sb);
        sb.append("\n");
    }

    private static class AvrcpTargetBinder extends IBluetoothAvrcpTarget.Stub
+49 −45
Original line number Diff line number Diff line
@@ -44,21 +44,58 @@ class AvrcpVolumeManager {
    String mCurrentDeviceAddr = "";
    boolean mAbsoluteVolumeSupported = false;

    int avrcpToSystemVolume(int avrcpVolume) {
    static int avrcpToSystemVolume(int avrcpVolume) {
        return (int) Math.floor((double) avrcpVolume * sDeviceMaxVolume / AVRCP_MAX_VOL);
    }

    int systemToAvrcpVolume(int deviceVolume) {
    static int systemToAvrcpVolume(int deviceVolume) {
        int avrcpVolume = (int) Math.floor((double) deviceVolume
                * AVRCP_MAX_VOL / sDeviceMaxVolume);
        if (avrcpVolume > 127) avrcpVolume = 127;
        return avrcpVolume;
    }

    SharedPreferences getVolumeMap() {
    private SharedPreferences getVolumeMap() {
        return mContext.getSharedPreferences(VOLUME_MAP, Context.MODE_PRIVATE);
    }

    private int getVolume(String bdaddr, int defaultValue) {
        if (!mVolumeMap.containsKey(bdaddr)) {
            Log.w(TAG, "getVolume: Couldn't find volume preference for device: " + bdaddr);
            return defaultValue;
        }

        return mVolumeMap.get(bdaddr);
    }

    private void switchVolumeDevice(String bdaddr) {
        // Inform the audio manager that the device has changed
        mAudioManager.avrcpSupportsAbsoluteVolume(bdaddr, mDeviceMap.get(bdaddr));

        // Get the current system volume and try to get the preference volume
        int currVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
        int savedVolume = getVolume(bdaddr, currVolume);

        // If the preference volume isn't equal to the current stream volume then that means
        // we had a stored preference.
        if (DEBUG) {
            Log.d(TAG, "switchVolumeDevice: currVolume=" + currVolume
                    + " savedVolume=" + savedVolume);
        }
        if (savedVolume != currVolume) {
            Log.i(TAG, "switchVolumeDevice: restoring volume level " + savedVolume);
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, savedVolume,
                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
        }

        // If absolute volume for the device is supported, set the volume for the device
        if (mDeviceMap.get(bdaddr)) {
            int avrcpVolume = systemToAvrcpVolume(savedVolume);
            Log.i(TAG, "switchVolumeDevice: Updating device volume: avrcpVolume=" + avrcpVolume);
            mNativeInterface.sendVolumeChanged(avrcpVolume);
        }
    }

    AvrcpVolumeManager(Context context, AudioManager audioManager,
            AvrcpNativeInterface nativeInterface) {
        mContext = context;
@@ -66,7 +103,7 @@ class AvrcpVolumeManager {
        mNativeInterface = nativeInterface;
        sDeviceMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        // Load the volume map into a hash map since shared preferences are slow
        // Load the volume map into a hash map since shared preferences are slow to poll and update
        Map<String, ?> allKeys = getVolumeMap().getAll();
        for (Map.Entry<String, ?> entry : allKeys.entrySet()) {
            String key = entry.getKey();
@@ -77,15 +114,6 @@ class AvrcpVolumeManager {
        }
    }

    int getVolume(String bdaddr, int defaultValue) {
        if (!mVolumeMap.containsKey(bdaddr)) {
            Log.w(TAG, "getVolume: Couldn't find volume preference for device: " + bdaddr);
            return defaultValue;
        }

        return mVolumeMap.get(bdaddr);
    }

    void storeVolume() {
        SharedPreferences.Editor pref = getVolumeMap().edit();
        int storeVolume =  mAudioManager.getStreamVolume(STREAM_MUSIC);
@@ -101,18 +129,18 @@ class AvrcpVolumeManager {
            Log.d(TAG, "deviceConnected: bdaddr=" + bdaddr + " absoluteVolume=" + absoluteVolume);
        }

        mDeviceMap.put(bdaddr.toUpperCase(), absoluteVolume);
        mDeviceMap.put(bdaddr, absoluteVolume);

        // AVRCP features lookup has completed after the device became active. Switch to the new
        // device now.
        if (bdaddr == mCurrentDeviceAddr) {
        if (bdaddr.equals(mCurrentDeviceAddr)) {
            switchVolumeDevice(bdaddr);
        }
    }

    void volumeDeviceSwitched(String bdaddr) {
        if (DEBUG) {
            Log.d(TAG, "activeDeviceChanged: mCurrentDeviceAddr=" + mCurrentDeviceAddr
            Log.d(TAG, "volumeDeviceSwitched: mCurrentDeviceAddr=" + mCurrentDeviceAddr
                    + " bdaddr=" + bdaddr);
        }

@@ -137,53 +165,29 @@ class AvrcpVolumeManager {
        // device supports absolute volume. Defer switching the device until AVRCP returns the
        // info.
        if (!mDeviceMap.containsKey(bdaddr)) {
            Log.w(TAG, "Device isn't connected: " + bdaddr);
            Log.w(TAG, "volumeDeviceSwitched: Device isn't connected: " + bdaddr);
            return;
        }

        switchVolumeDevice(bdaddr);
    }

    void switchVolumeDevice(String bdaddr) {
        // Inform the audio manager that the device has changed
        mAudioManager.avrcpSupportsAbsoluteVolume(bdaddr, mDeviceMap.get(bdaddr));

        // Get the current system volume and try to get the preference volume
        int currVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
        int savedVolume = getVolume(bdaddr, currVolume);

        // If the preference volume isn't equal to the current stream volume then that means
        // we had a stored preference.
    void deviceDisconnected(String bdaddr) {
        if (DEBUG) {
            Log.d(TAG, "activeDeviceChanged: currVolume=" + currVolume
                    + " savedVolume=" + savedVolume);
        }
        if (savedVolume != currVolume) {
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, savedVolume,
                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
        }

        // If absolute volume for the device is supported, set the volume for the device
        if (mDeviceMap.get(bdaddr)) {
            int avrcpVolume = systemToAvrcpVolume(savedVolume);
            Log.e(TAG, "activeDeviceChanged: Updating device volume: avrcpVolume=" + avrcpVolume);
            mNativeInterface.sendVolumeChanged(avrcpVolume);
        }
            Log.d(TAG, "deviceDisconnected: bdaddr=" + bdaddr);
        }

    void deviceDisconnected(String bdaddr) {
        Log.e(TAG, "deviceDisconnected: bdaddr=" + bdaddr);
        mDeviceMap.remove(bdaddr);
    }

    public void dump(StringBuilder sb) {
        sb.append("Bluetooth Device Volume Map:\n");
        sb.append("  Device Address    : Volume\n");
        Map<String, ?> allKeys = getVolumeMap().getAll();
        for (Map.Entry<String, ?> entry : allKeys.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Integer) {
                sb.append("    " + key + " - " + (Integer) value + "\n");
                sb.append("  " + key + " : " + (Integer) value + "\n");
                mVolumeMap.put(key, (Integer) value);
            }
        }
+172 −20
Original line number Diff line number Diff line
@@ -115,19 +115,6 @@ public class HearingAidServiceTest {
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_UNDEFINED);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_UNDEFINED);
        mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_UNDEFINED);
        HearingAidStackEvent event = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        event.device = mLeftDevice;
        event.valueInt1 = 0x02;
        event.valueLong2 = 0x0101;
        mService.messageFromNative(event);
        event.device = mRightDevice;
        event.valueInt1 = 0x03;
        mService.messageFromNative(event);
        event.device = mSingleDevice;
        event.valueInt1 = 0x00;
        event.valueLong2 = 0x0102;
        mService.messageFromNative(event);
        doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService)
                .getBondState(any(BluetoothDevice.class));
        doReturn(new ParcelUuid[]{BluetoothUuid.HearingAid}).when(mAdapterService)
@@ -408,8 +395,8 @@ public class HearingAidServiceTest {
     */
    @Test
    public void testConnectAPair_connectBothDevices() {
        HearingAidStackEvent connCompletedEvent;

        // Update hiSyncId map
        getHiSyncIdFromNative();
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
@@ -436,8 +423,8 @@ public class HearingAidServiceTest {
     */
    @Test
    public void testConnectAnotherPair_disconnectCurrentPair() {
        HearingAidStackEvent connCompletedEvent;

        // Update hiSyncId map
        getHiSyncIdFromNative();
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
@@ -454,7 +441,7 @@ public class HearingAidServiceTest {
        verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);


        HearingAidStackEvent connCompletedEvent;
        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
@@ -496,8 +483,8 @@ public class HearingAidServiceTest {
     */
    @Test
    public void testAudioManagerConnectDisconnect() {
        HearingAidStackEvent connCompletedEvent;

        // Update hiSyncId map
        getHiSyncIdFromNative();
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
@@ -519,6 +506,7 @@ public class HearingAidServiceTest {
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mRightDevice));

        HearingAidStackEvent connCompletedEvent;
        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
@@ -769,6 +757,8 @@ public class HearingAidServiceTest {

    @Test
    public void testConnectionStateChangedActiveDevice() {
        // Update hiSyncId map
        getHiSyncIdFromNative();
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
@@ -797,6 +787,8 @@ public class HearingAidServiceTest {

    @Test
    public void testConnectionStateChangedAnotherActiveDevice() {
        // Update hiSyncId map
        getHiSyncIdFromNative();
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
@@ -819,6 +811,151 @@ public class HearingAidServiceTest {
        Assert.assertTrue(mService.getActiveDevices().contains(mSingleDevice));
    }

    /**
     * Verify the correctness during first time connection.
     * Connect to left device -> Get left device hiSyncId -> Connect to right device ->
     * Get right device hiSyncId -> Both devices should be always connected
     */
    @Test
    public void firstTimeConnection_shouldConnectToBothDevices() {
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
        doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class));
        doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class));
        // Send a connect request for left device
        Assert.assertTrue("Connect failed", mService.connect(mLeftDevice));
        // Verify the connection state broadcast, and that we are in Connecting state
        verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mLeftDevice));

        HearingAidStackEvent connCompletedEvent;
        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connCompletedEvent.device = mLeftDevice;
        connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED;
        mService.messageFromNative(connCompletedEvent);

        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));

        // Get hiSyncId for left device
        HearingAidStackEvent hiSyncIdEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        hiSyncIdEvent.device = mLeftDevice;
        hiSyncIdEvent.valueInt1 = 0x02;
        hiSyncIdEvent.valueLong2 = 0x0101;
        mService.messageFromNative(hiSyncIdEvent);

        // Send a connect request for right device
        Assert.assertTrue("Connect failed", mService.connect(mRightDevice));
        // Verify the connection state broadcast, and that we are in Connecting state
        verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mRightDevice));
        // Verify the left device is still connected
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));

        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connCompletedEvent.device = mRightDevice;
        connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED;
        mService.messageFromNative(connCompletedEvent);

        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mRightDevice));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));

        // Get hiSyncId for right device
        hiSyncIdEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        hiSyncIdEvent.device = mRightDevice;
        hiSyncIdEvent.valueInt1 = 0x02;
        hiSyncIdEvent.valueLong2 = 0x0101;
        mService.messageFromNative(hiSyncIdEvent);

        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mRightDevice));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));
    }

    /**
     * Get the HiSyncId from native stack after connecting to left device, then connect right
     */
    @Test
    public void getHiSyncId_afterFirstDeviceConnected() {
        // Update the device priority so okToConnect() returns true
        mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON);
        mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_ON);
        doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class));
        doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class));
        // Send a connect request
        Assert.assertTrue("Connect failed", mService.connect(mLeftDevice));
        // Verify the connection state broadcast, and that we are in Connecting state
        verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mLeftDevice));
        Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
                mService.getConnectionState(mRightDevice));

        HearingAidStackEvent connCompletedEvent;
        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connCompletedEvent.device = mLeftDevice;
        connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED;
        mService.messageFromNative(connCompletedEvent);
        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));

        // Get hiSyncId update from native stack
        getHiSyncIdFromNative();
        // Send a connect request for right
        Assert.assertTrue("Connect failed", mService.connect(mRightDevice));
        // Verify the connection state broadcast, and that we are in Connecting state
        verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mRightDevice));
        // Verify the left device is still connected
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));

        // Send a message to trigger connection completed
        connCompletedEvent = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connCompletedEvent.device = mRightDevice;
        connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED;
        mService.messageFromNative(connCompletedEvent);

        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mRightDevice));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mLeftDevice));
    }

    private void connectDevice(BluetoothDevice device) {
        HearingAidStackEvent connCompletedEvent;

@@ -896,4 +1033,19 @@ public class HearingAidServiceTest {
        Assert.assertEquals(expected, mService.okToConnect(device));
    }

    private void getHiSyncIdFromNative() {
        HearingAidStackEvent event = new HearingAidStackEvent(
                HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        event.device = mLeftDevice;
        event.valueInt1 = 0x02;
        event.valueLong2 = 0x0101;
        mService.messageFromNative(event);
        event.device = mRightDevice;
        event.valueInt1 = 0x03;
        mService.messageFromNative(event);
        event.device = mSingleDevice;
        event.valueInt1 = 0x00;
        event.valueLong2 = 0x0102;
        mService.messageFromNative(event);
    }
}