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

Commit 0ec4a091 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "leaudio: Prevent from infinite loop on additng to background connect"

parents be975c70 52e2f6d0
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -418,8 +418,9 @@ static void bta_gattc_init_bk_conn(const tBTA_GATTC_API_OPEN* p_data,
                    p_data->connection_type, p_data->transport, false)) {
                    p_data->connection_type, p_data->transport, false)) {
    LOG_ERROR("Unable to connect to remote bd_addr=%s",
    LOG_ERROR("Unable to connect to remote bd_addr=%s",
              ADDRESS_TO_LOGGABLE_CSTR(p_data->remote_bda));
              ADDRESS_TO_LOGGABLE_CSTR(p_data->remote_bda));
    bta_gattc_send_open_cback(p_clreg, GATT_ERROR, p_data->remote_bda,
    bta_gattc_send_open_cback(p_clreg, GATT_ILLEGAL_PARAMETER,
                              GATT_INVALID_CONN_ID, BT_TRANSPORT_LE, 0);
                              p_data->remote_bda, GATT_INVALID_CONN_ID,
                              BT_TRANSPORT_LE, 0);
    return;
    return;
  }
  }


+6 −5
Original line number Original line Diff line number Diff line
@@ -1897,9 +1897,10 @@ class LeAudioClientImpl : public LeAudioClient {


    if (status != GATT_SUCCESS) {
    if (status != GATT_SUCCESS) {
      /* autoconnect connection failed, that's ok */
      /* autoconnect connection failed, that's ok */
      if (leAudioDevice->GetConnectionState() ==
      if (status != GATT_ILLEGAL_PARAMETER &&
          (leAudioDevice->GetConnectionState() ==
               DeviceConnectState::CONNECTING_AUTOCONNECT ||
               DeviceConnectState::CONNECTING_AUTOCONNECT ||
          leAudioDevice->autoconnect_flag_) {
           leAudioDevice->autoconnect_flag_)) {
        LOG_INFO("Device not available now, do background connect.");
        LOG_INFO("Device not available now, do background connect.");
        leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
        leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
        AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
        AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
@@ -1908,8 +1909,8 @@ class LeAudioClientImpl : public LeAudioClient {


      leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
      leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);


      LOG(ERROR) << "Failed to connect to LeAudio leAudioDevice, status: "
      LOG_ERROR("Failed to connect to LeAudio leAudioDevice, status: 0x%02x",
                 << +status;
                status);
      callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
      callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
      le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
      le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
          leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
          leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
+130 −0
Original line number Original line Diff line number Diff line
@@ -2615,6 +2615,136 @@ TEST_F(UnicastTest, ConnectTwoEarbudsCsisGroupUnknownAtConnect) {
  DisconnectLeAudio(test_address1, 2);
  DisconnectLeAudio(test_address1, 2);
}
}


TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) {
  // Prepare two devices
  uint8_t group_size = 2;
  uint8_t group_id = 2;

  /* Prepare  mock to not inject connect event so the device can stay in
   * CONNECTING state*/
  ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
      .WillByDefault(DoAll(Return()));

  const RawAddress test_address0 = GetTestAddress(0);
  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
      codec_spec_conf::kLeAudioLocationFrontLeft, 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_cnt*/
      group_size, 1);

  const RawAddress test_address1 = GetTestAddress(1);
  SetSampleDatabaseEarbudsValid(
      2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
      codec_spec_conf::kLeAudioLocationFrontRight, 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_cnt*/
      group_size, 2);

  // Load devices from the storage when storage API is called
  bool autoconnect = true;

  /* Common storage values */
  std::vector<uint8_t> handles;
  LeAudioClient::GetHandlesForStorage(test_address0, handles);

  std::vector<uint8_t> ases;
  LeAudioClient::GetAsesForStorage(test_address0, ases);

  std::vector<uint8_t> src_pacs;
  LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);

  std::vector<uint8_t> snk_pacs;
  LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);

  EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
    do_in_main_thread(
        FROM_HERE,
        base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
                   codec_spec_conf::kLeAudioLocationFrontLeft,
                   codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
                   std::move(handles), std::move(snk_pacs), std::move(src_pacs),
                   std::move(ases)));
    do_in_main_thread(
        FROM_HERE,
        base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
                   codec_spec_conf::kLeAudioLocationFrontRight,
                   codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
                   std::move(handles), std::move(snk_pacs), std::move(src_pacs),
                   std::move(ases)));
  });

  // Expect stored device0 to connect automatically (first directed connection )
  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
      .Times(1);

  // Expect stored device1 to connect automatically (first direct connection)
  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
      .Times(1);

  ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
      .WillByDefault(DoAll(Return(true)));
  ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
      .WillByDefault(DoAll(Return(true)));

  ON_CALL(mock_groups_module_, GetGroupId(_, _))
      .WillByDefault(DoAll(Return(group_id)));

  ON_CALL(mock_btm_interface_,
          GetSecurityFlagsByTransport(test_address0, NotNull(), _))
      .WillByDefault(
          DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));

  std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
      framework_encode_preference;

  // Initialize
  BtaAppRegisterCallback app_register_callback;
  ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
      .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
                           SaveArg<1>(&app_register_callback)));
  LeAudioClient::Initialize(
      &mock_audio_hal_client_callbacks_,
      base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
                 &mock_storage_load),
      base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
                 &mock_hal_2_1_verifier),
      framework_encode_preference);
  if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);

  // We need to wait for the storage callback before verifying stuff
  SyncOnMainLoop();
  ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);

  // Simulate connect parameters are invalid and phone does not fallback
  // to background connect.
  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address0,
                   BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
      .Times(0);

  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address1,
                   BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
      .Times(0);

  // Devices not found
  InjectConnectedEvent(test_address0, 0, GATT_ILLEGAL_PARAMETER);
  InjectConnectedEvent(test_address1, 0, GATT_ILLEGAL_PARAMETER);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}

TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
  // Prepare two devices
  // Prepare two devices
  uint8_t group_size = 2;
  uint8_t group_size = 2;
+6 −0
Original line number Original line Diff line number Diff line
@@ -166,6 +166,9 @@ bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) {
  if (p_dev_rec == NULL || (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == 0)
  if (p_dev_rec == NULL || (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == 0)
    return true;
    return true;


  LOG_WARN("%s, device type not BLE: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(address),
           p_dev_rec->device_type);

  // bonded device with identity address known
  // bonded device with identity address known
  if (!p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
  if (!p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
    return true;
    return true;
@@ -177,6 +180,9 @@ bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) {
    return true;
    return true;
  }
  }


  LOG_WARN("%s, the address type is 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(address),
           p_dev_rec->ble.AddressType());

  // Only Resolvable Private Address (RPA) is known, we don't allow it into
  // Only Resolvable Private Address (RPA) is known, we don't allow it into
  // the background connection procedure.
  // the background connection procedure.
  return false;
  return false;