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

Commit 1d8c9fd5 authored by David Duarte's avatar David Duarte
Browse files

hearing_aid: Do a direct connection if another ear is connected

On connection, if another device from the set is connecting,
transform the background connection to a direct connection to allow
to scan more aggressively and connection as fast as possible.

On a peer disconnection, if another device from the set is still
connected issue a direct connection. If this direct connection fails
(after 30s) it will be transformed back into a background connection.

Bug: 308032317
Test: manual, open Wireshark and look at the LE Extended Create Connection
  Scan Interval + the time it takes on the UI when:
  - taking the HA out of the case
  - putting one HA back in the case and taking it out
  - putting one HA back in the case and wait 30 seconds
Change-Id: Ie4fd9885fbc57dd608a94f173c21d0a1130efa09
parent c0e70b78
Loading
Loading
Loading
Loading
+64 −5
Original line number Diff line number Diff line
@@ -160,6 +160,16 @@ class HearingDevices {
    return (iter == devices.end()) ? nullptr : &(*iter);
  }

  HearingDevice* FindOtherConnectedDeviceFromSet(const HearingDevice& device) {
    auto iter = std::find_if(
        devices.begin(), devices.end(), [&device](const HearingDevice& other) {
          return &device != &other && device.hi_sync_id == other.hi_sync_id &&
                 other.conn_id != 0;
        });

    return (iter == devices.end()) ? nullptr : &(*iter);
  }

  HearingDevice* FindByConnId(uint16_t conn_id) {
    auto iter = std::find_if(devices.begin(), devices.end(),
                             [&conn_id](const HearingDevice& device) {
@@ -468,14 +478,42 @@ class HearingAidImpl : public HearingAid {
        return;
      }

      LOG_INFO("Failed to connect to Hearing Aid device");
      if (hearingDevice->switch_to_background_connection_after_failure) {
        hearingDevice->connecting_actively = false;
        hearingDevice->switch_to_background_connection_after_failure = false;
        BTA_GATTC_Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
      } else {
        LOG_INFO("Failed to connect to Hearing Aid device, bda=%s",
                 ADDRESS_TO_LOGGABLE_CSTR(address));

        hearingDevices.Remove(address);
        callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
      }
      return;
    }

    hearingDevice->conn_id = conn_id;

    uint64_t hi_sync_id = hearingDevice->hi_sync_id;

    // If there a background connection to the other device of a pair, promote
    // it to a direct connection to scan more agressively for it
    if (hi_sync_id != 0) {
      for (auto& device : hearingDevices.devices) {
        if (device.hi_sync_id == hi_sync_id && device.conn_id == 0 &&
            !device.connecting_actively) {
          LOG_INFO(
              "Promoting device from the set from background to direct"
              "connection, bda=%s",
              ADDRESS_TO_LOGGABLE_CSTR(device.address));
          device.connecting_actively = true;
          device.switch_to_background_connection_after_failure = true;
          BTA_GATTC_Open(gatt_if, device.address, BTM_BLE_DIRECT_CONNECTION,
                         false);
        }
      }
    }

    /* We must update connection parameters one at a time, otherwise anchor
     * point (start of connection event) for two devices can be too close to
     * each other. Here, by setting min_ce_len=max_ce_len=X, we force controller
@@ -1765,10 +1803,31 @@ class HearingAidImpl : public HearingAid {

    DoDisconnectCleanUp(hearingDevice);

    HearingDevice* other_connected_device_from_set =
        hearingDevices.FindOtherConnectedDeviceFromSet(*hearingDevice);

    if (other_connected_device_from_set != nullptr) {
      LOG_INFO(
          "Another device from the set is still connected, issuing a direct "
          "connection, other_device_bda=%s",
          ADDRESS_TO_LOGGABLE_CSTR(other_connected_device_from_set->address));
    }

    // If another device from the pair is still connected, do a direct
    // connection to scan more aggressively and connect as fast as possible
    hearingDevice->connecting_actively =
        other_connected_device_from_set != nullptr;

    auto connection_type = hearingDevice->connecting_actively
                               ? BTM_BLE_DIRECT_CONNECTION
                               : BTM_BLE_BKG_CONNECT_ALLOW_LIST;

    hearingDevice->switch_to_background_connection_after_failure =
        connection_type == BTM_BLE_DIRECT_CONNECTION;

    // This is needed just for the first connection. After stack is restarted,
    // code that loads device will add them to acceptlist.
    BTA_GATTC_Open(gatt_if, hearingDevice->address,
                   BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
    BTA_GATTC_Open(gatt_if, hearingDevice->address, connection_type, false);

    callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda);

+5 −1
Original line number Diff line number Diff line
@@ -114,9 +114,11 @@ struct HearingDevice {
  bool service_changed_rcvd;

  /* we are making active attempt to connect to this device, 'direct connect'.
   * This is true only during initial phase of first connection. */
   */
  bool connecting_actively;

  bool switch_to_background_connection_after_failure;

  /* For two hearing aids, you must update their parameters one after another,
   * not simulteanously, to ensure start of connection events for both devices
   * are far from each other. This status tracks whether this device is waiting
@@ -176,6 +178,7 @@ struct HearingDevice {
        first_connection(false),
        service_changed_rcvd(false),
        connecting_actively(false),
        switch_to_background_connection_after_failure(false),
        connection_update_status(NONE),
        accepting_audio(false),
        conn_id(0),
@@ -202,6 +205,7 @@ struct HearingDevice {
        first_connection(first_connection),
        service_changed_rcvd(false),
        connecting_actively(first_connection),
        switch_to_background_connection_after_failure(false),
        connection_update_status(NONE),
        accepting_audio(false),
        conn_id(0),