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

Commit 674b6683 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Do not update metadata if not needed" into main

parents 4b8c7779 a637ca23
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3657,9 +3657,9 @@ class LeAudioClientImpl : public LeAudioClient {
            bluetooth::common::ToString(configuration_context_type_).c_str(),
            configuration_context_type_);
    dprintf(fd, "  local source metadata context type mask: %s\n",
            local_metadata_context_types_.sink.to_string().c_str());
    dprintf(fd, "  local sink metadata context type mask: %s\n",
            local_metadata_context_types_.source.to_string().c_str());
    dprintf(fd, "  local sink metadata context type mask: %s\n",
            local_metadata_context_types_.sink.to_string().c_str());
    dprintf(fd, "  TBS state: %s\n", in_call_ ? " In call" : "No calls");
    dprintf(fd, "  Start time: ");
    for (auto t : stream_start_history_queue_) {
+11 −2
Original line number Diff line number Diff line
@@ -2444,15 +2444,24 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      auto directional_audio_context =
          context_types.get(ase->direction) &
          leAudioDevice->GetAvailableContexts(ase->direction);

      std::vector<uint8_t> new_metadata;
      if (directional_audio_context.any()) {
        ase->metadata = leAudioDevice->GetMetadata(
        new_metadata = leAudioDevice->GetMetadata(
            directional_audio_context, ccid_lists.get(ase->direction));
      } else {
        ase->metadata = leAudioDevice->GetMetadata(
        new_metadata = leAudioDevice->GetMetadata(
            AudioContexts(LeAudioContextType::UNSPECIFIED),
            std::vector<uint8_t>());
      }

      /* Do not update if metadata did not changed. */
      if (ase->metadata == new_metadata) {
        continue;
      }

      ase->metadata = new_metadata;

      struct le_audio::client_parser::ascs::ctp_update_metadata conf;

      conf.ase_id = ase->id;
+89 −2
Original line number Diff line number Diff line
@@ -2097,9 +2097,12 @@ TEST_F(StateMachineTest, testUpdateMetadataMultiple) {
  const auto leaudio_group_id = 4;
  const auto num_devices = 2;

  auto supported_contexts =
      types::AudioContexts(kContextTypeMedia | kContextTypeSoundEffects);

  // Prepare multiple fake connected devices in a group
  auto* group =
      PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
  auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type,
                                             num_devices, supported_contexts);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group);
@@ -2173,6 +2176,90 @@ TEST_F(StateMachineTest, testUpdateMetadataMultiple) {
  ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
}

TEST_F(StateMachineTest, testUpdateMetadataMultiple_NoUpdatesOnKeyTouch) {
  const auto context_type = kContextTypeMedia;
  const auto leaudio_group_id = 4;
  const auto num_devices = 2;

  /* Only Media is supported and available, */
  auto supported_contexts = types::AudioContexts(kContextTypeMedia);

  // Prepare multiple fake connected devices in a group
  auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type,
                                             num_devices, supported_contexts);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);

  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
  EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
  EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
  EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);

  InjectInitialIdleNotification(group);

  auto* leAudioDevice = group->GetFirstDevice();
  auto expected_devices_written = 0;
  while (leAudioDevice) {
    EXPECT_CALL(gatt_queue,
                WriteCharacteristic(leAudioDevice->conn_id_,
                                    leAudioDevice->ctp_hdls_.val_hdl, _,
                                    GATT_WRITE_NO_RSP, _, _))
        .Times(AtLeast(3));
    expected_devices_written++;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }
  ASSERT_EQ(expected_devices_written, num_devices);

  // Validate GroupStreamStatus
  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::STREAMING));

  // Start the configuration and stream Media content
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)}));

  testing::Mock::VerifyAndClearExpectations(&gatt_queue);

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

  ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
  reset_mock_function_count_map();

  // Make sure all devices get the metadata update
  leAudioDevice = group->GetFirstDevice();
  expected_devices_written = 0;
  while (leAudioDevice) {
    EXPECT_CALL(gatt_queue,
                WriteCharacteristic(leAudioDevice->conn_id_,
                                    leAudioDevice->ctp_hdls_.val_hdl, _,
                                    GATT_WRITE_NO_RSP, _, _))
        .Times(0);
    expected_devices_written++;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }
  ASSERT_EQ(expected_devices_written, num_devices);

  const auto metadata_context_type =
      kContextTypeMedia | kContextTypeSoundEffects;
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = metadata_context_type, .source = metadata_context_type}));

  /* This is just update metadata - watchdog is not used */
  ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
}

TEST_F(StateMachineTest, testDisableSingle) {
  /* Device is banded headphones with 2x snk + 0x src ase
   * (2xunidirectional CIS)