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

Commit 4b71444d authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: If storage of LeAudio is broken make sure to rediscover device

Bug: 302629196
Test: atest bluetooth_le_audio_client_test
Tag: #feature

Change-Id: I2b2a19071d056fe255c04c3515f3107eb30ab6d1
parent 220708d9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1413,14 +1413,20 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) {
      /* If PACs are invalid, just say whole cache is invalid */
      leAudioDevice->known_service_handles_ = false;
      LOG_WARN("Could not load sink pacs");
    }

    if (!DeserializeSourcePacs(leAudioDevice, source_pacs)) {
      /* If PACs are invalid, just say whole cache is invalid */
      leAudioDevice->known_service_handles_ = false;
      LOG_WARN("Could not load source pacs");
    }

    if (!DeserializeAses(leAudioDevice, ases)) {
      /* If ASEs are invalid, just say whole cache is invalid */
      leAudioDevice->known_service_handles_ = false;
      LOG_WARN("Could not load ases");
    }

+148 −0
Original line number Diff line number Diff line
@@ -3430,6 +3430,154 @@ TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) {
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}

TEST_F(UnicastTestNoInit, LoadStoredEarbudsBroakenStorage) {
  // Prepare two devices
  uint8_t group_size = 2;
  uint8_t group_id = 2;
  /* If the storage has been broken, make sure device will be rediscovered after
   * reconnection
   */

  /* 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;
  std::vector<uint8_t> empty_buf;

  EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
    do_in_main_thread(
        FROM_HERE,
        base::BindOnce(&LeAudioClient::AddFromStorage, test_address0,
                       autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft,
                       codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
                       std::move(empty_buf), std::move(empty_buf),
                       std::move(empty_buf), std::move(empty_buf)));
    do_in_main_thread(
        FROM_HERE,
        base::BindOnce(&LeAudioClient::AddFromStorage, test_address1,
                       autoconnect, codec_spec_conf::kLeAudioLocationFrontRight,
                       codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
                       std::move(empty_buf), std::move(empty_buf),
                       std::move(empty_buf), std::move(empty_buf)));
    SyncOnMainLoop();
  });

  // 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 devices are not there and phone fallbacks to targeted
  // announcements
  EXPECT_CALL(mock_gatt_interface_,
              Open(gatt_if, test_address0,
                   BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
      .Times(1);

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

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

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

  /* Stack should rediscover services as storage is broken */
  EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
  EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);

  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);

  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address1))
      .Times(1);

  /* For background connect, test needs to Inject Connected Event */
  InjectConnectedEvent(test_address0, 1);
  InjectConnectedEvent(test_address1, 2);
  SyncOnMainLoop();

  // Verify if all went well and we got the proper group
  std::vector<RawAddress> devs =
      LeAudioClient::Get()->GetGroupDevices(group_id);
  ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
  ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());

  DisconnectLeAudioWithAclClose(test_address0, 1);
  DisconnectLeAudioWithAclClose(test_address1, 2);
}

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