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

Commit db5c3663 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "CSIP: Fix notifying about connected devices"

parents 1e738baf 9fa2190a
Loading
Loading
Loading
Loading
+42 −7
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ public class CsipSetCoordinatorService extends ProfileService {
    private final Map<Integer, Integer> mGroupIdToGroupSize = new HashMap<>();
    // Tracks the number of available devices mapped to the group id
    private final Map<Integer, Set<BluetoothDevice>> mGroupIdToConnectedDevices = new HashMap<>();
    private final Map<BluetoothDevice, Integer> mFoundSetMemberToGroupId = new HashMap<>();
    private final Map<ParcelUuid, Map<Executor, IBluetoothCsipSetCoordinatorCallback>> mCallbacks =
            new HashMap<>();
    private final Map<Integer, Pair<UUID, IBluetoothCsipSetCoordinatorLockCallback>> mLocks =
@@ -221,6 +222,7 @@ public class CsipSetCoordinatorService extends ProfileService {

        mDeviceGroupIdRankMap.clear();
        mCallbacks.clear();
        mFoundSetMemberToGroupId.clear();
        mGroupIdToGroupSize.clear();
        mGroupIdToConnectedDevices.clear();
        mGroupIdToUuidMap.clear();
@@ -832,6 +834,25 @@ public class CsipSetCoordinatorService extends ProfileService {
        }
    }

    void notifySetMemberAvailable(BluetoothDevice device, int groupId) {
        if (DBG) {
            Log.d(TAG, "notifySetMemberAvailable: " + device + ", " + groupId);
        }

        /* Sent intent as well */
        Intent intent = new Intent(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID, groupId);

        intent.addFlags(
                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, BLUETOOTH_PRIVILEGED);

        /* Notify registered parties */
        handleSetMemberAvailable(device, groupId);
    }

    void messageFromNative(CsipSetCoordinatorStackEvent stackEvent) {
        BluetoothDevice device = stackEvent.device;
        Log.d(TAG, "Message from native: " + stackEvent);
@@ -854,13 +875,12 @@ public class CsipSetCoordinatorService extends ProfileService {
        } else if (stackEvent.type
                == CsipSetCoordinatorStackEvent.EVENT_TYPE_SET_MEMBER_AVAILABLE) {
            Objects.requireNonNull(device, "Device should never be null, event: " + stackEvent);
            /* Notify registered parties */
            handleSetMemberAvailable(device, stackEvent.valueInt1);

            /* Sent intent as well */
            intent = new Intent(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID, groupId);
            if (!mFoundSetMemberToGroupId.containsKey(device)) {
                mFoundSetMemberToGroupId.put(device, groupId);
            }
            if (mGroupIdToConnectedDevices.containsKey(groupId)) {
                notifySetMemberAvailable(device, groupId);
            }
        } else if (stackEvent.type == CsipSetCoordinatorStackEvent.EVENT_TYPE_GROUP_LOCK_CHANGED) {
            int lock_status = stackEvent.valueInt2;
            boolean lock_state = stackEvent.valueBool1;
@@ -953,6 +973,10 @@ public class CsipSetCoordinatorService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "Bond state changed for device: " + device + " state: " + bondState);
        }
        if (bondState == BluetoothDevice.BOND_BONDING
                && mFoundSetMemberToGroupId.containsKey(device)) {
            mFoundSetMemberToGroupId.remove(device);
        }

        // Remove state machine if the bonding for a device is removed
        if (bondState != BluetoothDevice.BOND_NONE) {
@@ -1017,6 +1041,11 @@ public class CsipSetCoordinatorService extends ProfileService {
            if (!mGroupIdToConnectedDevices.containsKey(groupId)) {
                mGroupIdToConnectedDevices.put(groupId, new HashSet<>());
            }
            for (Map.Entry<BluetoothDevice, Integer> entry : mFoundSetMemberToGroupId.entrySet()) {
                if (entry.getValue() == groupId) {
                    notifySetMemberAvailable(entry.getKey(), groupId);
                }
            }
            mGroupIdToConnectedDevices.get(groupId).add(device);
            disableCsipIfNeeded(groupId);
        }
@@ -1337,5 +1366,11 @@ public class CsipSetCoordinatorService extends ProfileService {
        for (CsipSetCoordinatorStateMachine sm : mStateMachines.values()) {
            sm.dump(sb);
        }
        ProfileService.println(sb, "mFoundSetMemberToGroupId: ");
        for (Map.Entry<BluetoothDevice, Integer> entry : mFoundSetMemberToGroupId.entrySet()) {
            ProfileService.println(
                    sb,
                    "  member device: " + entry.getKey() + ", group ID: " + entry.getValue());
        }
    }
}
+75 −5
Original line number Diff line number Diff line
@@ -521,23 +521,93 @@ public class CsipSetCoordinatorServiceTest {
    }

    /**
     * Test that native callback generates proper intent.
     * Test that native callback generates proper intent after group connected.
     */
    @Test
    public void testStackEventSetMemberAvailable() {
    public void testStackEventSetMemberAvailableAfterGroupConnected() {
        int group_id = 0x01;
        int group_size = 0x02;
        long uuidLsb = BluetoothUuid.CAP.getUuid().getLeastSignificantBits();
        long uuidMsb = BluetoothUuid.CAP.getUuid().getMostSignificantBits();

        // Make sure to use real methods when needed below
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onDeviceAvailable(any(byte[].class), anyInt(), anyInt(), anyInt(), anyLong(),
                        anyLong());
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onConnectionStateChanged(any(byte[].class), anyInt());
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onSetMemberAvailable(any(byte[].class), anyInt());

        mCsipSetCoordinatorNativeInterface.onDeviceAvailable(
                getByteAddress(mTestDevice), group_id, group_size, 0x02, uuidLsb, uuidMsb);

        mCsipSetCoordinatorNativeInterface.onConnectionStateChanged(
                getByteAddress(mTestDevice), BluetoothProfile.STATE_CONNECTED);

        // Comes from state machine
        mService.connectionStateChanged(mTestDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_CONNECTED);

        mCsipSetCoordinatorNativeInterface.onSetMemberAvailable(
                getByteAddress(mTestDevice), group_id);
                getByteAddress(mTestDevice2), group_id);

        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mTestDevice));
        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mTestDevice2));
        Assert.assertNotNull(intent);
        Assert.assertEquals(
                BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE, intent.getAction());
        Assert.assertEquals(mTestDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
        Assert.assertEquals(mTestDevice2, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
        Assert.assertEquals(
                group_id, intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID, -1));
    }

    /**
     * Test that native callback generates proper intent before group connected.
     */
    @Test
    public void testStackEventSetMemberAvailableBeforeGroupConnected() {
        int group_id = 0x01;
        int group_size = 0x02;
        long uuidLsb = BluetoothUuid.CAP.getUuid().getLeastSignificantBits();
        long uuidMsb = BluetoothUuid.CAP.getUuid().getMostSignificantBits();

        // Make sure to use real methods when needed below
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onDeviceAvailable(any(byte[].class), anyInt(), anyInt(), anyInt(), anyLong(),
                        anyLong());
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onSetMemberAvailable(any(byte[].class), anyInt());
        doCallRealMethod()
                .when(mCsipSetCoordinatorNativeInterface)
                .onConnectionStateChanged(any(byte[].class), anyInt());

        mCsipSetCoordinatorNativeInterface.onDeviceAvailable(
                getByteAddress(mTestDevice), group_id, group_size, 0x02, uuidLsb, uuidMsb);

        mCsipSetCoordinatorNativeInterface.onConnectionStateChanged(
                getByteAddress(mTestDevice), BluetoothProfile.STATE_CONNECTED);

        mCsipSetCoordinatorNativeInterface.onSetMemberAvailable(
                getByteAddress(mTestDevice2), group_id);

        Intent intent = TestUtils.waitForNoIntent(TIMEOUT_MS, mIntentQueue.get(mTestDevice2));
        Assert.assertNull(intent);

          // Comes from state machine
        mService.connectionStateChanged(mTestDevice, BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_CONNECTED);

        intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mTestDevice2));
        Assert.assertNotNull(intent);

        Assert.assertEquals(
                BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE, intent.getAction());
        Assert.assertEquals(mTestDevice2, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
        Assert.assertEquals(
                group_id, intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID, -1));
    }