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

Commit bec27134 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk Committed by Jakub Pawlowski
Browse files

le_audio: Implement active device handling

This is needed to set LE audio device representig this group as active.

Tag: #feature
Test: Set LE audio device as active
Sponsor: jpawlowski@
Bug: 150670922
Merged-In: I09164219027c2c31f55912a1687be1d654430c2f
Change-Id: I09164219027c2c31f55912a1687be1d654430c2f
parent 48e500e3
Loading
Loading
Loading
Loading
+8 −16
Original line number Original line Diff line number Diff line
@@ -82,27 +82,19 @@ class LeAudioClientCallbacksImpl : public LeAudioClientCallbacks {
                                 (jint)group_flags);
                                 (jint)group_flags);
  }
  }


  void OnAudioConf(const RawAddress& bd_addr, uint8_t direction,
  void OnAudioConf(uint8_t direction, int group_id,
                   uint8_t group_id, uint32_t sink_audio_location,
                   uint32_t sink_audio_location, uint32_t source_audio_location,
                   uint32_t source_audio_location) override {
                   uint16_t avail_cont) override {
    LOG(INFO) << __func__;
    LOG(INFO) << __func__;


    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;


    ScopedLocalRef<jbyteArray> addr(
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioConf,
        sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
                                 (jint)direction, (jint)group_id,
    if (!addr.get()) {
                                 (jint)sink_audio_location,
      LOG(ERROR) << "Failed to new jbyteArray bd addr for group status";
                                 (jint)source_audio_location, (jint)avail_cont);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(
        mCallbacksObj, method_onAudioConf, (jint)direction, (jint)group_id,
        (jint)sink_audio_location, (jint)source_audio_location, addr.get());
  }
  }


  void OnSetMemberAvailable(const RawAddress& bd_addr,
  void OnSetMemberAvailable(const RawAddress& bd_addr,
@@ -131,7 +123,7 @@ static LeAudioClientCallbacksImpl sLeAudioClientCallbacks;


static void classInitNative(JNIEnv* env, jclass clazz) {
static void classInitNative(JNIEnv* env, jclass clazz) {
  method_onGroupStatus = env->GetMethodID(clazz, "onGroupStatus", "(III)V");
  method_onGroupStatus = env->GetMethodID(clazz, "onGroupStatus", "(III)V");
  method_onAudioConf = env->GetMethodID(clazz, "onAudioConf", "(IIII[B)V");
  method_onAudioConf = env->GetMethodID(clazz, "onAudioConf", "(IIIII)V");
  method_onConnectionStateChanged =
  method_onConnectionStateChanged =
      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
  method_onSetMemberAvailable =
  method_onSetMemberAvailable =
+15 −2
Original line number Original line Diff line number Diff line
@@ -127,15 +127,28 @@ public class LeAudioNativeInterface {
        sendMessageToService(event);
        sendMessageToService(event);
    }
    }


    private void onGroupNodeStatus(byte[] address, int groupId, int nodeStatus) {
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED);
        event.valueInt1 = groupId;
        event.valueInt2 = nodeStatus;
        event.device = getDevice(address);

        if (DBG) {
            Log.d(TAG, "onGroupNodeStatus: " + event);
        }
        sendMessageToService(event);
    }

    private void onAudioConf(int direction, int groupId, int sinkAudioLocation,
    private void onAudioConf(int direction, int groupId, int sinkAudioLocation,
                             int sourceAudioLocation, byte[] address) {
                             int sourceAudioLocation, int availableContexts) {
        LeAudioStackEvent event =
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED);
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED);
        event.valueInt1 = direction;
        event.valueInt1 = direction;
        event.valueInt2 = groupId;
        event.valueInt2 = groupId;
        event.valueInt3 = sinkAudioLocation;
        event.valueInt3 = sinkAudioLocation;
        event.valueInt4 = sourceAudioLocation;
        event.valueInt4 = sourceAudioLocation;
        event.device = getDevice(address);
        event.valueInt5 = availableContexts;


        if (DBG) {
        if (DBG) {
            Log.d(TAG, "onAudioConf: " + event);
            Log.d(TAG, "onAudioConf: " + event);
+309 −23
Original line number Original line Diff line number Diff line
@@ -60,20 +60,52 @@ public class LeAudioService extends ProfileService {
    private static final int MAX_LE_AUDIO_STATE_MACHINES = 10;
    private static final int MAX_LE_AUDIO_STATE_MACHINES = 10;
    private static LeAudioService sLeAudioService;
    private static LeAudioService sLeAudioService;


    /**
     * Indicates group audio support for input direction
     */
    private static final int AUDIO_DIRECTION_INPUT_BIT = 0x01;

    /**
     * Indicates group audio support for output direction
     */
    private static final int AUDIO_DIRECTION_OUTPUT_BIT = 0x02;

    /*
     * Indicates no active contexts
     */
    private static final int ACTIVE_CONTEXTS_NONE = 0;

    private AdapterService mAdapterService;
    private AdapterService mAdapterService;
    private DatabaseManager mDatabaseManager;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
    private HandlerThread mStateMachinesThread;
    private BluetoothDevice mPreviousAudioDevice;
    private BluetoothDevice mPreviousAudioOutDevice;
    private BluetoothDevice mPreviousAudioInDevice;
    ServiceFactory mServiceFactory = new ServiceFactory();
    ServiceFactory mServiceFactory = new ServiceFactory();


    LeAudioNativeInterface mLeAudioNativeInterface;
    LeAudioNativeInterface mLeAudioNativeInterface;
    AudioManager mAudioManager;
    AudioManager mAudioManager;


    private class LeAudioGroupDescriptor {
        LeAudioGroupDescriptor() {
            mIsConnected = false;
            mIsActive = false;
            mActiveContexts = ACTIVE_CONTEXTS_NONE;
        }

        public Boolean mIsConnected;
        public Boolean mIsActive;
        public Integer mActiveContexts;
    }

    private final Map<Integer, LeAudioGroupDescriptor> mGroupDescriptors = new HashMap<>();
    private final Map<BluetoothDevice, LeAudioStateMachine> mStateMachines = new HashMap<>();
    private final Map<BluetoothDevice, LeAudioStateMachine> mStateMachines = new HashMap<>();


    private final Map<BluetoothDevice, Integer> mDeviceGroupIdMap = new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, Integer> mDeviceGroupIdMap = new ConcurrentHashMap<>();
    private final Map<Integer, Boolean> mGroupIdConnectedMap = new HashMap<>();
    private int mActiveDeviceGroupId = LE_AUDIO_GROUP_ID_INVALID;
    private int mActiveDeviceGroupId = LE_AUDIO_GROUP_ID_INVALID;
    private final int mContextSupportingInputAudio =
            BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION;
    private final int mContextSupportingOutputAudio = BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION |
            BluetoothLeAudio.CONTEXT_TYPE_MEDIA;


    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
@@ -111,7 +143,7 @@ public class LeAudioService extends ProfileService {
        mStateMachinesThread.start();
        mStateMachinesThread.start();


        mDeviceGroupIdMap.clear();
        mDeviceGroupIdMap.clear();
        mGroupIdConnectedMap.clear();
        mGroupDescriptors.clear();


        // Setup broadcast receivers
        // Setup broadcast receivers
        IntentFilter filter = new IntentFilter();
        IntentFilter filter = new IntentFilter();
@@ -162,7 +194,7 @@ public class LeAudioService extends ProfileService {
        }
        }


        mDeviceGroupIdMap.clear();
        mDeviceGroupIdMap.clear();
        mGroupIdConnectedMap.clear();
        mGroupDescriptors.clear();


        if (mStateMachinesThread != null) {
        if (mStateMachinesThread != null) {
            mStateMachinesThread.quitSafely();
            mStateMachinesThread.quitSafely();
@@ -298,6 +330,9 @@ public class LeAudioService extends ProfileService {
                }
                }
            }
            }
        }
        }

        mGroupDescriptors.remove(groupId);

        return true;
        return true;
    }
    }


@@ -383,19 +418,176 @@ public class LeAudioService extends ProfileService {
    }
    }


    /**
    /**
     * Set the active device.
     * Get supported group audio direction from available context.
     *
     * @param activeContext bitset of active context to be matched with possible audio direction
     * support.
     * @return matched possible audio direction support masked bitset
     * {@link AUDIO_DIRECTION_INPUT_BIT} if input audio is supported
     * {@link AUDIO_DIRECTION_OUTPUT_BIT} if output audio is supported
     */
    private Integer getAudioDirectionsFromActiveContextsMap(Integer activeContexts) {
        Integer supportedAudioDirections = 0;

        if ((activeContexts & mContextSupportingInputAudio) != 0) {
          supportedAudioDirections |= AUDIO_DIRECTION_INPUT_BIT;
        }
        if ((activeContexts & mContextSupportingOutputAudio) != 0) {
          supportedAudioDirections |= AUDIO_DIRECTION_OUTPUT_BIT;
        }

        return supportedAudioDirections;
    }

    private BluetoothDevice getFirstConnectedDeviceFromGroup(Integer groupId) {
        if (groupId != LE_AUDIO_GROUP_ID_INVALID) {
            for(Map.Entry<BluetoothDevice, Integer> entry : mDeviceGroupIdMap.entrySet()) {
                if ((entry.getValue() == groupId) && (entry.getKey().isConnected())) {
                    return entry.getKey();
                }
            }
        }

        return null;
    }

    /**
     * Report the active devices change to the active device manager and the media framework.
     * @param groupId id of group which devices should be updated
     * @param newActiveContexts new active contexts for group of devices
     */
    private void updateActiveDevices(Integer groupId, Integer oldActiveContexts,
            Integer newActiveContexts) {
        LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(groupId);
        if (descriptor == null) {
            Log.w(TAG, "Invalid group id: " + String.valueOf(groupId));
            return;
        }

        BluetoothDevice device = getFirstConnectedDeviceFromGroup(groupId);

        Integer oldSupportedAudioDirections =
                getAudioDirectionsFromActiveContextsMap(oldActiveContexts);
        boolean oldSupportedByDeviceOutput = (oldSupportedAudioDirections
                & AUDIO_DIRECTION_OUTPUT_BIT) != 0;
        boolean oldSupportedByDeviceInput = (oldSupportedAudioDirections
                & AUDIO_DIRECTION_INPUT_BIT) != 0;

        Integer newSupportedAudioDirections =
                getAudioDirectionsFromActiveContextsMap(newActiveContexts);
        boolean newSupportedByDeviceOutput = (newSupportedAudioDirections
                & AUDIO_DIRECTION_OUTPUT_BIT) != 0;
        boolean newSupportedByDeviceInput = (newSupportedAudioDirections
                & AUDIO_DIRECTION_INPUT_BIT) != 0;

        /* Disconnect output:
         * - If active output device changed (to none or any)
         * - If device stops supporting output
         */
        boolean outActiveDeviceReplace = (mPreviousAudioOutDevice != null) &&
                !(device == mPreviousAudioOutDevice);
        if (outActiveDeviceReplace || (oldSupportedByDeviceOutput && !newSupportedByDeviceOutput)) {
            boolean suppressNoisyIntent =
                    (getConnectionState(mPreviousAudioOutDevice) ==
                    BluetoothProfile.STATE_CONNECTED);
            mAudioManager.setBluetoothLeAudioOutDeviceConnectionState(
                    mPreviousAudioOutDevice, BluetoothProfile.STATE_DISCONNECTED,
                    suppressNoisyIntent);
            mPreviousAudioOutDevice = null;
        }

        /* Connect output:
         * - If active output device changed
         * - If device starts support output
         */
        if ((outActiveDeviceReplace && (device != null)) ||
                (!oldSupportedByDeviceOutput && newSupportedByDeviceOutput)) {
            mAudioManager.setBluetoothLeAudioOutDeviceConnectionState(
                    device, BluetoothProfile.STATE_CONNECTED, true);
            mPreviousAudioOutDevice = device;
        }

        /* Disconnect input:
         * - If active input device changed (to none or any)
         * - If device stops supporting input
         */
        boolean inActiveDeviceReplace = (mPreviousAudioInDevice != null) &&
                !(device == mPreviousAudioInDevice);
        if (inActiveDeviceReplace || (oldSupportedByDeviceInput && !newSupportedByDeviceInput)) {
            mAudioManager.setBluetoothLeAudioInDeviceConnectionState(
                    mPreviousAudioInDevice, BluetoothProfile.STATE_DISCONNECTED);
            mPreviousAudioInDevice = null;
        }

        /* Connect input:
         * - If active input device changed
         * - If device starts support input
         */
        if ((inActiveDeviceReplace && (device != null)) ||
                (!oldSupportedByDeviceInput && newSupportedByDeviceInput)) {
            mAudioManager.setBluetoothLeAudioInDeviceConnectionState(
                   device, BluetoothProfile.STATE_CONNECTED);
            mPreviousAudioInDevice = device;
        }

        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        if ((mPreviousAudioInDevice == null) && (mPreviousAudioOutDevice == null)) {
            /* Device has to be unabigous, represented by empty BluetoothDevice */
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mPreviousAudioOutDevice);
        } else {
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        }
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
    }

    /**
     * Set the active device group.
     * @param groupId group Id to set active
     */
    private void setActiveDeviceGroup(BluetoothDevice device) {
        int groupId = LE_AUDIO_GROUP_ID_INVALID;

        if (device != null) {
            groupId = mDeviceGroupIdMap.getOrDefault(device, LE_AUDIO_GROUP_ID_INVALID);
        }

        if (DBG) {
            Log.d(TAG, "setActiveDeviceGroup = " + groupId + ", device: " + device);
        }

        if (groupId == mActiveDeviceGroupId) {
            Log.w(TAG, "group is already active");
            return;
        }

        mActiveDeviceGroupId = groupId;
    }

    /**
     * Set the active group represented by device.
     *
     *
     * @param device the new active device
     * @param device the new active device
     * @return true on success, otherwise false
     * @return true on success, otherwise false
     */
     */
    public boolean setActiveDevice(BluetoothDevice device) {
    public boolean setActiveDevice(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        if (DBG) {
        synchronized (mStateMachines) {
            Log.d(TAG, "setActiveDevice:" + device);
            /* Clear active group */
            if (device == null) {
                setActiveDeviceGroup(device);
                return true;
            }
            }

            if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
                Log.e(TAG, "setActiveDevice(" + device + "): failed because group device is not " +
                        "connected");
                return false;
                return false;
            }
            }
            setActiveDeviceGroup(device);
            return true;
        }
    }


    /**
    /**
     * Get the connected physical LeAudio devices that are active.
     * Get the connected physical LeAudio devices that are active.
@@ -407,12 +599,26 @@ public class LeAudioService extends ProfileService {
            Log.d(TAG, "getActiveDevices");
            Log.d(TAG, "getActiveDevices");
        }
        }
        ArrayList<BluetoothDevice> activeDevices = new ArrayList<>();
        ArrayList<BluetoothDevice> activeDevices = new ArrayList<>();
        synchronized (mStateMachines) {
            if (mActiveDeviceGroupId == LE_AUDIO_GROUP_ID_INVALID) {
                return activeDevices;
            }
            for (BluetoothDevice device : mDeviceGroupIdMap.keySet()) {
                if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
                    continue;
                }
                if (mDeviceGroupIdMap.get(device) == Integer.valueOf(mActiveDeviceGroupId)) {
                    activeDevices.add(device);
                }
            }
        }
        return activeDevices;
        return activeDevices;
    }
    }


    void messageFromNative(LeAudioStackEvent stackEvent) {
    void messageFromNative(LeAudioStackEvent stackEvent) {
        Log.d(TAG, "Message from native: " + stackEvent);
        Log.d(TAG, "Message from native: " + stackEvent);
        BluetoothDevice device = stackEvent.device;
        BluetoothDevice device = stackEvent.device;
        Intent intent = null;


        if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
        if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
        // Some events require device state machine
        // Some events require device state machine
@@ -437,32 +643,98 @@ public class LeAudioService extends ProfileService {
                sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent);
                sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent);
                return;
                return;
            }
            }
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED) {
            int group_id = stackEvent.valueInt1;
            int node_status = stackEvent.valueInt2;

            Objects.requireNonNull(stackEvent.device,
                    "Device should never be null, event: " + stackEvent);

            switch (node_status) {
                case LeAudioStackEvent.GROUP_NODE_ADDED:
                    mDeviceGroupIdMap.put(device, group_id);
                    mGroupDescriptors.put(group_id, new LeAudioGroupDescriptor());
                    break;
                case LeAudioStackEvent.GROUP_NODE_REMOVED:
                    mDeviceGroupIdMap.remove(device);
                    mGroupDescriptors.remove(group_id);
                    break;
                default:
                    break;
            }
            }


        // Some events do not require device state machine
            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
        if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED) {
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS, node_status);
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED) {
            int direction = stackEvent.valueInt1;
            int group_id = stackEvent.valueInt2;
            int snk_audio_location = stackEvent.valueInt3;
            int src_audio_location = stackEvent.valueInt4;
            int available_contexts = stackEvent.valueInt5;

            LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(group_id);
            if (descriptor != null) {
                if (descriptor.mIsActive) {
                    updateActiveDevices(group_id, descriptor.mActiveContexts, available_contexts);
                }
                descriptor.mActiveContexts = available_contexts;
            } else {
                Log.e(TAG, "no descriptors for group: " + group_id);
            }

            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONF_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_DIRECTION, direction);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SINK_LOCATION, snk_audio_location);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SOURCE_LOCATION, src_audio_location);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS, available_contexts);
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED) {
            int group_id = stackEvent.valueInt1;
            int group_id = stackEvent.valueInt1;
            int group_status = stackEvent.valueInt2;
            int group_status = stackEvent.valueInt2;
            int group_flags = stackEvent.valueInt3;


            // TODO: Handle Stream events
            switch (group_status) {
            switch (group_status) {
                case LeAudioStackEvent.GROUP_STATUS_IDLE:
                case LeAudioStackEvent.GROUP_STATUS_IDLE:
                case LeAudioStackEvent.GROUP_STATUS_RECONFIGURED:
                case LeAudioStackEvent.GROUP_STATUS_RECONFIGURED:
                case LeAudioStackEvent.GROUP_STATUS_DESTROYED:
                case LeAudioStackEvent.GROUP_STATUS_DESTROYED:
                case LeAudioStackEvent.GROUP_STATUS_SUSPENDED:
                case LeAudioStackEvent.GROUP_STATUS_SUSPENDED:
                    setActiveDevice(null);
                    // TODO: Get all devices with a group and Unassign? or they are already unasigned
                    // This event may come after removing all the nodes from a certain group but only that.
                    break;
                case LeAudioStackEvent.GROUP_STATUS_STREAMING:
                case LeAudioStackEvent.GROUP_STATUS_STREAMING:
                    BluetoothDevice streaming_device = getConnectedPeerDevices(group_id).get(0);
                    setActiveDevice(streaming_device);
                    break;
                    break;
                case LeAudioStackEvent.GROUP_STATUS_ACTIVE: {
                    LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(group_id);
                    if (descriptor != null) {
                        if (!descriptor.mIsActive) {
                            updateActiveDevices(group_id, ACTIVE_CONTEXTS_NONE,
                                    descriptor.mActiveContexts);
                            descriptor.mIsActive = true;
                        }
                    } else {
                        Log.e(TAG, "no descriptors for group: " + group_id);
                    }
                    break;
                }
                case LeAudioStackEvent.GROUP_STATUS_INACTIVE: {
                    LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(group_id);
                    if (descriptor != null) {
                        if (descriptor.mIsActive) {
                            updateActiveDevices(group_id, descriptor.mActiveContexts,
                                    ACTIVE_CONTEXTS_NONE);
                            descriptor.mIsActive = false;
                        }
                    } else {
                        Log.e(TAG, "no descriptors for group: " + group_id);
                    }
                    break;
                }
                default:
                default:
                    break;
                    break;
            }
            }


            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, group_status);
        }
        }
    }
    }


@@ -580,8 +852,16 @@ public class LeAudioService extends ProfileService {
                // MetricsLogger.logProfileConnectionEvent(
                // MetricsLogger.logProfileConnectionEvent(
                //         BluetoothMetricsProto.ProfileId.LE_AUDIO);
                //         BluetoothMetricsProto.ProfileId.LE_AUDIO);
            }
            }
            if (!mGroupIdConnectedMap.getOrDefault(myGroupId, false)) {

                mGroupIdConnectedMap.put(myGroupId, true);
            LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(myGroupId);
            if (descriptor != null) {
                descriptor.mIsConnected = true;
                /* HearingAid activates device after connection
                 * A2dp makes active device via activedevicemanager - connection intent
                 */
                setActiveDevice(device);
            } else {
                Log.e(TAG, "no descriptors for group: " + myGroupId);
            }
            }


            McpService mcpService = mServiceFactory.getMcpService();
            McpService mcpService = mServiceFactory.getMcpService();
@@ -592,7 +872,13 @@ public class LeAudioService extends ProfileService {
        if (fromState == BluetoothProfile.STATE_CONNECTED && getConnectedDevices().isEmpty()) {
        if (fromState == BluetoothProfile.STATE_CONNECTED && getConnectedDevices().isEmpty()) {
            setActiveDevice(null);
            setActiveDevice(null);
            int myGroupId = getGroupId(device);
            int myGroupId = getGroupId(device);
            mGroupIdConnectedMap.put(myGroupId, false);

            LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(myGroupId);
            if (descriptor != null) {
                descriptor.mIsConnected = true;
            } else {
                Log.e(TAG, "no descriptors for group: " + myGroupId);
            }
        }
        }
        // Check if the device is disconnected - if unbond, remove the state machine
        // Check if the device is disconnected - if unbond, remove the state machine
        if (toState == BluetoothProfile.STATE_DISCONNECTED) {
        if (toState == BluetoothProfile.STATE_DISCONNECTED) {
+39 −4

File changed.

Preview size limit exceeded, changes collapsed.