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

Commit 69f0cc61 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Fix RemoveDevice just after Connection Timeout

When Connection Timeout occurs, Android does Direct Connect for 30
seconds.
If during this time user will Forget Device, the device will stay in
the controller allow list.

This patch fixes that.

Bug: 352673441
Test: atest bluetooth_le_audio_test
Flag: Exempt, regression test with unit test new unit tests added
Change-Id: Id383e73038b2ef43d4cdb19b83c3fbbf8a299fd7
parent b379e520
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -1468,10 +1468,14 @@ public:
        /* Device is disconnecting, just mark it shall be removed after all. */
        leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
        return;
      case DeviceConnectState::CONNECTING_AUTOCONNECT:
        /* Fallthrough as for AUTOCONNECT it might be that device is doing direct connect
         * in case of previous connection timeout.
         */
      case DeviceConnectState::CONNECTING_BY_USER:
        BTA_GATTC_CancelOpen(gatt_if_, address, true);
        [[fallthrough]];
      case DeviceConnectState::CONNECTING_AUTOCONNECT:
        leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
        break;
      case DeviceConnectState::DISCONNECTED:
        /* Do nothing, just remove device  */
        break;
+98 −1
Original line number Diff line number Diff line
@@ -5370,7 +5370,7 @@ TEST_F(UnicastTest, RemoveDeviceWhenConnected) {
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}
TEST_F(UnicastTest, RemoveDeviceWhenConnecting) {
TEST_F(UnicastTest, RemoveDeviceWhenUserConnecting) {
  const RawAddress test_address0 = GetTestAddress(0);
  uint16_t conn_id = 1;
@@ -5411,6 +5411,103 @@ TEST_F(UnicastTest, RemoveDeviceWhenConnecting) {
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}
TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingWithTargetedAnnouncements) {
  const RawAddress test_address0 = GetTestAddress(0);
  uint16_t conn_id = 1;
  /* Scenario
   * 1. Connect device
   * 2. Disconnect by remote device -> this shall start Reconnection Using TA
   * 3. Remove device
   */
  SetSampleDatabaseEarbudsValid(
          conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
          codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
          /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
          default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
          .Times(1);
  ConnectLeAudio(test_address0, true);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
          .Times(1);
  // Inject disconnected event, Reconnect with TA shall start
  InjectDisconnectedEvent(conn_id);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  // Remove device when being in auto connect state.
  EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
  EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
  EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
  do_in_main_thread(base::BindOnce(
          [](LeAudioClient* client, const RawAddress& test_address0) {
            client->RemoveDevice(test_address0);
          },
          LeAudioClient::Get(), test_address0));
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}
TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingAfterConnectionTimeout) {
  const RawAddress test_address0 = GetTestAddress(0);
  uint16_t conn_id = 1;
  /* Scenario
   * 1. Connect device
   * 2. Disconnect remote device with connection timeout -> this shall start direct connect
   * 3. Remove device
   */
  SetSampleDatabaseEarbudsValid(
          conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
          codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
          /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
          default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
          .Times(1);
  ConnectLeAudio(test_address0, true);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  // Prepare mock for direct connect and inject connection timeout
  ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
          .WillByDefault(DoAll(Return()));
  EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
          .Times(1);
  InjectDisconnectedEvent(conn_id, GATT_CONN_TIMEOUT);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  // Remove device when being in auto connect state after connection timeout
  EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
  EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
  EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
  do_in_main_thread(base::BindOnce(
          [](LeAudioClient* client, const RawAddress& test_address0) {
            client->RemoveDevice(test_address0);
          },
          LeAudioClient::Get(), test_address0));
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}
TEST_F(UnicastTest, RemoveDeviceWhenGettingConnectionReady) {
  const RawAddress test_address0 = GetTestAddress(0);
  uint16_t conn_id = 1;