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 #include <gtest/gtest.h>
18 
19 #include "client_interface.h"
20 #include "codec_status.h"
21 
22 namespace {
23 
24 using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
25 using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
26 using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
27 using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
28 using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
29 using ::android::hardware::bluetooth::audio::V2_0::CodecType;
30 using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
31 using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
32 using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
33 using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
34 using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
35 using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
36 using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
37 using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
38 
39 using ::bluetooth::audio::AudioCapabilities;
40 using ::bluetooth::audio::AudioConfiguration;
41 using ::bluetooth::audio::BluetoothAudioClientInterface;
42 using ::bluetooth::audio::BluetoothAudioStatus;
43 using ::bluetooth::audio::PcmParameters;
44 using ::bluetooth::audio::SessionType;
45 using ::bluetooth::audio::codec::A2dpCodecToHalBitsPerSample;
46 using ::bluetooth::audio::codec::A2dpCodecToHalChannelMode;
47 using ::bluetooth::audio::codec::A2dpCodecToHalSampleRate;
48 using ::bluetooth::audio::codec::BitsPerSample;
49 using ::bluetooth::audio::codec::ChannelMode;
50 using ::bluetooth::audio::codec::CodecConfiguration;
51 using ::bluetooth::audio::codec::IsCodecOffloadingEnabled;
52 using ::bluetooth::audio::codec::SampleRate;
53 using ::bluetooth::audio::codec::UpdateOffloadingCapabilities;
54 using ::testing::Test;
55 
56 struct SampleRatePair {
57   SampleRate hal_sample_rate_;
58   btav_a2dp_codec_sample_rate_t btav_sample_rate_;
59 };
60 constexpr SampleRatePair kSampleRatePairs[9] = {
61     {.hal_sample_rate_ = SampleRate::RATE_UNKNOWN,
62      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE},
63     {.hal_sample_rate_ = SampleRate::RATE_44100,
64      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_44100},
65     {.hal_sample_rate_ = SampleRate::RATE_48000,
66      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_48000},
67     {.hal_sample_rate_ = SampleRate::RATE_88200,
68      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_88200},
69     {.hal_sample_rate_ = SampleRate::RATE_96000,
70      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_96000},
71     {.hal_sample_rate_ = SampleRate::RATE_176400,
72      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_176400},
73     {.hal_sample_rate_ = SampleRate::RATE_192000,
74      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_192000},
75     {.hal_sample_rate_ = SampleRate::RATE_16000,
76      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_16000},
77     {.hal_sample_rate_ = SampleRate::RATE_24000,
78      .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_24000}};
79 
80 struct BitsPerSamplePair {
81   BitsPerSample hal_bits_per_sample_;
82   btav_a2dp_codec_bits_per_sample_t btav_bits_per_sample_;
83 };
84 constexpr BitsPerSamplePair kBitsPerSamplePairs[4] = {
85     {.hal_bits_per_sample_ = BitsPerSample::BITS_UNKNOWN,
86      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE},
87     {.hal_bits_per_sample_ = BitsPerSample::BITS_16,
88      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16},
89     {.hal_bits_per_sample_ = BitsPerSample::BITS_24,
90      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24},
91     {.hal_bits_per_sample_ = BitsPerSample::BITS_32,
92      .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32}};
93 
94 struct ChannelModePair {
95   ChannelMode hal_channel_mode_;
96   btav_a2dp_codec_channel_mode_t btav_channel_mode_;
97 };
98 constexpr ChannelModePair kChannelModePairs[3] = {
99     {.hal_channel_mode_ = ChannelMode::UNKNOWN,
100      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE},
101     {.hal_channel_mode_ = ChannelMode::MONO,
102      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO},
103     {.hal_channel_mode_ = ChannelMode::STEREO,
104      .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO}};
105 
106 constexpr btav_a2dp_codec_index_t codec_indexes[] = {
107     BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,  BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
108     BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
109     BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, BTAV_A2DP_CODEC_INDEX_SINK_SBC,
110     BTAV_A2DP_CODEC_INDEX_SINK_AAC,    BTAV_A2DP_CODEC_INDEX_SINK_LDAC};
111 constexpr uint16_t kPeerMtus[5] = {660, 663, 883, 1005, 1500};
112 
113 class TestTransport : public bluetooth::audio::IBluetoothTransportInstance {
114  private:
115   static constexpr uint64_t kRemoteDelayReportMs = 200;
116 
117  public:
TestTransport(SessionType session_type)118   TestTransport(SessionType session_type)
119       : bluetooth::audio::IBluetoothTransportInstance(session_type, {}){};
StartRequest()120   bluetooth::audio::BluetoothAudioCtrlAck StartRequest() override {
121     return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
122   }
SuspendRequest()123   bluetooth::audio::BluetoothAudioCtrlAck SuspendRequest() override {
124     return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
125   }
StopRequest()126   void StopRequest() override {}
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_readed,timespec * data_position)127   bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
128                                uint64_t* total_bytes_readed,
129                                timespec* data_position) override {
130     if (remote_delay_report_ns) {
131       *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
132     }
133     if (total_bytes_readed) {
134       *total_bytes_readed = 0;
135     }
136     if (data_position) {
137       clock_gettime(CLOCK_MONOTONIC, data_position);
138     }
139     return true;
140   }
MetadataChanged(const source_metadata_t & source_metadata __unused)141   void MetadataChanged(
142       const source_metadata_t& source_metadata __unused) override {}
ResetPresentationPosition()143   void ResetPresentationPosition() override{};
LogBytesRead(size_t bytes_readed __unused)144   void LogBytesRead(size_t bytes_readed __unused) override{};
145 };
146 
147 class BluetoothAudioClientInterfaceTest : public Test {
148  protected:
149   TestTransport* test_transport_ = nullptr;
150   BluetoothAudioClientInterface* clientif_ = nullptr;
151 
152   static constexpr int kClientIfReturnSuccess = 0;
153 
SetUp()154   void SetUp() override {}
155 
TearDown()156   void TearDown() override {
157     if (clientif_ != nullptr) delete clientif_;
158     clientif_ = nullptr;
159     if (test_transport_ != nullptr) delete test_transport_;
160     test_transport_ = nullptr;
161   }
162 
IsSoftwarePcmParametersSupported(const PcmParameters & pcm_config)163   bool IsSoftwarePcmParametersSupported(const PcmParameters& pcm_config) {
164     const std::vector<AudioCapabilities>& capabilities =
165         clientif_->GetAudioCapabilities();
166     PcmParameters pcm_capabilities = capabilities[0].pcmCapabilities();
167     bool is_pcm_config_valid =
168         (pcm_config.sampleRate != SampleRate::RATE_UNKNOWN &&
169          pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
170          pcm_config.channelMode != ChannelMode::UNKNOWN);
171     bool is_pcm_config_supported =
172         (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
173          pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
174          pcm_config.channelMode & pcm_capabilities.channelMode);
175     return (is_pcm_config_valid && is_pcm_config_supported);
176   }
177 
IsCodecOffloadingSupported(const CodecConfiguration & codec_config)178   bool IsCodecOffloadingSupported(const CodecConfiguration& codec_config) {
179     CodecCapabilities codec_capability = {};
180     for (auto audio_capability : clientif_->GetAudioCapabilities()) {
181       if (audio_capability.codecCapabilities().codecType ==
182           codec_config.codecType) {
183         codec_capability = audio_capability.codecCapabilities();
184       }
185     }
186     if (codec_capability.codecType != codec_config.codecType) {
187       // codec is unsupported
188       return false;
189     }
190     bool is_codec_config_supported = false;
191     switch (codec_config.codecType) {
192       case CodecType::SBC: {
193         SbcParameters sbc_config = codec_config.config.sbcConfig();
194         SbcParameters sbc_capability =
195             codec_capability.capabilities.sbcCapabilities();
196         is_codec_config_supported =
197             (sbc_config.sampleRate & sbc_capability.sampleRate &&
198              sbc_config.channelMode & sbc_capability.channelMode &&
199              sbc_config.blockLength & sbc_capability.blockLength &&
200              sbc_config.numSubbands & sbc_capability.numSubbands &&
201              sbc_config.allocMethod & sbc_capability.allocMethod &&
202              sbc_config.bitsPerSample & sbc_capability.bitsPerSample &&
203              (sbc_capability.minBitpool <= sbc_config.minBitpool &&
204               sbc_config.minBitpool <= sbc_config.maxBitpool &&
205               sbc_config.maxBitpool <= sbc_capability.maxBitpool));
206         return is_codec_config_supported;
207       }
208       case CodecType::AAC: {
209         AacParameters aac_config = codec_config.config.aacConfig();
210         AacParameters aac_capability =
211             codec_capability.capabilities.aacCapabilities();
212         is_codec_config_supported =
213             (aac_config.objectType & aac_capability.objectType &&
214              aac_config.sampleRate & aac_capability.sampleRate &&
215              aac_config.channelMode & aac_capability.channelMode &&
216              (aac_config.variableBitRateEnabled ==
217                   AacVariableBitRate::DISABLED ||
218               aac_capability.variableBitRateEnabled ==
219                   AacVariableBitRate::ENABLED) &&
220              aac_config.bitsPerSample & aac_capability.bitsPerSample);
221         return is_codec_config_supported;
222       }
223       case CodecType::LDAC: {
224         LdacParameters ldac_config = codec_config.config.ldacConfig();
225         LdacParameters ldac_capability =
226             codec_capability.capabilities.ldacCapabilities();
227         is_codec_config_supported =
228             (ldac_config.sampleRate & ldac_capability.sampleRate &&
229              ldac_config.channelMode & ldac_capability.channelMode &&
230              ldac_config.bitsPerSample & ldac_capability.bitsPerSample);
231         return is_codec_config_supported;
232       }
233       case CodecType::APTX:
234         [[fallthrough]];
235       case CodecType::APTX_HD: {
236         AptxParameters aptx_config = codec_config.config.aptxConfig();
237         AptxParameters aptx_capability =
238             codec_capability.capabilities.aptxCapabilities();
239         is_codec_config_supported =
240             (aptx_config.sampleRate & aptx_capability.sampleRate &&
241              aptx_config.channelMode & aptx_capability.channelMode &&
242              aptx_config.bitsPerSample & aptx_capability.bitsPerSample);
243         return is_codec_config_supported;
244       }
245       case CodecType::UNKNOWN:
246         return false;
247     }
248   }
249 };
250 
251 }  // namespace
252 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpCodecToHalPcmConfig)253 TEST_F(BluetoothAudioClientInterfaceTest, A2dpCodecToHalPcmConfig) {
254   btav_a2dp_codec_config_t a2dp_codec_config = {};
255   for (auto sample_rate_pair : kSampleRatePairs) {
256     a2dp_codec_config.sample_rate = sample_rate_pair.btav_sample_rate_;
257     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
258       a2dp_codec_config.bits_per_sample =
259           bits_per_sample_pair.btav_bits_per_sample_;
260       for (auto channel_mode_pair : kChannelModePairs) {
261         a2dp_codec_config.channel_mode = channel_mode_pair.btav_channel_mode_;
262         EXPECT_EQ(A2dpCodecToHalSampleRate(a2dp_codec_config),
263                   sample_rate_pair.hal_sample_rate_);
264         EXPECT_EQ(A2dpCodecToHalBitsPerSample(a2dp_codec_config),
265                   bits_per_sample_pair.hal_bits_per_sample_);
266         EXPECT_EQ(A2dpCodecToHalChannelMode(a2dp_codec_config),
267                   channel_mode_pair.hal_channel_mode_);
268       }  // ChannelMode
269     }    // BitsPerSampple
270   }      // SampleRate
271 }
272 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpSoftwareSession)273 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpSoftwareSession) {
274   test_transport_ =
275       new TestTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
276   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
277   AudioConfiguration audio_config = {};
278   PcmParameters pcm_config = {};
279   for (auto sample_rate_pair : kSampleRatePairs) {
280     pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
281     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
282       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
283       for (auto channel_mode_pair : kChannelModePairs) {
284         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
285         audio_config.pcmConfig(pcm_config);
286         clientif_->UpdateAudioConfig(audio_config);
287         if (IsSoftwarePcmParametersSupported(pcm_config)) {
288           EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
289         } else {
290           EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
291         }
292         EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
293       }  // ChannelMode
294     }    // BitsPerSampple
295   }      // SampleRate
296 }
297 
298 struct CodecOffloadingPreference {
299   bool is_target_codec_included_;
300   std::vector<btav_a2dp_codec_config_t> preference_;
301 };
302 
CodecOffloadingPreferenceGenerator(btav_a2dp_codec_index_t target_codec_index)303 std::vector<CodecOffloadingPreference> CodecOffloadingPreferenceGenerator(
304     btav_a2dp_codec_index_t target_codec_index) {
305   std::vector<CodecOffloadingPreference> codec_offloading_preferences = {
306       {.is_target_codec_included_ = false,
307        .preference_ = std::vector<btav_a2dp_codec_config_t>(0)}};
308   btav_a2dp_codec_config_t a2dp_codec_config = {};
309   for (auto codec_index : codec_indexes) {
310     a2dp_codec_config.codec_type = codec_index;
311     auto duplicated_preferences = codec_offloading_preferences;
312     for (auto iter = duplicated_preferences.begin();
313          iter != duplicated_preferences.end(); ++iter) {
314       if (codec_index == target_codec_index) {
315         iter->is_target_codec_included_ = true;
316       }
317       iter->preference_.push_back(a2dp_codec_config);
318     }
319     codec_offloading_preferences.insert(codec_offloading_preferences.end(),
320                                         duplicated_preferences.begin(),
321                                         duplicated_preferences.end());
322   }
323   return codec_offloading_preferences;
324 }
325 
SbcCodecConfigurationsGenerator()326 std::vector<CodecConfiguration> SbcCodecConfigurationsGenerator() {
327   std::vector<CodecConfiguration> sbc_codec_configs;
328   CodecConfiguration codec_config = {};
329   SbcBlockLength block_lengths[4] = {
330       SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8,
331       SbcBlockLength::BLOCKS_12, SbcBlockLength::BLOCKS_16};
332   SbcNumSubbands num_subbands[2] = {SbcNumSubbands::SUBBAND_4,
333                                     SbcNumSubbands::SUBBAND_8};
334   SbcAllocMethod alloc_methods[2] = {SbcAllocMethod::ALLOC_MD_S,
335                                      SbcAllocMethod::ALLOC_MD_L};
336   for (auto sample_rate_pair : kSampleRatePairs) {
337     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
338       for (auto channel_mode_pair : kChannelModePairs) {
339         for (auto peer_mtu : kPeerMtus) {
340           for (auto block_length : block_lengths) {
341             for (auto num_subband : num_subbands) {
342               for (auto alloc_method : alloc_methods) {
343                 codec_config.codecType = CodecType::SBC;
344                 codec_config.peerMtu = peer_mtu;
345                 codec_config.isScmstEnabled = false;
346                 // A2DP_SBC_DEFAULT_BITRATE
347                 codec_config.encodedAudioBitrate = 328000;
348                 SbcParameters sbc = {
349                     .sampleRate = sample_rate_pair.hal_sample_rate_,
350                     .channelMode = (channel_mode_pair.hal_channel_mode_ ==
351                                             ChannelMode::MONO
352                                         ? SbcChannelMode::MONO
353                                         : SbcChannelMode::JOINT_STEREO),
354                     .blockLength = block_length,
355                     .numSubbands = num_subband,
356                     .allocMethod = alloc_method,
357                     .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_,
358                     .minBitpool = 2,
359                     .maxBitpool = 53};
360                 codec_config.config.sbcConfig(sbc);
361                 sbc_codec_configs.push_back(codec_config);
362               }  // SbcAllocMethod
363             }    // SbcNumSubbands
364           }      // SbcBlockLength
365         }        // peerMtu
366       }          // ChannelMode
367     }            // BitsPerSampple
368   }              // SampleRate
369   return sbc_codec_configs;
370 }
371 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpSbcCodecOffloadingState)372 TEST_F(BluetoothAudioClientInterfaceTest, A2dpSbcCodecOffloadingState) {
373   test_transport_ =
374       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
375   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
376   auto sbc_codec_configs = SbcCodecConfigurationsGenerator();
377   for (auto codec_offloading_preference :
378        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC)) {
379     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
380     for (CodecConfiguration codec_config : sbc_codec_configs) {
381       if (IsCodecOffloadingSupported(codec_config) &&
382           codec_offloading_preference.is_target_codec_included_) {
383         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
384       } else {
385         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
386       }
387     }
388   }
389 }
390 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadSbcSession)391 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) {
392   test_transport_ =
393       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
394   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
395   AudioConfiguration audio_config = {};
396   for (CodecConfiguration codec_config : SbcCodecConfigurationsGenerator()) {
397     audio_config.codecConfig(codec_config);
398     clientif_->UpdateAudioConfig(audio_config);
399     if (IsCodecOffloadingSupported(codec_config)) {
400       EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
401     } else {
402       EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
403     }
404     EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
405   }
406 }
407 
AacCodecConfigurationsGenerator()408 std::vector<CodecConfiguration> AacCodecConfigurationsGenerator() {
409   std::vector<CodecConfiguration> aac_codec_configs;
410   CodecConfiguration codec_config = {};
411   AacObjectType object_types[4] = {
412       AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC,
413       AacObjectType::MPEG4_LTP, AacObjectType::MPEG4_SCALABLE};
414   AacVariableBitRate variable_bitrates[2] = {AacVariableBitRate::DISABLED,
415                                              AacVariableBitRate::ENABLED};
416   for (auto sample_rate_pair : kSampleRatePairs) {
417     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
418       for (auto channel_mode_pair : kChannelModePairs) {
419         for (auto peer_mtu : kPeerMtus) {
420           for (auto object_type : object_types) {
421             for (auto variable_bitrate : variable_bitrates) {
422               codec_config.codecType = CodecType::AAC;
423               codec_config.peerMtu = peer_mtu;
424               codec_config.isScmstEnabled = false;
425               // A2DP_AAC_DEFAULT_BITRATE
426               codec_config.encodedAudioBitrate = 320000;
427               AacParameters aac = {
428                   .objectType = object_type,
429                   .sampleRate = sample_rate_pair.hal_sample_rate_,
430                   .channelMode = channel_mode_pair.hal_channel_mode_,
431                   .variableBitRateEnabled = variable_bitrate,
432                   .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
433               codec_config.config.aacConfig(aac);
434               aac_codec_configs.push_back(codec_config);
435             }  // AacVariableBitRate
436           }    // AacObjectType
437         }      // peerMtu
438       }        // ChannelMode
439     }          // BitsPerSampple
440   }            // SampleRate
441   return aac_codec_configs;
442 }
443 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAacCodecOffloadingState)444 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAacCodecOffloadingState) {
445   test_transport_ =
446       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
447   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
448   auto aac_codec_configs = AacCodecConfigurationsGenerator();
449   for (auto codec_offloading_preference :
450        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC)) {
451     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
452     for (CodecConfiguration codec_config : aac_codec_configs) {
453       if (IsCodecOffloadingSupported(codec_config) &&
454           codec_offloading_preference.is_target_codec_included_) {
455         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
456       } else {
457         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
458       }
459     }
460   }
461 }
462 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadAacSession)463 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) {
464   test_transport_ =
465       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
466   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
467   AudioConfiguration audio_config = {};
468   for (CodecConfiguration codec_config : AacCodecConfigurationsGenerator()) {
469     audio_config.codecConfig(codec_config);
470     clientif_->UpdateAudioConfig(audio_config);
471     if (IsCodecOffloadingSupported(codec_config)) {
472       EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
473     } else {
474       EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
475     }
476     EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
477   }
478 }
479 
LdacCodecConfigurationsGenerator()480 std::vector<CodecConfiguration> LdacCodecConfigurationsGenerator() {
481   std::vector<CodecConfiguration> ldac_codec_configs;
482   CodecConfiguration codec_config = {};
483   LdacQualityIndex quality_indexes[4] = {
484       LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
485       LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
486   for (auto sample_rate_pair : kSampleRatePairs) {
487     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
488       for (auto channel_mode_pair : kChannelModePairs) {
489         for (auto peer_mtu : kPeerMtus) {
490           for (auto quality_index : quality_indexes) {
491             codec_config.codecType = CodecType::LDAC;
492             codec_config.peerMtu = peer_mtu;
493             codec_config.isScmstEnabled = false;
494             codec_config.encodedAudioBitrate = 990000;
495             LdacParameters ldac = {
496                 .sampleRate = sample_rate_pair.hal_sample_rate_,
497                 .channelMode =
498                     (channel_mode_pair.hal_channel_mode_ == ChannelMode::MONO
499                          ? LdacChannelMode::MONO
500                          : LdacChannelMode::STEREO),
501                 .qualityIndex = quality_index,
502                 .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
503             codec_config.config.ldacConfig(ldac);
504             ldac_codec_configs.push_back(codec_config);
505           }  // LdacQualityIndex
506         }    // peerMtu
507       }      // ChannelMode
508     }        // BitsPerSampple
509   }          // SampleRate
510   return ldac_codec_configs;
511 }
512 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpLdacCodecOffloadingState)513 TEST_F(BluetoothAudioClientInterfaceTest, A2dpLdacCodecOffloadingState) {
514   test_transport_ =
515       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
516   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
517   auto ldac_codec_configs = LdacCodecConfigurationsGenerator();
518   for (auto codec_offloading_preference :
519        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC)) {
520     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
521     for (CodecConfiguration codec_config : ldac_codec_configs) {
522       if (IsCodecOffloadingSupported(codec_config) &&
523           codec_offloading_preference.is_target_codec_included_) {
524         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
525       } else {
526         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
527       }
528     }
529   }
530 }
531 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadLdacSession)532 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) {
533   test_transport_ =
534       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
535   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
536   AudioConfiguration audio_config = {};
537   for (CodecConfiguration codec_config : LdacCodecConfigurationsGenerator()) {
538     audio_config.codecConfig(codec_config);
539     clientif_->UpdateAudioConfig(audio_config);
540     if (IsCodecOffloadingSupported(codec_config)) {
541       EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
542     } else {
543       EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
544     }
545     EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
546   }
547 }
548 
AptxCodecConfigurationsGenerator(CodecType codec_type)549 std::vector<CodecConfiguration> AptxCodecConfigurationsGenerator(
550     CodecType codec_type) {
551   std::vector<CodecConfiguration> aptx_codec_configs;
552   if (codec_type != CodecType::APTX && codec_type != CodecType::APTX_HD)
553     return aptx_codec_configs;
554   CodecConfiguration codec_config = {};
555   for (auto sample_rate_pair : kSampleRatePairs) {
556     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
557       for (auto channel_mode_pair : kChannelModePairs) {
558         for (auto peer_mtu : kPeerMtus) {
559           codec_config.codecType = codec_type;
560           codec_config.peerMtu = peer_mtu;
561           codec_config.isScmstEnabled = false;
562           codec_config.encodedAudioBitrate =
563               (codec_type == CodecType::APTX ? 352000 : 576000);
564           AptxParameters aptx = {
565               .sampleRate = sample_rate_pair.hal_sample_rate_,
566               .channelMode = channel_mode_pair.hal_channel_mode_,
567               .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
568           codec_config.config.aptxConfig(aptx);
569           aptx_codec_configs.push_back(codec_config);
570         }  // peerMtu
571       }    // ChannelMode
572     }      // BitsPerSampple
573   }        // SampleRate
574   return aptx_codec_configs;
575 }
576 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAptxCodecOffloadingState)577 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxCodecOffloadingState) {
578   test_transport_ =
579       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
580   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
581   auto aptx_codec_configs = AptxCodecConfigurationsGenerator(CodecType::APTX);
582   for (auto codec_offloading_preference :
583        CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX)) {
584     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
585     for (CodecConfiguration codec_config : aptx_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,StartAndEndA2dpOffloadAptxSession)596 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxSession) {
597   test_transport_ =
598       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
599   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
600   AudioConfiguration audio_config = {};
601   for (CodecConfiguration codec_config :
602        AptxCodecConfigurationsGenerator(CodecType::APTX)) {
603     audio_config.codecConfig(codec_config);
604     clientif_->UpdateAudioConfig(audio_config);
605     if (IsCodecOffloadingSupported(codec_config)) {
606       EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
607     } else {
608       EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
609     }
610     EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
611   }
612 }
613 
TEST_F(BluetoothAudioClientInterfaceTest,A2dpAptxHdCodecOffloadingState)614 TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxHdCodecOffloadingState) {
615   test_transport_ =
616       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
617   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
618   auto aptx_hd_codec_configs =
619       AptxCodecConfigurationsGenerator(CodecType::APTX_HD);
620   for (auto codec_offloading_preference : CodecOffloadingPreferenceGenerator(
621            BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD)) {
622     UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
623     for (CodecConfiguration codec_config : aptx_hd_codec_configs) {
624       if (IsCodecOffloadingSupported(codec_config) &&
625           codec_offloading_preference.is_target_codec_included_) {
626         ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
627       } else {
628         ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
629       }
630     }
631   }
632 }
633 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadAptxHdSession)634 TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxHdSession) {
635   test_transport_ =
636       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
637   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
638   AudioConfiguration audio_config = {};
639   for (CodecConfiguration codec_config :
640        AptxCodecConfigurationsGenerator(CodecType::APTX_HD)) {
641     audio_config.codecConfig(codec_config);
642     clientif_->UpdateAudioConfig(audio_config);
643     if (IsCodecOffloadingSupported(codec_config)) {
644       EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
645     } else {
646       EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
647     }
648     EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
649   }
650 }
651 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndA2dpOffloadUnknownSession)652 TEST_F(BluetoothAudioClientInterfaceTest,
653        StartAndEndA2dpOffloadUnknownSession) {
654   test_transport_ =
655       new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
656   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
657   AudioConfiguration audio_config = {};
658   CodecConfiguration codec_config = {};
659   codec_config.codecType = CodecType::UNKNOWN;
660   codec_config.peerMtu = 1005;
661   codec_config.isScmstEnabled = false;
662   codec_config.encodedAudioBitrate = 328000;
663   codec_config.config = {};
664   audio_config.codecConfig(codec_config);
665   clientif_->UpdateAudioConfig(audio_config);
666   if (IsCodecOffloadingSupported(codec_config)) {
667     EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
668   } else {
669     EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
670   }
671   EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
672 }
673 
TEST_F(BluetoothAudioClientInterfaceTest,StartAndEndHearingAidSoftwareSession)674 TEST_F(BluetoothAudioClientInterfaceTest,
675        StartAndEndHearingAidSoftwareSession) {
676   test_transport_ =
677       new TestTransport(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
678   clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
679   AudioConfiguration audio_config = {};
680   PcmParameters pcm_config = {};
681   for (auto sample_rate_pair : kSampleRatePairs) {
682     pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
683     for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
684       pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
685       for (auto channel_mode_pair : kChannelModePairs) {
686         pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
687         audio_config.pcmConfig(pcm_config);
688         clientif_->UpdateAudioConfig(audio_config);
689         if (IsSoftwarePcmParametersSupported(pcm_config)) {
690           EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
691         } else {
692           EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
693         }
694         EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
695       }  // ChannelMode
696     }    // BitsPerSampple
697   }      // SampleRate
698 }
699