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