1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "bluetooth"
18 
19 #include "client_interface_hidl.h"
20 
21 #include <gtest/gtest.h>
22 
23 #include <vector>
24 
25 #include "codec_status_hidl.h"
26 
27 namespace {
28 
29 using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
30 using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
31 using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
32 using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
33 using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
34 using ::android::hardware::bluetooth::audio::V2_0::CodecType;
35 using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
36 using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
37 using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
38 using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
39 using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
40 using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
41 using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
42 using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
43 
44 using ::bluetooth::audio::hidl::AudioCapabilities;
45 using ::bluetooth::audio::hidl::AudioCapabilities_2_1;
46 using ::bluetooth::audio::hidl::AudioConfiguration;
47 using ::bluetooth::audio::hidl::AudioConfiguration_2_1;
48 using ::bluetooth::audio::hidl::BluetoothAudioClientInterface;
49 using ::bluetooth::audio::hidl::BluetoothAudioSinkClientInterface;
50 using ::bluetooth::audio::hidl::BluetoothAudioSourceClientInterface;
51 using ::bluetooth::audio::hidl::BluetoothAudioStatus;
52 using ::bluetooth::audio::hidl::PcmParameters;
53 using ::bluetooth::audio::hidl::PcmParameters_2_1;
54 using ::bluetooth::audio::hidl::SampleRate;
55 using ::bluetooth::audio::hidl::SampleRate_2_1;
56 using ::bluetooth::audio::hidl::SessionType;
57 using ::bluetooth::audio::hidl::SessionType_2_1;
58 using ::bluetooth::audio::hidl::codec::A2dpCodecToHalBitsPerSample;
59 using ::bluetooth::audio::hidl::codec::A2dpCodecToHalChannelMode;
60 using ::bluetooth::audio::hidl::codec::A2dpCodecToHalSampleRate;
61 using ::bluetooth::audio::hidl::codec::BitsPerSample;
62 using ::bluetooth::audio::hidl::codec::ChannelMode;
63 using ::bluetooth::audio::hidl::codec::CodecConfiguration;
64 using ::bluetooth::audio::hidl::codec::IsCodecOffloadingEnabled;
65 using ::bluetooth::audio::hidl::codec::UpdateOffloadingCapabilities;
66 using ::testing::Test;
67 
68 struct SampleRatePair {
69   SampleRate hal_sample_rate_;
70   btav_a2dp_codec_sample_rate_t btav_sample_rate_;
71 };
72 constexpr SampleRatePair kSampleRatePairs[9] = {
73     {.hal_sample_rate_ = SampleRate::RATE_UNKNOWN,
74      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE},
75     {.hal_sample_rate_ = SampleRate::RATE_44100,
76      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_44100},
77     {.hal_sample_rate_ = SampleRate::RATE_48000,
78      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_48000},
79     {.hal_sample_rate_ = SampleRate::RATE_88200,
80      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_88200},
81     {.hal_sample_rate_ = SampleRate::RATE_96000,
82      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_96000},
83     {.hal_sample_rate_ = SampleRate::RATE_176400,
84      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_176400},
85     {.hal_sample_rate_ = SampleRate::RATE_192000,
86      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_192000},
87     {.hal_sample_rate_ = SampleRate::RATE_16000,
88      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_16000},
89     {.hal_sample_rate_ = SampleRate::RATE_24000,
90      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_24000}};
91 
92 constexpr SampleRate_2_1 kSampleRates_2_1[] = {
93     SampleRate_2_1::RATE_UNKNOWN, SampleRate_2_1::RATE_8000,
94     SampleRate_2_1::RATE_16000,   SampleRate_2_1::RATE_24000,
95     SampleRate_2_1::RATE_32000,   SampleRate_2_1::RATE_44100,
96     SampleRate_2_1::RATE_48000};
97 
98 constexpr uint32_t kDataIntervalUs[] = {0 /* Invalid */,
99                                         10000 /* Valid 10ms */};
100 
101 struct BitsPerSamplePair {
102   BitsPerSample hal_bits_per_sample_;
103   btav_a2dp_codec_bits_per_sample_t btav_bits_per_sample_;
104 };
105 constexpr BitsPerSamplePair kBitsPerSamplePairs[4] = {
106     {.hal_bits_per_sample_ = BitsPerSample::BITS_UNKNOWN,
107      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE},
108     {.hal_bits_per_sample_ = BitsPerSample::BITS_16,
109      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16},
110     {.hal_bits_per_sample_ = BitsPerSample::BITS_24,
111      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24},
112     {.hal_bits_per_sample_ = BitsPerSample::BITS_32,
113      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32}};
114 
115 struct ChannelModePair {
116   ChannelMode hal_channel_mode_;
117   btav_a2dp_codec_channel_mode_t btav_channel_mode_;
118 };
119 constexpr ChannelModePair kChannelModePairs[3] = {
120     {.hal_channel_mode_ = ChannelMode::UNKNOWN,
121      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE},
122     {.hal_channel_mode_ = ChannelMode::MONO,
123      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO},
124     {.hal_channel_mode_ = ChannelMode::STEREO,
125      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO}};
126 
127 constexpr btav_a2dp_codec_index_t codec_indexes[] = {
128     BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,  BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
129     BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
130     BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, BTAV_A2DP_CODEC_INDEX_SINK_SBC,
131     BTAV_A2DP_CODEC_INDEX_SINK_AAC,    BTAV_A2DP_CODEC_INDEX_SINK_LDAC};
132 constexpr uint16_t kPeerMtus[5] = {660, 663, 883, 1005, 1500};
133 
134 class TestSinkTransport
135     : public bluetooth::audio::hidl::IBluetoothSinkTransportInstance {
136  private:
137   static constexpr uint64_t kRemoteDelayReportMs = 200;
138 
139  public:
TestSinkTransport(SessionType session_type)140   TestSinkTransport(SessionType session_type)
141       : bluetooth::audio::hidl::IBluetoothSinkTransportInstance(session_type,
142                                                                 {}){};
TestSinkTransport(SessionType_2_1 session_type_2_1)143   TestSinkTransport(SessionType_2_1 session_type_2_1)
144       : bluetooth::audio::hidl::IBluetoothSinkTransportInstance(
145             session_type_2_1, (AudioConfiguration_2_1){}){};
StartRequest()146   bluetooth::audio::hidl::BluetoothAudioCtrlAck StartRequest() override {
147     return bluetooth::audio::hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
148   }
SuspendRequest()149   bluetooth::audio::hidl::BluetoothAudioCtrlAck SuspendRequest() override {
150     return bluetooth::audio::hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
151   }
StopRequest()152   void StopRequest() override {}
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_readed,timespec * data_position)153   bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
154                                uint64_t* total_bytes_readed,
155                                timespec* data_position) override {
156     if (remote_delay_report_ns) {
157       *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
158     }
159     if (total_bytes_readed) {
160       *total_bytes_readed = 0;
161     }
162     if (data_position) {
163       clock_gettime(CLOCK_MONOTONIC, data_position);
164     }
165     return true;
166   }
MetadataChanged(const source_metadata_t & source_metadata __unused)167   void MetadataChanged(
168       const source_metadata_t& source_metadata __unused) override {}
ResetPresentationPosition()169   void ResetPresentationPosition() override{};
LogBytesRead(size_t bytes_readed __unused)170   void LogBytesRead(size_t bytes_readed __unused) override{};
171 };
172 
173 class TestSourceTransport
174     : public bluetooth::audio::hidl::IBluetoothSourceTransportInstance {
175  private:
176   static constexpr uint64_t kRemoteDelayReportMs = 200;
177 
178  public:
TestSourceTransport(SessionType session_type)179   TestSourceTransport(SessionType session_type)
180       : bluetooth::audio::hidl::IBluetoothSourceTransportInstance(session_type,
181                                                                   {}){};
TestSourceTransport(SessionType_2_1 session_type_2_1)182   TestSourceTransport(SessionType_2_1 session_type_2_1)
183       : bluetooth::audio::hidl::IBluetoothSourceTransportInstance(
184             session_type_2_1, (AudioConfiguration_2_1){}){};
StartRequest()185   bluetooth::audio::hidl::BluetoothAudioCtrlAck StartRequest() override {
186     return bluetooth::audio::hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
187   }
SuspendRequest()188   bluetooth::audio::hidl::BluetoothAudioCtrlAck SuspendRequest() override {
189     return bluetooth::audio::hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
190   }
StopRequest()191   void StopRequest() override {}
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)192   bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
193                                uint64_t* total_bytes_written,
194                                timespec* data_position) override {
195     if (remote_delay_report_ns) {
196       *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
197     }
198     if (total_bytes_written) {
199       *total_bytes_written = 0;
200     }
201     if (data_position) {
202       clock_gettime(CLOCK_MONOTONIC, data_position);
203     }
204     return true;
205   }
MetadataChanged(const source_metadata_t & source_metadata __unused)206   void MetadataChanged(
207       const source_metadata_t& source_metadata __unused) override {}
ResetPresentationPosition()208   void ResetPresentationPosition() override{};
LogBytesWritten(size_t bytes_written __unused)209   void LogBytesWritten(size_t bytes_written __unused) override{};
210 };
211 
212 class BluetoothAudioClientInterfaceTest : public Test {
213  protected:
214   TestSinkTransport* test_sink_transport_ = nullptr;
215   TestSourceTransport* test_source_transport_ = nullptr;
216   BluetoothAudioSinkClientInterface* clientif_sink_ = nullptr;
217   BluetoothAudioSourceClientInterface* clientif_source_ = nullptr;
218 
219   static constexpr int kClientIfReturnSuccess = 0;
220 
SetUp()221   void SetUp() override {}
222 
TearDown()223   void TearDown() override {
224     if (clientif_sink_ != nullptr) delete clientif_sink_;
225     clientif_sink_ = nullptr;
226     if (test_sink_transport_ != nullptr) delete test_sink_transport_;
227     test_sink_transport_ = nullptr;
228 
229     if (clientif_source_ != nullptr) delete clientif_source_;
230     clientif_source_ = nullptr;
231     if (test_source_transport_ != nullptr) delete test_source_transport_;
232     test_source_transport_ = nullptr;
233   }
234 
IsSoftwarePcmParametersSupported(const PcmParameters & pcm_config)235   bool IsSoftwarePcmParametersSupported(const PcmParameters& pcm_config) {
236     const std::vector<AudioCapabilities>& capabilities =
237         clientif_sink_->GetAudioCapabilities();
238     PcmParameters pcm_capabilities = capabilities[0].pcmCapabilities();
239     bool is_pcm_config_valid =
240         (pcm_config.sampleRate != SampleRate::RATE_UNKNOWN &&
241          pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
242          pcm_config.channelMode != ChannelMode::UNKNOWN);
243     bool is_pcm_config_supported =
244         (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
245          pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
246          pcm_config.channelMode & pcm_capabilities.channelMode);
247     return (is_pcm_config_valid && is_pcm_config_supported);
248   }
249 
IsSinkSoftwarePcmParameters_2_1_Supported(const PcmParameters_2_1 & pcm_config)250   bool IsSinkSoftwarePcmParameters_2_1_Supported(
251       const PcmParameters_2_1& pcm_config) {
252     return IsSoftwarePcmParameters_2_1_Supported(pcm_config, clientif_sink_);
253   }
254 
IsSourceSoftwarePcmParameters_2_1_Supported(const PcmParameters_2_1 & pcm_config)255   bool IsSourceSoftwarePcmParameters_2_1_Supported(
256       const PcmParameters_2_1& pcm_config) {
257     return IsSoftwarePcmParameters_2_1_Supported(pcm_config, clientif_source_);
258   }
259 
IsCodecOffloadingSupported(const CodecConfiguration & codec_config)260   bool IsCodecOffloadingSupported(const CodecConfiguration& codec_config) {
261     CodecCapabilities codec_capability = {};
262     for (auto audio_capability : clientif_sink_->GetAudioCapabilities()) {
263       if (audio_capability.codecCapabilities().codecType ==
264           codec_config.codecType) {
265         codec_capability = audio_capability.codecCapabilities();
266       }
267     }
268     if (codec_capability.codecType != codec_config.codecType) {
269       // codec is unsupported
270       return false;
271     }
272     bool is_codec_config_supported = false;
273     switch (codec_config.codecType) {
274       case CodecType::SBC: {
275         SbcParameters sbc_config = codec_config.config.sbcConfig();
276         SbcParameters sbc_capability =
277             codec_capability.capabilities.sbcCapabilities();
278         is_codec_config_supported =
279             (sbc_config.sampleRate & sbc_capability.sampleRate &&
280              sbc_config.channelMode & sbc_capability.channelMode &&
281              sbc_config.blockLength & sbc_capability.blockLength &&
282              sbc_config.numSubbands & sbc_capability.numSubbands &&
283              sbc_config.allocMethod & sbc_capability.allocMethod &&
284              sbc_config.bitsPerSample & sbc_capability.bitsPerSample &&
285              (sbc_capability.minBitpool <= sbc_config.minBitpool &&
286               sbc_config.minBitpool <= sbc_config.maxBitpool &&
287               sbc_config.maxBitpool <= sbc_capability.maxBitpool));
288         return is_codec_config_supported;
289       }
290       case CodecType::AAC: {
291         AacParameters aac_config = codec_config.config.aacConfig();
292         AacParameters aac_capability =
293             codec_capability.capabilities.aacCapabilities();
294         is_codec_config_supported =
295             (aac_config.objectType & aac_capability.objectType &&
296              aac_config.sampleRate & aac_capability.sampleRate &&
297              aac_config.channelMode & aac_capability.channelMode &&
298              (aac_config.variableBitRateEnabled ==
299                   AacVariableBitRate::DISABLED ||
300               aac_capability.variableBitRateEnabled ==
301                   AacVariableBitRate::ENABLED) &&
302              aac_config.bitsPerSample & aac_capability.bitsPerSample);
303         return is_codec_config_supported;
304       }
305       case CodecType::LDAC: {
306         LdacParameters ldac_config = codec_config.config.ldacConfig();
307         LdacParameters ldac_capability =
308             codec_capability.capabilities.ldacCapabilities();
309         is_codec_config_supported =
310             (ldac_config.sampleRate & ldac_capability.sampleRate &&
311              ldac_config.channelMode & ldac_capability.channelMode &&
312              ldac_config.bitsPerSample & ldac_capability.bitsPerSample);
313         return is_codec_config_supported;
314       }
315       case CodecType::APTX:
316         [[fallthrough]];
317       case CodecType::APTX_HD: {
318         AptxParameters aptx_config = codec_config.config.aptxConfig();
319         AptxParameters aptx_capability =
320             codec_capability.capabilities.aptxCapabilities();
321         is_codec_config_supported =
322             (aptx_config.sampleRate & aptx_capability.sampleRate &&
323              aptx_config.channelMode & aptx_capability.channelMode &&
324              aptx_config.bitsPerSample & aptx_capability.bitsPerSample);
325         return is_codec_config_supported;
326       }
327       case CodecType::UNKNOWN:
328         return false;
329     }
330   }
331 
332  private:
IsSoftwarePcmParameters_2_1_Supported(const PcmParameters_2_1 & pcm_config,const BluetoothAudioClientInterface * clientif_)333   bool IsSoftwarePcmParameters_2_1_Supported(
334       const PcmParameters_2_1& pcm_config,
335       const BluetoothAudioClientInterface* clientif_) {
336     const std::vector<AudioCapabilities_2_1>& capabilities =
337         clientif_->GetAudioCapabilities_2_1();
338     PcmParameters_2_1 pcm_capabilities = capabilities[0].pcmCapabilities();
339     bool is_pcm_config_valid =
340         (pcm_config.sampleRate != SampleRate_2_1::RATE_UNKNOWN &&
341          pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
342          pcm_config.channelMode != ChannelMode::UNKNOWN &&
343          pcm_config.dataIntervalUs != 0);
344     bool is_pcm_config_supported =
345         (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
346          pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
347          pcm_config.channelMode & pcm_capabilities.channelMode);
348     return (is_pcm_config_valid && is_pcm_config_supported);
349   }
350 };
351 
352 }  // namespace
353 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpCodecToHalPcmConfig)354 TEST_F(BluetoothAudioClientInterfaceTest, A2dpCodecToHalPcmConfig) {
355   btav_a2dp_codec_config_t a2dp_codec_config = {};
356   for (auto sample_rate_pair : kSampleRatePairs) {
357     a2dp_codec_config.sample_rate = sample_rate_pair.btav_sample_rate_;
358     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
359       a2dp_codec_config.bits_per_sample =
360           bits_per_sample_pair.btav_bits_per_sample_;
361       for (auto channel_mode_pair : kChannelModePairs) {
362         a2dp_codec_config.channel_mode = channel_mode_pair.btav_channel_mode_;
363         ASSERT_EQ(A2dpCodecToHalSampleRate(a2dp_codec_config),
364                   sample_rate_pair.hal_sample_rate_);
365         ASSERT_EQ(A2dpCodecToHalBitsPerSample(a2dp_codec_config),
366                   bits_per_sample_pair.hal_bits_per_sample_);
367         ASSERT_EQ(A2dpCodecToHalChannelMode(a2dp_codec_config),
368                   channel_mode_pair.hal_channel_mode_);
369       }  // ChannelMode
370     }    // BitsPerSampple
371   }      // SampleRate
372 }
373 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpSoftwareSession)374 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpSoftwareSession) {
375   test_sink_transport_ =
376       new TestSinkTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
377   clientif_sink_ =
378       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
379   AudioConfiguration audio_config = {};
380   PcmParameters pcm_config = {};
381   for (auto sample_rate_pair : kSampleRatePairs) {
382     pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
383     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
384       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
385       for (auto channel_mode_pair : kChannelModePairs) {
386         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
387         audio_config.pcmConfig(pcm_config);
388         clientif_sink_->UpdateAudioConfig(audio_config);
389         if (IsSoftwarePcmParametersSupported(pcm_config)) {
390           ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
391         } else {
392           ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
393         }
394         ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
395       }  // ChannelMode
396     }    // BitsPerSampple
397   }      // SampleRate
398 }
399 
400 struct CodecOffloadingPreference {
401   bool is_target_codec_included_;
402   std::vector<btav_a2dp_codec_config_t> preference_;
403 };
404 
CodecOffloadingPreferenceGenerator(btav_a2dp_codec_index_t target_codec_index)405 std::vector<CodecOffloadingPreference> CodecOffloadingPreferenceGenerator(
406     btav_a2dp_codec_index_t target_codec_index) {
407   std::vector<CodecOffloadingPreference> codec_offloading_preferences = {
408       {.is_target_codec_included_ = false,
409        .preference_ = std::vector<btav_a2dp_codec_config_t>(0)}};
410   btav_a2dp_codec_config_t a2dp_codec_config = {};
411   for (auto codec_index : codec_indexes) {
412     a2dp_codec_config.codec_type = codec_index;
413     auto duplicated_preferences = codec_offloading_preferences;
414     for (auto iter = duplicated_preferences.begin();
415          iter != duplicated_preferences.end(); ++iter) {
416       if (codec_index == target_codec_index) {
417         iter->is_target_codec_included_ = true;
418       }
419       iter->preference_.push_back(a2dp_codec_config);
420     }
421     codec_offloading_preferences.insert(codec_offloading_preferences.end(),
422                                         duplicated_preferences.begin(),
423                                         duplicated_preferences.end());
424   }
425   return codec_offloading_preferences;
426 }
427 
SbcCodecConfigurationsGenerator()428 std::vector<CodecConfiguration> SbcCodecConfigurationsGenerator() {
429   std::vector<CodecConfiguration> sbc_codec_configs;
430   CodecConfiguration codec_config = {};
431   SbcBlockLength block_lengths[4] = {
432       SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8,
433       SbcBlockLength::BLOCKS_12, SbcBlockLength::BLOCKS_16};
434   SbcNumSubbands num_subbands[2] = {SbcNumSubbands::SUBBAND_4,
435                                     SbcNumSubbands::SUBBAND_8};
436   SbcAllocMethod alloc_methods[2] = {SbcAllocMethod::ALLOC_MD_S,
437                                      SbcAllocMethod::ALLOC_MD_L};
438   for (auto sample_rate_pair : kSampleRatePairs) {
439     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
440       for (auto channel_mode_pair : kChannelModePairs) {
441         for (auto peer_mtu : kPeerMtus) {
442           for (auto block_length : block_lengths) {
443             for (auto num_subband : num_subbands) {
444               for (auto alloc_method : alloc_methods) {
445                 codec_config.codecType = CodecType::SBC;
446                 codec_config.peerMtu = peer_mtu;
447                 codec_config.isScmstEnabled = false;
448                 // A2DP_SBC_DEFAULT_BITRATE
449                 codec_config.encodedAudioBitrate = 328000;
450                 SbcParameters sbc = {
451                     .sampleRate = sample_rate_pair.hal_sample_rate_,
452                     .channelMode = (channel_mode_pair.hal_channel_mode_ ==
453                                             ChannelMode::MONO
454                                         ? SbcChannelMode::MONO
455                                         : SbcChannelMode::JOINT_STEREO),
456                     .blockLength = block_length,
457                     .numSubbands = num_subband,
458                     .allocMethod = alloc_method,
459                     .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_,
460                     .minBitpool = 2,
461                     .maxBitpool = 53};
462                 codec_config.config.sbcConfig(sbc);
463                 sbc_codec_configs.push_back(codec_config);
464               }  // SbcAllocMethod
465             }    // SbcNumSubbands
466           }      // SbcBlockLength
467         }        // peerMtu
468       }          // ChannelMode
469     }            // BitsPerSampple
470   }              // SampleRate
471   return sbc_codec_configs;
472 }
473 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpSbcCodecOffloadingState)474 TEST_F(BluetoothAudioClientInterfaceTest, A2dpSbcCodecOffloadingState) {
475   test_sink_transport_ =
476       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
477   clientif_sink_ =
478       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
479   auto sbc_codec_configs = SbcCodecConfigurationsGenerator();
480   for (auto codec_offloading_preference :
481        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC)) {
482     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
483     for (CodecConfiguration codec_config : sbc_codec_configs) {
484       if (IsCodecOffloadingSupported(codec_config) &&
485           codec_offloading_preference.is_target_codec_included_) {
486         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
487       } else {
488         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
489       }
490     }
491   }
492 }
493 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadSbcSession)494 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) {
495   test_sink_transport_ =
496       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
497   clientif_sink_ =
498       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
499   AudioConfiguration audio_config = {};
500   for (CodecConfiguration codec_config : SbcCodecConfigurationsGenerator()) {
501     audio_config.codecConfig(codec_config);
502     clientif_sink_->UpdateAudioConfig(audio_config);
503     if (IsCodecOffloadingSupported(codec_config)) {
504       ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
505     } else {
506       ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
507     }
508     ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
509   }
510 }
511 
AacCodecConfigurationsGenerator()512 std::vector<CodecConfiguration> AacCodecConfigurationsGenerator() {
513   std::vector<CodecConfiguration> aac_codec_configs;
514   CodecConfiguration codec_config = {};
515   AacObjectType object_types[4] = {
516       AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC,
517       AacObjectType::MPEG4_LTP, AacObjectType::MPEG4_SCALABLE};
518   AacVariableBitRate variable_bitrates[2] = {AacVariableBitRate::DISABLED,
519                                              AacVariableBitRate::ENABLED};
520   for (auto sample_rate_pair : kSampleRatePairs) {
521     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
522       for (auto channel_mode_pair : kChannelModePairs) {
523         for (auto peer_mtu : kPeerMtus) {
524           for (auto object_type : object_types) {
525             for (auto variable_bitrate : variable_bitrates) {
526               codec_config.codecType = CodecType::AAC;
527               codec_config.peerMtu = peer_mtu;
528               codec_config.isScmstEnabled = false;
529               // A2DP_AAC_DEFAULT_BITRATE
530               codec_config.encodedAudioBitrate = 320000;
531               AacParameters aac = {
532                   .objectType = object_type,
533                   .sampleRate = sample_rate_pair.hal_sample_rate_,
534                   .channelMode = channel_mode_pair.hal_channel_mode_,
535                   .variableBitRateEnabled = variable_bitrate,
536                   .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
537               codec_config.config.aacConfig(aac);
538               aac_codec_configs.push_back(codec_config);
539             }  // AacVariableBitRate
540           }    // AacObjectType
541         }      // peerMtu
542       }        // ChannelMode
543     }          // BitsPerSampple
544   }            // SampleRate
545   return aac_codec_configs;
546 }
547 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAacCodecOffloadingState)548 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAacCodecOffloadingState) {
549   test_sink_transport_ =
550       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
551   clientif_sink_ =
552       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
553   auto aac_codec_configs = AacCodecConfigurationsGenerator();
554   for (auto codec_offloading_preference :
555        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC)) {
556     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
557     for (CodecConfiguration codec_config : aac_codec_configs) {
558       if (IsCodecOffloadingSupported(codec_config) &&
559           codec_offloading_preference.is_target_codec_included_) {
560         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
561       } else {
562         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
563       }
564     }
565   }
566 }
567 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadAacSession)568 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) {
569   test_sink_transport_ =
570       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
571   clientif_sink_ =
572       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
573   AudioConfiguration audio_config = {};
574   for (CodecConfiguration codec_config : AacCodecConfigurationsGenerator()) {
575     audio_config.codecConfig(codec_config);
576     clientif_sink_->UpdateAudioConfig(audio_config);
577     if (IsCodecOffloadingSupported(codec_config)) {
578       ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
579     } else {
580       ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
581     }
582     ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
583   }
584 }
585 
LdacCodecConfigurationsGenerator()586 std::vector<CodecConfiguration> LdacCodecConfigurationsGenerator() {
587   std::vector<CodecConfiguration> ldac_codec_configs;
588   CodecConfiguration codec_config = {};
589   LdacQualityIndex quality_indexes[4] = {
590       LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
591       LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
592   for (auto sample_rate_pair : kSampleRatePairs) {
593     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
594       for (auto channel_mode_pair : kChannelModePairs) {
595         for (auto peer_mtu : kPeerMtus) {
596           for (auto quality_index : quality_indexes) {
597             codec_config.codecType = CodecType::LDAC;
598             codec_config.peerMtu = peer_mtu;
599             codec_config.isScmstEnabled = false;
600             codec_config.encodedAudioBitrate = 990000;
601             LdacParameters ldac = {
602                 .sampleRate = sample_rate_pair.hal_sample_rate_,
603                 .channelMode =
604                     (channel_mode_pair.hal_channel_mode_ == ChannelMode::MONO
605                          ? LdacChannelMode::MONO
606                          : LdacChannelMode::STEREO),
607                 .qualityIndex = quality_index,
608                 .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
609             codec_config.config.ldacConfig(ldac);
610             ldac_codec_configs.push_back(codec_config);
611           }  // LdacQualityIndex
612         }    // peerMtu
613       }      // ChannelMode
614     }        // BitsPerSampple
615   }          // SampleRate
616   return ldac_codec_configs;
617 }
618 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpLdacCodecOffloadingState)619 TEST_F(BluetoothAudioClientInterfaceTest, A2dpLdacCodecOffloadingState) {
620   test_sink_transport_ =
621       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
622   clientif_sink_ =
623       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
624   auto ldac_codec_configs = LdacCodecConfigurationsGenerator();
625   for (auto codec_offloading_preference :
626        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC)) {
627     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
628     for (CodecConfiguration codec_config : ldac_codec_configs) {
629       if (IsCodecOffloadingSupported(codec_config) &&
630           codec_offloading_preference.is_target_codec_included_) {
631         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
632       } else {
633         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
634       }
635     }
636   }
637 }
638 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadLdacSession)639 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) {
640   test_sink_transport_ =
641       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
642   clientif_sink_ =
643       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
644   AudioConfiguration audio_config = {};
645   for (CodecConfiguration codec_config : LdacCodecConfigurationsGenerator()) {
646     audio_config.codecConfig(codec_config);
647     clientif_sink_->UpdateAudioConfig(audio_config);
648     if (IsCodecOffloadingSupported(codec_config)) {
649       ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
650     } else {
651       ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
652     }
653     ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
654   }
655 }
656 
AptxCodecConfigurationsGenerator(CodecType codec_type)657 std::vector<CodecConfiguration> AptxCodecConfigurationsGenerator(
658     CodecType codec_type) {
659   std::vector<CodecConfiguration> aptx_codec_configs;
660   if (codec_type != CodecType::APTX && codec_type != CodecType::APTX_HD)
661     return aptx_codec_configs;
662   CodecConfiguration codec_config = {};
663   for (auto sample_rate_pair : kSampleRatePairs) {
664     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
665       for (auto channel_mode_pair : kChannelModePairs) {
666         for (auto peer_mtu : kPeerMtus) {
667           codec_config.codecType = codec_type;
668           codec_config.peerMtu = peer_mtu;
669           codec_config.isScmstEnabled = false;
670           codec_config.encodedAudioBitrate =
671               (codec_type == CodecType::APTX ? 352000 : 576000);
672           AptxParameters aptx = {
673               .sampleRate = sample_rate_pair.hal_sample_rate_,
674               .channelMode = channel_mode_pair.hal_channel_mode_,
675               .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
676           codec_config.config.aptxConfig(aptx);
677           aptx_codec_configs.push_back(codec_config);
678         }  // peerMtu
679       }    // ChannelMode
680     }      // BitsPerSampple
681   }        // SampleRate
682   return aptx_codec_configs;
683 }
684 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAptxCodecOffloadingState)685 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxCodecOffloadingState) {
686   test_sink_transport_ =
687       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
688   clientif_sink_ =
689       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
690   auto aptx_codec_configs = AptxCodecConfigurationsGenerator(CodecType::APTX);
691   for (auto codec_offloading_preference :
692        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX)) {
693     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
694     for (CodecConfiguration codec_config : aptx_codec_configs) {
695       if (IsCodecOffloadingSupported(codec_config) &&
696           codec_offloading_preference.is_target_codec_included_) {
697         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
698       } else {
699         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
700       }
701     }
702   }
703 }
704 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadAptxSession)705 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxSession) {
706   test_sink_transport_ =
707       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
708   clientif_sink_ =
709       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
710   AudioConfiguration audio_config = {};
711   for (CodecConfiguration codec_config :
712        AptxCodecConfigurationsGenerator(CodecType::APTX)) {
713     audio_config.codecConfig(codec_config);
714     clientif_sink_->UpdateAudioConfig(audio_config);
715     if (IsCodecOffloadingSupported(codec_config)) {
716       ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
717     } else {
718       ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
719     }
720     ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
721   }
722 }
723 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAptxHdCodecOffloadingState)724 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxHdCodecOffloadingState) {
725   test_sink_transport_ =
726       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
727   clientif_sink_ =
728       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
729   auto aptx_hd_codec_configs =
730       AptxCodecConfigurationsGenerator(CodecType::APTX_HD);
731   for (auto codec_offloading_preference : CodecOffloadingPreferenceGenerator(
732            BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD)) {
733     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
734     for (CodecConfiguration codec_config : aptx_hd_codec_configs) {
735       if (IsCodecOffloadingSupported(codec_config) &&
736           codec_offloading_preference.is_target_codec_included_) {
737         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
738       } else {
739         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
740       }
741     }
742   }
743 }
744 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadAptxHdSession)745 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxHdSession) {
746   test_sink_transport_ =
747       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
748   clientif_sink_ =
749       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
750   AudioConfiguration audio_config = {};
751   for (CodecConfiguration codec_config :
752        AptxCodecConfigurationsGenerator(CodecType::APTX_HD)) {
753     audio_config.codecConfig(codec_config);
754     clientif_sink_->UpdateAudioConfig(audio_config);
755     if (IsCodecOffloadingSupported(codec_config)) {
756       ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
757     } else {
758       ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
759     }
760     ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
761   }
762 }
763 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadUnknownSession)764 TEST_F(BluetoothAudioClientInterfaceTest,
765        StartAndEndA2dpOffloadUnknownSession) {
766   test_sink_transport_ =
767       new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
768   clientif_sink_ =
769       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
770   AudioConfiguration audio_config = {};
771   CodecConfiguration codec_config = {};
772   codec_config.codecType = CodecType::UNKNOWN;
773   codec_config.peerMtu = 1005;
774   codec_config.isScmstEnabled = false;
775   codec_config.encodedAudioBitrate = 328000;
776   codec_config.config = {};
777   audio_config.codecConfig(codec_config);
778   clientif_sink_->UpdateAudioConfig(audio_config);
779   if (IsCodecOffloadingSupported(codec_config)) {
780     ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
781   } else {
782     ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
783   }
784   ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
785 }
786 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndHearingAidSoftwareSession)787 TEST_F(BluetoothAudioClientInterfaceTest,
788        StartAndEndHearingAidSoftwareSession) {
789   test_sink_transport_ = new TestSinkTransport(
790       SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
791   clientif_sink_ =
792       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
793   AudioConfiguration audio_config = {};
794   PcmParameters pcm_config = {};
795   for (auto sample_rate_pair : kSampleRatePairs) {
796     pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
797     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
798       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
799       for (auto channel_mode_pair : kChannelModePairs) {
800         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
801         audio_config.pcmConfig(pcm_config);
802         clientif_sink_->UpdateAudioConfig(audio_config);
803         if (IsSoftwarePcmParametersSupported(pcm_config)) {
804           ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
805         } else {
806           ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
807         }
808         ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
809       }  // ChannelMode
810     }    // BitsPerSampple
811   }      // SampleRate
812 }
813 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndLeAudioEncodingSoftwareSession)814 TEST_F(BluetoothAudioClientInterfaceTest,
815        StartAndEndLeAudioEncodingSoftwareSession) {
816   test_sink_transport_ = new TestSinkTransport(
817       SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
818   clientif_sink_ =
819       new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
820   AudioConfiguration_2_1 audio_config = {};
821   PcmParameters_2_1 pcm_config = {};
822   for (auto sample_rate : kSampleRates_2_1) {
823     pcm_config.sampleRate = sample_rate;
824     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
825       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
826       for (auto channel_mode_pair : kChannelModePairs) {
827         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
828         for (auto data_interval_us : kDataIntervalUs) {
829           pcm_config.dataIntervalUs = data_interval_us;
830           audio_config.pcmConfig(pcm_config);
831           clientif_sink_->UpdateAudioConfig_2_1(audio_config);
832           if (IsSinkSoftwarePcmParameters_2_1_Supported(pcm_config)) {
833             ASSERT_EQ(clientif_sink_->StartSession_2_1(),
834                       kClientIfReturnSuccess);
835           } else {
836             ASSERT_NE(clientif_sink_->StartSession_2_1(),
837                       kClientIfReturnSuccess);
838           }
839           ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
840         }  // dataIntervalUs
841       }    // ChannelMode
842     }      // BitsPerSampple
843   }        // SampleRate
844 }
845 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndLeAudioDecodedSoftwareSession)846 TEST_F(BluetoothAudioClientInterfaceTest,
847        StartAndEndLeAudioDecodedSoftwareSession) {
848   test_source_transport_ = new TestSourceTransport(
849       SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
850   clientif_source_ =
851       new BluetoothAudioSourceClientInterface(test_source_transport_, nullptr);
852   AudioConfiguration_2_1 audio_config = {};
853   PcmParameters_2_1 pcm_config = {};
854   for (auto sample_rate : kSampleRates_2_1) {
855     pcm_config.sampleRate = sample_rate;
856     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
857       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
858       for (auto channel_mode_pair : kChannelModePairs) {
859         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
860         for (auto data_interval_us : kDataIntervalUs) {
861           pcm_config.dataIntervalUs = data_interval_us;
862           audio_config.pcmConfig(pcm_config);
863           clientif_source_->UpdateAudioConfig_2_1(audio_config);
864           if (IsSourceSoftwarePcmParameters_2_1_Supported(pcm_config)) {
865             ASSERT_EQ(clientif_source_->StartSession_2_1(),
866                       kClientIfReturnSuccess);
867           } else {
868             ASSERT_NE(clientif_source_->StartSession_2_1(),
869                       kClientIfReturnSuccess);
870           }
871           ASSERT_EQ(clientif_source_->EndSession(), kClientIfReturnSuccess);
872         }  // dataIntervalUs
873       }    // ChannelMode
874     }      // BitsPerSampple
875   }        // SampleRate
876 }
877