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

Commit fd9d3b67 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Improve recovery after state machine timeout

When LeAudio detect state machine timeout during stream creation,
audio device group is disconnected.
With this patch, we will try to reconnect to such device using direct
connect for 30 sec and later fallback to default background reconnection
mode.

Bug: 277414152
Test: atest BluetoothInstrumentationTests
Tag: #feature
Change-Id: I5af2e78bfe6626187fe2ace1f268c9a52015aff1
parent 10e396c9
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -1123,6 +1123,7 @@ class LeAudioClientImpl : public LeAudioClient {
        Disconnect(address);
        [[fallthrough]];
      case DeviceConnectState::DISCONNECTING:
      case DeviceConnectState::DISCONNECTING_AND_RECOVER:
        /* Remove device from the background connect if it is there */
        BTA_GATTC_CancelOpen(gatt_if_, address, false);
        /* Device is disconnecting, just mark it shall be removed after all. */
@@ -1397,6 +1398,7 @@ class LeAudioClientImpl : public LeAudioClient {
        return;
      case DeviceConnectState::DISCONNECTED:
      case DeviceConnectState::DISCONNECTING:
      case DeviceConnectState::DISCONNECTING_AND_RECOVER:
      case DeviceConnectState::CONNECTING_AUTOCONNECT:
      case DeviceConnectState::PENDING_REMOVAL:
      case DeviceConnectState::REMOVING:
@@ -1427,6 +1429,8 @@ class LeAudioClientImpl : public LeAudioClient {
    /* Remote in bad state, force ACL Disconnection. */
    if (acl_force_disconnect) {
      leAudioDevice->DisconnectAcl();
      leAudioDevice->SetConnectionState(
          DeviceConnectState::DISCONNECTING_AND_RECOVER);
    }
  }

@@ -2017,6 +2021,21 @@ class LeAudioClientImpl : public LeAudioClient {
      leAudioDevices_.Remove(address);
      return;
    }

    if (leAudioDevice->GetConnectionState() ==
        DeviceConnectState::DISCONNECTING_AND_RECOVER) {
      /* We are back after disconnecting device which was in a bad state.
       * lets try to reconnected - 30 sec with direct connect and later fallback
       * to default background reconnection mode
       */
      LOG_INFO("Reconnecting to %s after timeout on state machine.",
               ADDRESS_TO_LOGGABLE_CSTR(address));
      leAudioDevice->SetConnectionState(
          DeviceConnectState::CONNECTING_AUTOCONNECT);
      BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
      return;
    }

    /* Attempt background re-connect if disconnect was not intended locally
     * or if autoconnect is set and device got disconnected because of some
     * issues
+3 −0
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@ std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state) {
    case DeviceConnectState::DISCONNECTING:
      char_value_ = "DISCONNECTING";
      break;
    case DeviceConnectState::DISCONNECTING_AND_RECOVER:
      char_value_ = "DISCONNECTING_AND_RECOVER";
      break;
    case DeviceConnectState::PENDING_REMOVAL:
      char_value_ = "PENDING_REMOVAL";
      break;
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ enum class DeviceConnectState : uint8_t {
  REMOVING,
  /* Disconnecting */
  DISCONNECTING,
  /* Disconnecting for recover - after that we want direct connect to be
     initiated */
  DISCONNECTING_AND_RECOVER,
  /* Device will be removed after scheduled action is finished: One of such
   * action is taking Stream to IDLE
   */
+4 −0
Original line number Diff line number Diff line
@@ -4643,6 +4643,10 @@ TEST_F(UnicastTest, SpeakerStreamingTimeout) {
  // Verify Data transfer on one audio source cis
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);

  // Do not accept direct connect, but expect it to arrive.
  ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
      .WillByDefault(Return());

  state_machine_callbacks_->OnStateTransitionTimeout(group_id);

  /* No assigned cises should remain when transition remains in IDLE state */