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

Commit 7eb1ea7b authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Android (Google) Code Review
Browse files

Merge changes Id923dda9,I1f3645a8,I551bc46e,I9104254b into tm-d1-dev

* changes:
  leaudio: Add non vendor specific configuration for GAME mode
  leaudio: Return early if there is no updated context
  leaudio: Fix handling active context type
  leaudio: Add priority to GAME context type
parents 244186bf 131b09ff
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -128,7 +128,8 @@
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Server_Preferred_1",
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1",
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_Server_Preferred_1",
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1"
                "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1",
                "DualDev_OneChanStereoSnk_48_4_Server_Preferred"
            ]
        },
        {
+96 −42
Original line number Diff line number Diff line
@@ -82,6 +82,12 @@ using le_audio::client_parser::ascs::kCtpResponseInvalidAseCisMapping;
using le_audio::client_parser::ascs::kCtpResponseNoReason;

/* Enums */
enum class AudioReconfigurationResult {
  RECONFIGURATION_NEEDED = 0x00,
  RECONFIGURATION_NOT_NEEDED,
  RECONFIGURATION_NOT_POSSIBLE
};

enum class AudioState {
  IDLE = 0x00,
  READY_TO_START,
@@ -90,6 +96,25 @@ enum class AudioState {
  RELEASING,
};

std::ostream& operator<<(std::ostream& os,
                         const AudioReconfigurationResult& state) {
  switch (state) {
    case AudioReconfigurationResult::RECONFIGURATION_NEEDED:
      os << "RECONFIGURATION_NEEDED";
      break;
    case AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED:
      os << "RECONFIGURATION_NOT_NEEDED";
      break;
    case AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE:
      os << "RECONFIGRATION_NOT_POSSIBLE";
      break;
    default:
      os << "UNKNOWN";
      break;
  }
  return os;
}

std::ostream& operator<<(std::ostream& os, const AudioState& audio_state) {
  switch (audio_state) {
    case AudioState::IDLE:
@@ -2701,14 +2726,17 @@ class LeAudioClientImpl : public LeAudioClient {
    std::move(cleanupCb).Run();
  }

  bool UpdateConfigAndCheckIfReconfigurationIsNeeded(
  AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded(
      int group_id, LeAudioContextType context_type) {
    bool reconfiguration_needed = false;
    bool sink_cfg_available = true;
    bool source_cfg_available = true;

    auto group = aseGroups_.FindById(group_id);
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(group_id);
      return reconfiguration_needed;
      return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
    }

    std::optional<LeAudioCodecConfiguration> source_configuration =
@@ -2728,11 +2756,7 @@ class LeAudioClientImpl : public LeAudioClient {
        current_source_codec_config = {0, 0, 0, 0};
        reconfiguration_needed = true;
      }

      LOG(INFO) << __func__
                << ", group does not supports source direction for"
                   " context: "
                << static_cast<int>(context_type);
      source_cfg_available = false;
    }

    if (sink_configuration) {
@@ -2746,20 +2770,28 @@ class LeAudioClientImpl : public LeAudioClient {
        reconfiguration_needed = true;
      }

      LOG(INFO) << __func__
                << ", group does not supports sink direction for"
                   " context: "
                << static_cast<int>(context_type);
      sink_cfg_available = false;
    }

    if (reconfiguration_needed) {
      LOG(INFO) << __func__
                << " Session reconfiguration needed group: " << group->group_id_
                << " for context type: " << static_cast<int>(context_type);
    LOG_DEBUG(
        " Context: %s Reconfigufation_needed = %d, sink_cfg_available = %d, "
        "source_cfg_available = %d",
        ToString(context_type).c_str(), reconfiguration_needed,
        sink_cfg_available, source_cfg_available);

    if (!reconfiguration_needed) {
      return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
    }

    if (!sink_cfg_available && !source_cfg_available) {
      return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
    }

    LOG_INFO(" Session reconfiguration needed group: %d for context type: %s",
             group->group_id_, ToString(context_type).c_str());

    current_context_type_ = context_type;
    return reconfiguration_needed;
    return AudioReconfigurationResult::RECONFIGURATION_NEEDED;
  }

  bool OnAudioResume(LeAudioDeviceGroup* group) {
@@ -3088,7 +3120,6 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  LeAudioContextType AudioContentToLeAudioContext(
      LeAudioContextType current_context_type,
      audio_content_type_t content_type, audio_usage_t usage) {
    /* Check audio attribute usage of stream */
    switch (usage) {
@@ -3123,12 +3154,16 @@ class LeAudioClientImpl : public LeAudioClient {

  LeAudioContextType ChooseContextType(
      std::vector<LeAudioContextType>& available_contents) {
    /* Mini policy. Voice is prio 1, media is prio 2 */
    /* Mini policy. Voice is prio 1, game prio 2, media is prio 3 */
    auto iter = find(available_contents.begin(), available_contents.end(),
                     LeAudioContextType::CONVERSATIONAL);
    if (iter != available_contents.end())
      return LeAudioContextType::CONVERSATIONAL;

    iter = find(available_contents.begin(), available_contents.end(),
                LeAudioContextType::GAME);
    if (iter != available_contents.end()) return LeAudioContextType::GAME;

    iter = find(available_contents.begin(), available_contents.end(),
                LeAudioContextType::MEDIA);
    if (iter != available_contents.end()) return LeAudioContextType::MEDIA;
@@ -3139,10 +3174,19 @@ class LeAudioClientImpl : public LeAudioClient {

  bool StopStreamIfNeeded(LeAudioDeviceGroup* group,
                          LeAudioContextType new_context_type) {
    DLOG(INFO) << __func__ << " context type " << int(new_context_type);
    if (!UpdateConfigAndCheckIfReconfigurationIsNeeded(group->group_id_,
                                                       new_context_type)) {
      DLOG(INFO) << __func__ << " reconfiguration not needed";
    auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(
        group->group_id_, new_context_type);

    LOG_INFO("group_id %d, context type %s, reconfig_needed %s",
             group->group_id_, ToString(new_context_type).c_str(),
             ToString(reconfig_result).c_str());
    if (reconfig_result ==
        AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED) {
      return false;
    }

    if (reconfig_result ==
        AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE) {
      return false;
    }

@@ -3163,8 +3207,24 @@ class LeAudioClientImpl : public LeAudioClient {
    auto tracks = source_metadata.tracks;
    auto track_count = source_metadata.track_count;

    if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
      LOG(WARNING) << ", cannot start streaming if no active group set";
      return;
    }

    auto group = aseGroups_.FindById(active_group_id_);
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(active_group_id_);
      return;
    }
    bool is_group_streaming =
        (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

    std::vector<LeAudioContextType> contexts;

    auto supported_context_type = group->GetActiveContexts();

    while (track_count) {
      if (tracks->content_type == 0 && tracks->usage == 0) {
        --track_count;
@@ -3175,37 +3235,31 @@ class LeAudioClientImpl : public LeAudioClient {
      LOG_INFO("%s: usage=%d, content_type=%d, gain=%f", __func__,
               tracks->usage, tracks->content_type, tracks->gain);

      auto new_context = AudioContentToLeAudioContext(
          current_context_type_, tracks->content_type, tracks->usage);
      auto new_context =
          AudioContentToLeAudioContext(tracks->content_type, tracks->usage);

      /* Check only supported context types.*/
      if (static_cast<int>(new_context) & supported_context_type.to_ulong()) {
        contexts.push_back(new_context);
      } else {
        LOG_WARN(" Context type %s not supported by remote device",
                 ToString(new_context).c_str());
      }

      --track_count;
      ++tracks;
    }

    if (contexts.empty()) {
      DLOG(INFO) << __func__ << " invalid metadata update";
      LOG_WARN(" invalid/unknown metadata update");
      return;
    }

    auto new_context = ChooseContextType(contexts);
    DLOG(INFO) << __func__
               << " new_context_type: " << static_cast<int>(new_context);

    auto group = aseGroups_.FindById(active_group_id_);
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(active_group_id_);
      return;
    }
    LOG_DEBUG("new_context_type: %s", ToString(new_context).c_str());

    if (new_context == current_context_type_) {
      LOG(INFO) << __func__ << " Context did not changed.";
      return;
    }

    if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
      LOG(WARNING) << ", cannot start streaming if no active group set";
      LOG_INFO("Context did not changed.");
      return;
    }

@@ -3214,7 +3268,7 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
    if (is_group_streaming) {
      /* Configuration is the same for new context, just will do update
       * metadata of stream
       */
+52 −40
Original line number Diff line number Diff line
@@ -551,8 +551,8 @@ uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) {

/* This method returns AudioContext value if support for any type has changed */
std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(void) {
  DLOG(INFO) << __func__ << " group id: " << group_id_ << " active contexts: "
             << loghex(active_contexts_mask_.to_ulong());
  LOG_DEBUG(" group id: %d, active contexts: 0x%04lx", group_id_,
            active_contexts_mask_.to_ulong());
  return UpdateActiveContextsMap(active_contexts_mask_);
}

@@ -562,10 +562,19 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(
  AudioContexts contexts = 0x0000;
  bool active_contexts_has_been_modified = false;

  if (update_contexts.none()) {
    LOG_DEBUG("No context updated");
    return contexts;
  }

  for (LeAudioContextType ctx_type : types::kLeAudioContextAllTypesArray) {
    AudioContexts type_set = static_cast<uint16_t>(ctx_type);

    LOG_DEBUG("Taking context: %s, 0x%04lx",
              bluetooth::common::ToString(ctx_type).c_str(),
              update_contexts.to_ulong());
    if ((type_set & update_contexts).none()) {
      LOG_INFO("Configuration not in updated context %s",
               bluetooth::common::ToString(ctx_type).c_str());
      /* Fill context bitset for possible returned value if updated */
      if (active_context_to_configuration_map.count(ctx_type) > 0)
        contexts |= type_set;
@@ -575,9 +584,11 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(

    auto new_conf = FindFirstSupportedConfiguration(ctx_type);

    bool ctx_previously_not_supported =
        (active_context_to_configuration_map.count(ctx_type) == 0 ||
         active_context_to_configuration_map[ctx_type] == nullptr);
    /* Check if support for context type has changed */
    if (active_context_to_configuration_map.count(ctx_type) == 0 ||
        active_context_to_configuration_map[ctx_type] == nullptr) {
    if (ctx_previously_not_supported) {
      /* Current configuration for context type is empty */
      if (new_conf == nullptr) {
        /* Configuration remains empty */
@@ -604,12 +615,14 @@ std::optional<AudioContexts> LeAudioDeviceGroup::UpdateActiveContextsMap(
      }
    }

    LOG(INFO) << __func__ << ", updated context: " << loghex(int(ctx_type))
              << ", "
              << (active_context_to_configuration_map[ctx_type] != nullptr
                      ? active_context_to_configuration_map[ctx_type]->name
                      : "empty")
              << " -> " << (new_conf != nullptr ? new_conf->name : "empty");
    LOG_INFO(
        "updated context: %s, %s -> %s",
        bluetooth::common::ToString(ctx_type).c_str(),
        (ctx_previously_not_supported
             ? "empty"
             : active_context_to_configuration_map[ctx_type]->name.c_str()),
        (new_conf != nullptr ? new_conf->name.c_str() : "empty"));

    active_context_to_configuration_map[ctx_type] = new_conf;
  }

@@ -744,10 +757,9 @@ bool LeAudioDeviceGroup::IsConfigurationSupported(
    types::LeAudioContextType context_type) {
  if (!set_configurations::check_if_may_cover_scenario(
          audio_set_conf, NumOfConnected(context_type))) {
    DLOG(INFO) << __func__ << " cannot cover scenario "
               << static_cast<int>(context_type)
               << " size of for context type: "
               << +NumOfConnected(context_type);
    LOG_DEBUG(" cannot cover scenario  %s: size of for context type %d",
              bluetooth::common::ToString(context_type).c_str(),
              +NumOfConnected(context_type));
    return false;
  }

@@ -759,11 +771,9 @@ bool LeAudioDeviceGroup::IsConfigurationSupported(
   * 3) ASEs should be filled according to performance profile.
   */
  for (const auto& ent : (*audio_set_conf).confs) {
    DLOG(INFO) << __func__
               << " Looking for configuration: " << audio_set_conf->name
               << " - "
               << (ent.direction == types::kLeAudioDirectionSink ? "snk"
                                                                 : "src");
    LOG_DEBUG(" Looking for configuration: %s - %s",
              audio_set_conf->name.c_str(),
              (ent.direction == types::kLeAudioDirectionSink ? "snk" : "src"));

    uint8_t required_device_cnt = ent.device_cnt;
    uint8_t max_required_ase_per_dev =
@@ -771,10 +781,11 @@ bool LeAudioDeviceGroup::IsConfigurationSupported(
    uint8_t active_ase_num = 0;
    auto strategy = ent.strategy;

    DLOG(INFO) << __func__ << " Number of devices: " << +required_device_cnt
               << " number of ASEs: " << +ent.ase_cnt
               << " Max ASE per device: " << +max_required_ase_per_dev
               << " strategy: " << static_cast<int>(strategy);
    LOG_DEBUG(
        " Number of devices: %d, number of ASEs: %d,  Max ASE per device: %d "
        "strategy: %d",
        +required_device_cnt, +ent.ase_cnt, +max_required_ase_per_dev,
        static_cast<int>(strategy));

    for (auto* device = GetFirstDeviceWithActiveContext(context_type);
         device != nullptr && required_device_cnt > 0;
@@ -806,8 +817,8 @@ bool LeAudioDeviceGroup::IsConfigurationSupported(
              strategy, audio_locations,
              std::get<LeAudioLc3Config>(ent.codec.config).GetChannelCount(),
              device->GetLc3SupportedChannelCount(ent.direction))) {
        DLOG(INFO) << __func__ << " insufficient device audio allocation: "
                   << audio_locations;
        LOG_DEBUG(" insufficient device audio allocation: %lu",
                  audio_locations.to_ulong());
        continue;
      }

@@ -825,13 +836,13 @@ bool LeAudioDeviceGroup::IsConfigurationSupported(

    if (required_device_cnt > 0) {
      /* Don't left any active devices if requirements are not met */
      DLOG(INFO) << __func__ << " could not configure all the devices";
      LOG_DEBUG(" could not configure all the devices");
      return false;
    }
  }

  DLOG(INFO) << "Choosed ASE Configuration for group: " << this->group_id_
             << " configuration: " << audio_set_conf->name;
  LOG_DEBUG("Chosen ASE Configuration for group: %d, configuration: %s",
            this->group_id_, audio_set_conf->name.c_str());
  return true;
}

@@ -1205,13 +1216,14 @@ LeAudioDeviceGroup::FindFirstSupportedConfiguration(
  const set_configurations::AudioSetConfigurations* confs =
      AudioSetConfigurationProvider::Get()->GetConfigurations(context_type);

  DLOG(INFO) << __func__ << " context type: " << (int)context_type
             << " number of connected devices: " << NumOfConnected();
  LOG_DEBUG("context type: %s,  number of connected devices: %d",
            bluetooth::common::ToString(context_type).c_str(),
            +NumOfConnected());

  /* Filter out device set for all scenarios */
  if (!set_configurations::check_if_may_cover_scenario(confs,
                                                       NumOfConnected())) {
    LOG(ERROR) << __func__ << ", group is unable to cover scenario";
    LOG_ERROR(", group is unable to cover scenario");
    return nullptr;
  }

@@ -1219,7 +1231,7 @@ LeAudioDeviceGroup::FindFirstSupportedConfiguration(

  for (const auto& conf : *confs) {
    if (IsConfigurationSupported(conf, context_type)) {
      DLOG(INFO) << __func__ << " found: " << conf->name;
      LOG_DEBUG("found: %s", conf->name.c_str());
      return conf;
    }
  }
@@ -1656,7 +1668,7 @@ LeAudioDevice::GetCodecConfigurationSupportedPac(
      direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;

  if (pacs.size() == 0) {
    LOG(ERROR) << __func__ << " missing PAC for direction " << +direction;
    LOG_ERROR("missing PAC for direction %d", direction);
    return nullptr;
  }

@@ -1738,12 +1750,12 @@ AudioContexts LeAudioDevice::SetAvailableContexts(AudioContexts snk_contexts,
  updated_contexts = snk_contexts ^ avail_snk_contexts_;
  updated_contexts |= src_contexts ^ avail_src_contexts_;

  DLOG(INFO) << __func__
             << "\n\t avail_snk_contexts_: " << avail_snk_contexts_.to_string()
             << "\n\t avail_src_contexts_: " << avail_src_contexts_.to_string()
             << "\n\t snk_contexts:" << snk_contexts.to_string()
             << "\n\t src_contexts: " << src_contexts.to_string()
             << "\n\t updated_contexts: " << updated_contexts.to_string();
  LOG_DEBUG(
      "\n\t avail_snk_contexts_: %s \n\t avail_src_contexts_: %s  \n\t "
      "snk_contexts: %s \n\t src_contexts: %s \n\t updated_contexts: %s",
      avail_snk_contexts_.to_string().c_str(),
      avail_src_contexts_.to_string().c_str(), snk_contexts.to_string().c_str(),
      src_contexts.to_string().c_str(), updated_contexts.to_string().c_str());

  avail_snk_contexts_ = snk_contexts;
  avail_src_contexts_ = src_contexts;
+42 −1
Original line number Diff line number Diff line
@@ -808,7 +808,6 @@ class UnicastTestNoInit : public Test {

  void SetUp() override {
    init_message_loop_thread();

    ON_CALL(controller_interface_, SupportsBleConnectedIsochronousStreamCentral)
        .WillByDefault(Return(true));
    ON_CALL(controller_interface_,
@@ -3161,5 +3160,47 @@ TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
  LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
  Mock::VerifyAndClearExpectations(mock_unicast_audio_source_);
}

TEST_F(UnicastTest, StartNotSupportedContextType) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
      codec_spec_conf::kLeAudioLocationStereo, 0x0004, false /*add_csis*/,
      true /*add_cas*/, true /*add_pacs*/, true /*add_ascs*/, 1 /*set_size*/,
      0 /*rank*/);
  EXPECT_CALL(mock_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  // Start streaming
  uint8_t cis_count_out = 1;
  uint8_t cis_count_in = 0;

  // Audio sessions are started only when device gets active
  EXPECT_CALL(*mock_unicast_audio_source_, Start(_, _)).Times(1);
  EXPECT_CALL(*mock_audio_sink_, Start(_, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);

  StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
                 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);

  Mock::VerifyAndClearExpectations(&mock_client_callbacks_);
  Mock::VerifyAndClearExpectations(mock_unicast_audio_source_);
  SyncOnMainLoop();

  // Verify Data transfer on one audio source cis
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);

  EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
  UpdateMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN);
}
}  // namespace
}  // namespace le_audio
+85 −35

File changed.

Preview size limit exceeded, changes collapsed.

Loading