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

Commit e4efe7b2 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Send codec config just before device is ACTIVE

This patch makes sure that before device is Connected to Audio Framework
(device is ACTIVE), LeAudioService knows currect codec configuration.

Also, when currect codec configuration changes, AF is notified

Bug: 314094343
Bug: 326442537
Test: atest LeAudioServiceTest bluetooth_le_audio_client_test
Change-Id: I01e1850c8c3992fc57e58398b2fef33d23050690
parent dfd5df58
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -2690,6 +2690,37 @@ public class LeAudioService extends ProfileService {
        mDialingOutTimeoutEvent = null;
    }

    void notifyAudioFrameworkForCodecConfigUpdate(int groupId, LeAudioGroupDescriptor descriptor) {
        Log.i(TAG, " notifyAudioFrameworkForCodecConfigUpdate groupId: " + groupId);

        if (!Flags.leaudioCodecConfigCallbackOrderFix()) {
            Log.d(TAG, " leaudio_codec_config_callback_order_fix is not enabled");
            return;
        }

        if (mActiveAudioOutDevice != null) {
            int volume = getAudioDeviceGroupVolume(groupId);

            final BluetoothProfileConnectionInfo connectionInfo;
            if (isAtLeastU()) {
                connectionInfo =
                        BluetoothProfileConnectionInfo.createLeAudioOutputInfo(true, volume);
            } else {
                connectionInfo = BluetoothProfileConnectionInfo.createLeAudioInfo(true, true);
            }

            mAudioManager.handleBluetoothActiveDeviceChanged(
                    mActiveAudioOutDevice, mActiveAudioOutDevice, connectionInfo);
        }

        if (mActiveAudioInDevice != null) {
            mAudioManager.handleBluetoothActiveDeviceChanged(
                    mActiveAudioOutDevice,
                    mActiveAudioOutDevice,
                    BluetoothProfileConnectionInfo.createLeAudioInfo(false, false));
        }
    }

    // Suppressed since this is part of a local process
    @SuppressLint("AndroidFrameworkRequiresPermission")
    void messageFromNative(LeAudioStackEvent stackEvent) {
@@ -2848,6 +2879,11 @@ public class LeAudioService extends ProfileService {

            descriptor.mCodecStatus = status;
            notifyUnicastCodecConfigChanged(groupId, status);

            if (descriptor.isActive()) {
                // Audio framework needs to be notified so it get new codec config
                notifyAudioFrameworkForCodecConfigUpdate(groupId, descriptor);
            }
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED) {
            int direction = stackEvent.valueInt1;
            int groupId = stackEvent.valueInt2;
+1 −0
Original line number Diff line number Diff line
@@ -1320,6 +1320,7 @@ class LeAudioClientImpl : public LeAudioClient {
    sink_monitor_notified_status_ = std::nullopt;
    if (IS_FLAG_ENABLED(leaudio_codec_config_callback_order_fix)) {
      SendAudioGroupSelectableCodecConfigChanged(group);
      SendAudioGroupCurrentCodecConfigChanged(group);
      callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
    } else {
      callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
+55 −0
Original line number Diff line number Diff line
@@ -4724,6 +4724,61 @@ TEST_F(UnicastTest, GroupSetActiveNonConnectedGroup) {
  Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
}

TEST_F_WITH_FLAGS(UnicastTest, GroupSetActive_CurrentCodecSentOfActive,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
                      TEST_BT, leaudio_codec_config_callback_order_fix))) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  /**
   * In this test we want to make sure that Available context change reach Java
   * when group is in Configured state
   */

  default_channel_cnt = 1;

  SetSampleDatabaseEarbudsValid(
      1, 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);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

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

  // Audio sessions are started only when device gets active
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnAudioGroupSelectableCodecConf(group_id, _, _))
      .Times(1);
  btle_audio_codec_config_t empty_conf{};
  btle_audio_codec_config_t output_config = {
      .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
      .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
      .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
      .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2,
      .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
      .octets_per_frame = 120};

  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
      .Times(1);

  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
}

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