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

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

Merge changes I64de4bb5,I765f4a82,I2f2054c6,I5fdc54d0

* changes:
  Csip: Add method for checking group lock status
  Csip: Add more means to get grouped devices
  BassClient: Allow only one pending source operation
  BassClient: Reconnect devices in the background
parents fd6e7cbc c6d52967
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -96,7 +96,8 @@ class CsisClientCallbacksImpl : public CsisClientCallbacks {
  }
  }


  void OnDeviceAvailable(const RawAddress& bd_addr, int group_id,
  void OnDeviceAvailable(const RawAddress& bd_addr, int group_id,
                         int group_size, const bluetooth::Uuid& uuid) override {
                         int group_size, int rank,
                         const bluetooth::Uuid& uuid) override {
    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
@@ -112,7 +113,7 @@ class CsisClientCallbacksImpl : public CsisClientCallbacks {


    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDeviceAvailable,
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDeviceAvailable,
                                 addr.get(), (jint)group_id, (jint)group_size,
                                 addr.get(), (jint)group_id, (jint)group_size,
                                 UUID_PARAMS(uuid));
                                 (jint)rank, UUID_PARAMS(uuid));
  }
  }


  void OnSetMemberAvailable(const RawAddress& bd_addr, int group_id) override {
  void OnSetMemberAvailable(const RawAddress& bd_addr, int group_id) override {
@@ -157,7 +158,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
      env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V");
      env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V");


  method_onDeviceAvailable =
  method_onDeviceAvailable =
      env->GetMethodID(clazz, "onDeviceAvailable", "([BIIJJ)V");
      env->GetMethodID(clazz, "onDeviceAvailable", "([BIIIJJ)V");


  method_onSetMemberAvailable =
  method_onSetMemberAvailable =
      env->GetMethodID(clazz, "onSetMemberAvailable", "([BI)V");
      env->GetMethodID(clazz, "onSetMemberAvailable", "([BI)V");
+6 −0
Original line number Original line Diff line number Diff line
@@ -741,6 +741,9 @@ public class BassClientService extends ProfileService {
                    BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
                    BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
            return;
            return;
        }
        }
        if (stateMachine.hasPendingSourceOperation()) {
            throw new IllegalStateException("addSource: source operation already pending");
        }
        if (!hasRoomForBroadcastSourceAddition(sink)) {
        if (!hasRoomForBroadcastSourceAddition(sink)) {
            log("addSource: device has no room");
            log("addSource: device has no room");
            mCallbacks.notifySourceAddFailed(sink, sourceMetadata,
            mCallbacks.notifySourceAddFailed(sink, sourceMetadata,
@@ -784,6 +787,9 @@ public class BassClientService extends ProfileService {
                    BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
                    BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
            return;
            return;
        }
        }
        if (stateMachine.hasPendingSourceOperation()) {
            throw new IllegalStateException("modifySource: source operation already pending");
        }
        Message message = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);
        Message message = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);
        message.arg1 = sourceId;
        message.arg1 = sourceId;
        message.obj = updatedMetadata;
        message.obj = updatedMetadata;
+23 −1
Original line number Original line Diff line number Diff line
@@ -245,6 +245,10 @@ public class BassClientStateMachine extends StateMachine {
        mCurrentMetadata.clear();
        mCurrentMetadata.clear();
    }
    }


    Boolean hasPendingSourceOperation() {
        return mPendingMetadata != null;
    }

    BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) {
    BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) {
        return mCurrentMetadata.getOrDefault(sourceId, null);
        return mCurrentMetadata.getOrDefault(sourceId, null);
    }
    }
@@ -992,6 +996,16 @@ public class BassClientStateMachine extends StateMachine {
            } else {
            } else {
                broadcastConnectionState(
                broadcastConnectionState(
                        mDevice, mLastConnectionState, BluetoothProfile.STATE_DISCONNECTED);
                        mDevice, mLastConnectionState, BluetoothProfile.STATE_DISCONNECTED);
                if (mLastConnectionState != BluetoothProfile.STATE_DISCONNECTED) {
                    // Reconnect in background if not disallowed by the service
                    if (mService.okToConnect(mDevice)) {
                        mBluetoothGatt = mDevice.connectGatt(mService, true,
                                mGattCallback, BluetoothDevice.TRANSPORT_LE,
                                (BluetoothDevice.PHY_LE_1M_MASK
                                        | BluetoothDevice.PHY_LE_2M_MASK
                                        | BluetoothDevice.PHY_LE_CODED_MASK), null);
                    }
                }
            }
            }
        }
        }


@@ -1028,7 +1042,15 @@ public class BassClientStateMachine extends StateMachine {
                    }
                    }
                    break;
                    break;
                case DISCONNECT:
                case DISCONNECT:
                    Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice);
                    // Disconnect if there's an ongoing background connection
                    if (mBluetoothGatt != null) {
                        log("Cancelling the background connection to " + mDevice);
                        mBluetoothGatt.disconnect();
                        mBluetoothGatt.close();
                        mBluetoothGatt = null;
                    } else {
                        Log.d(TAG, "Disconnected: DISCONNECT ignored: " + mDevice);
                    }
                    break;
                    break;
                case CONNECTION_STATE_CHANGED:
                case CONNECTION_STATE_CHANGED:
                    int state = (int) message.obj;
                    int state = (int) message.obj;
+2 −1
Original line number Original line Diff line number Diff line
@@ -149,13 +149,14 @@ public class CsipSetCoordinatorNativeInterface {
    /** Device availability */
    /** Device availability */
    @VisibleForTesting
    @VisibleForTesting
    public void onDeviceAvailable(
    public void onDeviceAvailable(
            byte[] address, int groupId, int groupSize, long uuidLsb, long uuidMsb) {
            byte[] address, int groupId, int groupSize, int rank, long uuidLsb, long uuidMsb) {
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(
        CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(
                CsipSetCoordinatorStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
                CsipSetCoordinatorStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        event.device = getDevice(address);
        event.device = getDevice(address);
        event.valueInt1 = groupId;
        event.valueInt1 = groupId;
        event.valueInt2 = groupSize;
        event.valueInt2 = groupSize;
        event.valueInt3 = rank;
        event.valueUuid1 = uuid;
        event.valueUuid1 = uuid;


        if (DBG) {
        if (DBG) {
+47 −13
Original line number Original line Diff line number Diff line
@@ -52,11 +52,9 @@ import com.android.modules.utils.SynchronousResultReceiver;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
@@ -87,7 +85,8 @@ public class CsipSetCoordinatorService extends ProfileService {
            new HashMap<>();
            new HashMap<>();


    private final Map<Integer, ParcelUuid> mGroupIdToUuidMap = new HashMap<>();
    private final Map<Integer, ParcelUuid> mGroupIdToUuidMap = new HashMap<>();
    private final Map<BluetoothDevice, Set<Integer>> mDeviceGroupIdMap = new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, Map<Integer, Integer>> mDeviceGroupIdRankMap =
            new ConcurrentHashMap<>();
    private final Map<Integer, Integer> mGroupIdToGroupSize = new HashMap<>();
    private final Map<Integer, Integer> mGroupIdToGroupSize = new HashMap<>();
    private final Map<ParcelUuid, Map<Executor, IBluetoothCsipSetCoordinatorCallback>> mCallbacks =
    private final Map<ParcelUuid, Map<Executor, IBluetoothCsipSetCoordinatorCallback>> mCallbacks =
            new HashMap<>();
            new HashMap<>();
@@ -201,7 +200,7 @@ public class CsipSetCoordinatorService extends ProfileService {
            }
            }
        }
        }


        mDeviceGroupIdMap.clear();
        mDeviceGroupIdRankMap.clear();
        mCallbacks.clear();
        mCallbacks.clear();
        mGroupIdToGroupSize.clear();
        mGroupIdToGroupSize.clear();
        mGroupIdToUuidMap.clear();
        mGroupIdToUuidMap.clear();
@@ -554,6 +553,17 @@ public class CsipSetCoordinatorService extends ProfileService {
        }
        }
    }
    }


    /**
     * Check whether a given group is currently locked.
     * @param groupId unique group identifier
     * @return true if group is currently locked, otherwise false.
     *
     * @hide
     */
    public boolean isGroupLocked(int groupId) {
        return mLocks.containsKey(groupId);
    }

    /**
    /**
     * Get collection of group IDs for a given UUID
     * Get collection of group IDs for a given UUID
     * @param uuid
     * @param uuid
@@ -573,13 +583,37 @@ public class CsipSetCoordinatorService extends ProfileService {
     * @return map of group id and related uuids.
     * @return map of group id and related uuids.
     */
     */
    public Map<Integer, ParcelUuid> getGroupUuidMapByDevice(BluetoothDevice device) {
    public Map<Integer, ParcelUuid> getGroupUuidMapByDevice(BluetoothDevice device) {
        Set<Integer> device_groups = mDeviceGroupIdMap.getOrDefault(device, new HashSet<>());
        Map<Integer, Integer> device_groups =
                mDeviceGroupIdRankMap.getOrDefault(device, new HashMap<>());
        return mGroupIdToUuidMap.entrySet()
        return mGroupIdToUuidMap.entrySet()
                .stream()
                .stream()
                .filter(e -> device_groups.contains(e.getKey()))
                .filter(e -> device_groups.containsKey(e.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
    }


    /**
     * Get grouped devices
     * @param groupId group ID
     * @return related list of devices sorted from the lowest to the highest rank value.
     */
    public @NonNull List<BluetoothDevice> getGroupDevicesOrdered(int groupId) {
        final Map<BluetoothDevice, Integer> deviceRankMap = new HashMap();
        for (Map.Entry<BluetoothDevice, ?> entry : mDeviceGroupIdRankMap.entrySet()) {
            Map<Integer, Integer> rankMap = (Map<Integer, Integer>) entry.getValue();
            BluetoothDevice device = entry.getKey();
            if (rankMap.containsKey(groupId)) {
                deviceRankMap.put(device, rankMap.get(groupId));
            }
        }

        // Return device list sorted by descending rank order
        return deviceRankMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .map(e -> e.getKey())
                .collect(Collectors.toList());
    }

    /**
    /**
     * Get group desired size
     * Get group desired size
     * @param groupId group ID
     * @param groupId group ID
@@ -590,18 +624,18 @@ public class CsipSetCoordinatorService extends ProfileService {
                IBluetoothCsipSetCoordinator.CSIS_GROUP_SIZE_UNKNOWN);
                IBluetoothCsipSetCoordinator.CSIS_GROUP_SIZE_UNKNOWN);
    }
    }


    private void handleDeviceAvailable(BluetoothDevice device, int groupId, UUID uuid) {
    private void handleDeviceAvailable(BluetoothDevice device, int groupId, int rank, UUID uuid) {
        ParcelUuid parcel_uuid = new ParcelUuid(uuid);
        ParcelUuid parcel_uuid = new ParcelUuid(uuid);
        if (!getAllGroupIds(parcel_uuid).contains(groupId)) {
        if (!getAllGroupIds(parcel_uuid).contains(groupId)) {
            mGroupIdToUuidMap.put(groupId, parcel_uuid);
            mGroupIdToUuidMap.put(groupId, parcel_uuid);
        }
        }


        if (!mDeviceGroupIdMap.containsKey(device)) {
        if (!mDeviceGroupIdRankMap.containsKey(device)) {
            mDeviceGroupIdMap.put(device, new HashSet<Integer>());
            mDeviceGroupIdRankMap.put(device, new HashMap<Integer, Integer>());
        }
        }


        Set<Integer> all_device_groups = mDeviceGroupIdMap.get(device);
        Map<Integer, Integer> all_device_groups = mDeviceGroupIdRankMap.get(device);
        all_device_groups.add(groupId);
        all_device_groups.put(groupId, rank);
    }
    }


    private void executeCallback(Executor exec, IBluetoothCsipSetCoordinatorCallback callback,
    private void executeCallback(Executor exec, IBluetoothCsipSetCoordinatorCallback callback,
@@ -700,7 +734,7 @@ public class CsipSetCoordinatorService extends ProfileService {
            intent.putExtra(
            intent.putExtra(
                    BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_TYPE_UUID, stackEvent.valueUuid1);
                    BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_TYPE_UUID, stackEvent.valueUuid1);


            handleDeviceAvailable(device, groupId, stackEvent.valueUuid1);
            handleDeviceAvailable(device, groupId, stackEvent.valueInt3, stackEvent.valueUuid1);
        } else if (stackEvent.type
        } else if (stackEvent.type
                == CsipSetCoordinatorStackEvent.EVENT_TYPE_SET_MEMBER_AVAILABLE) {
                == CsipSetCoordinatorStackEvent.EVENT_TYPE_SET_MEMBER_AVAILABLE) {
            Objects.requireNonNull(device, "Device should never be null, event: " + stackEvent);
            Objects.requireNonNull(device, "Device should never be null, event: " + stackEvent);
@@ -808,7 +842,7 @@ public class CsipSetCoordinatorService extends ProfileService {
            return;
            return;
        }
        }


        mDeviceGroupIdMap.remove(device);
        mDeviceGroupIdRankMap.remove(device);


        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
            CsipSetCoordinatorStateMachine sm = mStateMachines.get(device);
            CsipSetCoordinatorStateMachine sm = mStateMachines.get(device);
Loading