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

Commit 0ab4a727 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Add way to handle invalid CSIS member device

Preparation for health base action mechanism.

Bug: 279233743
Tag: #feature
Test: atest bluetooth_le_audio_client_test
Change-Id: Ic0b5cdabe04d4b7a6dcb2b45b97dc64420ba0fca
parent e705b689
Loading
Loading
Loading
Loading
+48 −2
Original line number Diff line number Diff line
@@ -2219,6 +2219,47 @@ class LeAudioClientImpl : public LeAudioClient {
    );
  }

  void checkIfGroupMember(RawAddress address) {
    LOG_INFO("checking being a group member: %s",
             ADDRESS_TO_LOGGABLE_CSTR(address));
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);

    if (leAudioDevice == nullptr) {
      LOG_WARN("Device %s, probably removed",
               ADDRESS_TO_LOGGABLE_CSTR(address));
      return;
    }

    if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
      LOG_ERROR("device %s not a valid group member",
                ADDRESS_TO_LOGGABLE_CSTR(address));
      DisconnectDevice(leAudioDevice);
      return;
    }
  }

  /* This is called, when CSIS native module is about to add device to the
   * group once the CSIS service will be verified on the remote side.
   * After some time (kCsisGroupMemberDelayMs)  a checkIfGroupMember will be
   * called and will verify if the remote device has a group_id properly set.
   * if not, it means there is something wrong with CSIS service on the remote
   * side.
   */
  void scheduleGuardForCsisAdd(RawAddress& address) {
    LOG_INFO("Schedule reconnecting to %s after timeout on state machine.",
             ADDRESS_TO_LOGGABLE_CSTR(address));
    do_in_main_thread_delayed(
        FROM_HERE,
        base::BindOnce(&LeAudioClientImpl::checkIfGroupMember,
                       base::Unretained(this), address),
#if BASE_VER < 931007
        base::TimeDelta::FromMilliseconds(kCsisGroupMemberDelayMs)
#else
        base::Milliseconds(kCsisGroupMemberDelayMs)
#endif
    );
  }

  void OnGattDisconnected(uint16_t conn_id, tGATT_IF client_if,
                          RawAddress address, tGATT_DISCONN_REASON reason) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
@@ -2795,11 +2836,15 @@ class LeAudioClientImpl : public LeAudioClient {

    /* CSIS will trigger adding to group */
    if (leAudioDevice->csis_member_) {
      LOG(INFO) << __func__ << " waiting for CSIS to create group for device "
                << ADDRESS_TO_LOGGABLE_STR(leAudioDevice->address_);
      LOG_INFO(" %s,  waiting for CSIS to create group for device ",
               ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
      scheduleGuardForCsisAdd(leAudioDevice->address_);
      return;
    }

    LOG_INFO("%s Not a CSIS member. Create group by our own",
             ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));

    /* If there is no Csis just add device by our own */
    DeviceGroups::Get()->AddDevice(leAudioDevice->address_,
                                   le_audio::uuid::kCapServiceUuid);
@@ -5250,6 +5295,7 @@ class LeAudioClientImpl : public LeAudioClient {
  static constexpr uint64_t kGroupConnectedWatchDelayMs = 3000;
  static constexpr uint64_t kRecoveryReconnectDelayMs = 2000;
  static constexpr uint64_t kAutoConnectAfterOwnDisconnectDelayMs = 1000;
  static constexpr uint64_t kCsisGroupMemberDelayMs = 5000;

  static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
      "persist.bluetooth.leaudio.notify.idle.during.call";
+31 −0
Original line number Diff line number Diff line
@@ -2532,6 +2532,37 @@ TEST_F(UnicastTest, ConnectOneEarbudNoCsis) {
  ConnectLeAudio(test_address0);
}

TEST_F(UnicastTest, ConnectOneEarbudWithInvalidCsis) {
  const RawAddress test_address0 = GetTestAddress(0);
  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
      codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
      default_channel_cnt, 0x0004,
      /* source sample freq 16khz */ true, /*add_csis*/
      true,                                /*add_cas*/
      true,                                /*add_pacs*/
      default_ase_cnt /*add_ascs*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);

  // Report working CSIS
  ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
      .WillByDefault(Return(true));

  /* Make sure Group has not knowledge about the device */
  ON_CALL(mock_groups_module_, GetGroupId(_, _))
      .WillByDefault([](const RawAddress& addr, bluetooth::Uuid uuid) {
        return bluetooth::groups::kGroupUnknown;
      });

  ConnectLeAudio(test_address0);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
}

TEST_F(UnicastTest, ConnectDisconnectOneEarbud) {
  const RawAddress test_address0 = GetTestAddress(0);
  SetSampleDatabaseEarbudsValid(1, test_address0,