1 /*
2  * Copyright 2022 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 "BTAudioHalDeviceProxyHIDL"
18 
19 #include "device_port_proxy_hidl.h"
20 
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.h>
23 #include <audio_utils/primitives.h>
24 #include <inttypes.h>
25 #include <stdlib.h>
26 
27 #include "BluetoothAudioSessionControl_2_1.h"
28 #include "stream_apis.h"
29 #include "utils.h"
30 
31 namespace android {
32 namespace bluetooth {
33 namespace audio {
34 namespace hidl {
35 
36 using ::android::base::StringPrintf;
37 using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1;
38 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
39 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
40 using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
41 using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
42 using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
43 using BluetoothAudioStatusHidl = ::android::hardware::bluetooth::audio::V2_0::Status;
44 using ControlResultCallback = std::function<void(uint16_t cookie, bool start_resp,
45                                                  const BluetoothAudioStatusHidl& status)>;
46 using SessionChangedCallback = std::function<void(uint16_t cookie)>;
47 
48 namespace {
49 
SampleRateToAudioFormat(SampleRate_2_1 sample_rate)50 unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) {
51   switch (sample_rate) {
52     case SampleRate_2_1::RATE_8000:
53       return 8000;
54     case SampleRate_2_1::RATE_16000:
55       return 16000;
56     case SampleRate_2_1::RATE_24000:
57       return 24000;
58     case SampleRate_2_1::RATE_32000:
59       return 32000;
60     case SampleRate_2_1::RATE_44100:
61       return 44100;
62     case SampleRate_2_1::RATE_48000:
63       return 48000;
64     case SampleRate_2_1::RATE_88200:
65       return 88200;
66     case SampleRate_2_1::RATE_96000:
67       return 96000;
68     case SampleRate_2_1::RATE_176400:
69       return 176400;
70     case SampleRate_2_1::RATE_192000:
71       return 192000;
72     default:
73       return kBluetoothDefaultSampleRate;
74   }
75 }
OutputChannelModeToAudioFormat(ChannelMode channel_mode)76 audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
77   switch (channel_mode) {
78     case ChannelMode::MONO:
79       return AUDIO_CHANNEL_OUT_MONO;
80     case ChannelMode::STEREO:
81       return AUDIO_CHANNEL_OUT_STEREO;
82     default:
83       return kBluetoothDefaultOutputChannelModeMask;
84   }
85 }
86 
InputChannelModeToAudioFormat(ChannelMode channel_mode)87 audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) {
88   switch (channel_mode) {
89     case ChannelMode::MONO:
90       return AUDIO_CHANNEL_IN_MONO;
91     case ChannelMode::STEREO:
92       return AUDIO_CHANNEL_IN_STEREO;
93     default:
94       return kBluetoothDefaultInputChannelModeMask;
95   }
96 }
97 
BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample)98 audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) {
99   switch (bits_per_sample) {
100     case BitsPerSample::BITS_16:
101       return AUDIO_FORMAT_PCM_16_BIT;
102     case BitsPerSample::BITS_24:
103       return AUDIO_FORMAT_PCM_24_BIT_PACKED;
104     case BitsPerSample::BITS_32:
105       return AUDIO_FORMAT_PCM_32_BIT;
106     default:
107       return kBluetoothDefaultAudioFormatBitsPerSample;
108   }
109 }
110 
111 // The maximum time to wait in std::condition_variable::wait_for()
112 constexpr unsigned int kMaxWaitingTimeMs = 4500;
113 
114 }  // namespace
115 
BluetoothAudioPortHidl()116 BluetoothAudioPortHidl::BluetoothAudioPortHidl()
117     : session_type_hidl_(SessionType_2_1::UNKNOWN),
118       cookie_(android::bluetooth::audio::kObserversCookieUndefined),
119       state_(BluetoothStreamState::DISABLED) {}
120 
~BluetoothAudioPortHidlOut()121 BluetoothAudioPortHidlOut::~BluetoothAudioPortHidlOut() {
122   if (BluetoothAudioPortHidl::in_use()) {
123     BluetoothAudioPortHidl::TearDown();
124   }
125 }
126 
~BluetoothAudioPortHidlIn()127 BluetoothAudioPortHidlIn::~BluetoothAudioPortHidlIn() {
128   if (BluetoothAudioPortHidl::in_use()) {
129     BluetoothAudioPortHidl::TearDown();
130   }
131 }
132 
SetUp(audio_devices_t devices)133 bool BluetoothAudioPortHidl::SetUp(audio_devices_t devices) {
134   if (!init_session_type(devices)) {
135     return false;
136   }
137 
138   state_ = BluetoothStreamState::STANDBY;
139 
140   auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/,
141                                          const BluetoothAudioStatusHidl& status) {
142     if (!port->in_use()) {
143       LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use";
144       return;
145     }
146     if (port->cookie_ != cookie) {
147       LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
148                  << StringPrintf("%#hx", cookie) << ") is corrupted";
149       return;
150     }
151     port->ControlResultHandler(status);
152   };
153   auto session_changed_cb = [port = this](uint16_t cookie) {
154     if (!port->in_use()) {
155       LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use";
156       return;
157     }
158     if (port->cookie_ != cookie) {
159       LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
160                  << StringPrintf("%#hx", cookie) << ") is corrupted";
161       return;
162     }
163     port->SessionChangedHandler();
164   };
165   ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
166           .control_result_cb_ = control_result_cb, .session_changed_cb_ = session_changed_cb};
167   cookie_ =
168           BluetoothAudioSessionControl_2_1::RegisterControlResultCback(session_type_hidl_, cbacks);
169   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
170             << ", cookie=" << StringPrintf("%#hx", cookie_);
171 
172   return cookie_ != android::bluetooth::audio::kObserversCookieUndefined;
173 }
174 
init_session_type(audio_devices_t device)175 bool BluetoothAudioPortHidl::init_session_type(audio_devices_t device) {
176   switch (device) {
177     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
178     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
179     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
180       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
181                    << StringPrintf("%#x", device) << ")";
182       session_type_hidl_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
183       break;
184     case AUDIO_DEVICE_OUT_HEARING_AID:
185       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
186                    << StringPrintf("%#x", device) << ")";
187       session_type_hidl_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
188       break;
189     case AUDIO_DEVICE_OUT_BLE_HEADSET:
190       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
191                    << StringPrintf("%#x", device) << ")";
192       session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
193       break;
194     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
195       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
196                    << StringPrintf("%#x", device) << ")";
197       session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
198       break;
199     case AUDIO_DEVICE_IN_BLE_HEADSET:
200       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
201                    << StringPrintf("%#x", device) << ")";
202       session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
203       break;
204     default:
205       LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
206       return false;
207   }
208 
209   if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_hidl_)) {
210     LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
211                << ", session_type=" << toString(session_type_hidl_) << " is not ready";
212     return false;
213   }
214   return true;
215 }
216 
TearDown()217 void BluetoothAudioPortHidl::TearDown() {
218   if (!in_use()) {
219     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
220                << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
221     return;
222   }
223 
224   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
225             << ", cookie=" << StringPrintf("%#hx", cookie_);
226   BluetoothAudioSessionControl_2_1::UnregisterControlResultCback(session_type_hidl_, cookie_);
227   cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
228 }
229 
ControlResultHandler(const BluetoothAudioStatusHidl & status)230 void BluetoothAudioPortHidl::ControlResultHandler(const BluetoothAudioStatusHidl& status) {
231   if (!in_use()) {
232     LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use";
233     return;
234   }
235   std::unique_lock<std::mutex> port_lock(cv_mutex_);
236   BluetoothStreamState previous_state = state_;
237   LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_hidl_)
238             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
239             << ", status=" << toString(status);
240 
241   switch (previous_state) {
242     case BluetoothStreamState::STARTED:
243       /* Only Suspend signal can be send in STARTED state*/
244       if (status == BluetoothAudioStatus::SUCCESS) {
245         state_ = BluetoothStreamState::STANDBY;
246       } else {
247         // Set to standby since the stack may be busy switching between outputs
248         LOG(WARNING) << "control_result_cb: status=" << toString(status)
249                      << " failure for session_type=" << toString(session_type_hidl_)
250                      << ", cookie=" << StringPrintf("%#hx", cookie_)
251                      << ", previous_state=" << previous_state;
252       }
253       break;
254     case BluetoothStreamState::STARTING:
255       if (status == BluetoothAudioStatusHidl::SUCCESS) {
256         state_ = BluetoothStreamState::STARTED;
257       } else {
258         // Set to standby since the stack may be busy switching between outputs
259         LOG(WARNING) << "control_result_cb: status=" << toString(status)
260                      << " failure for session_type=" << toString(session_type_hidl_)
261                      << ", cookie=" << StringPrintf("%#hx", cookie_)
262                      << ", previous_state=" << previous_state;
263         state_ = BluetoothStreamState::STANDBY;
264       }
265       break;
266     case BluetoothStreamState::SUSPENDING:
267       if (status == BluetoothAudioStatusHidl::SUCCESS) {
268         state_ = BluetoothStreamState::STANDBY;
269       } else {
270         // It will be failed if the headset is disconnecting, and set to disable
271         // to wait for re-init again
272         LOG(WARNING) << "control_result_cb: status=" << toString(status)
273                      << " failure for session_type=" << toString(session_type_hidl_)
274                      << ", cookie=" << StringPrintf("%#hx", cookie_)
275                      << ", previous_state=" << previous_state;
276         state_ = BluetoothStreamState::DISABLED;
277       }
278       break;
279     default:
280       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
281                  << " for session_type=" << toString(session_type_hidl_)
282                  << ", cookie=" << StringPrintf("%#hx", cookie_)
283                  << ", previous_state=" << previous_state;
284       return;
285   }
286   port_lock.unlock();
287   internal_cv_.notify_all();
288 }
289 
SessionChangedHandler()290 void BluetoothAudioPortHidl::SessionChangedHandler() {
291   if (!in_use()) {
292     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
293     return;
294   }
295   std::unique_lock<std::mutex> port_lock(cv_mutex_);
296   BluetoothStreamState previous_state = state_;
297   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_hidl_)
298             << ", cookie=" << StringPrintf("%#hx", cookie_)
299             << ", previous_state=" << previous_state;
300   state_ = BluetoothStreamState::DISABLED;
301   port_lock.unlock();
302   internal_cv_.notify_all();
303 }
304 
in_use() const305 bool BluetoothAudioPortHidl::in_use() const {
306   return cookie_ != android::bluetooth::audio::kObserversCookieUndefined;
307 }
308 
GetPreferredDataIntervalUs(size_t * interval_us) const309 bool BluetoothAudioPortHidl::GetPreferredDataIntervalUs(size_t* interval_us) const {
310   if (!in_use()) {
311     return false;
312   }
313 
314   const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& hal_audio_cfg =
315           BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
316   if (hal_audio_cfg.getDiscriminator() !=
317       ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::hidl_discriminator::
318               pcmConfig) {
319     return false;
320   }
321 
322   const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
323           hal_audio_cfg.pcmConfig();
324   *interval_us = pcm_cfg.dataIntervalUs;
325   return true;
326 }
327 
CondwaitState(BluetoothStreamState state)328 bool BluetoothAudioPortHidl::CondwaitState(BluetoothStreamState state) {
329   bool retval;
330   std::unique_lock<std::mutex> port_lock(cv_mutex_);
331   switch (state) {
332     case BluetoothStreamState::STARTING:
333       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
334                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
335       retval = internal_cv_.wait_for(
336               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
337               [this] { return this->state_ != BluetoothStreamState::STARTING; });
338       retval = retval && state_ == BluetoothStreamState::STARTED;
339       break;
340     case BluetoothStreamState::SUSPENDING:
341       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
342                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
343       retval = internal_cv_.wait_for(
344               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
345               [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
346       retval = retval && state_ == BluetoothStreamState::STANDBY;
347       break;
348     default:
349       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_hidl_)
350                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
351       return false;
352   }
353 
354   return retval;  // false if any failure like timeout
355 }
356 
Start()357 bool BluetoothAudioPortHidl::Start() {
358   if (!in_use()) {
359     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
360     return false;
361   }
362 
363   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
364             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
365             << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
366   bool retval = false;
367   if (state_ == BluetoothStreamState::STANDBY) {
368     state_ = BluetoothStreamState::STARTING;
369     if (BluetoothAudioSessionControl_2_1::StartStream(session_type_hidl_)) {
370       retval = CondwaitState(BluetoothStreamState::STARTING);
371     } else {
372       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
373                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
374                  << " Hal fails";
375     }
376   }
377 
378   if (retval) {
379     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
380               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
381               << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
382   } else {
383     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
384                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
385                << " failure";
386   }
387 
388   return retval;  // false if any failure like timeout
389 }
390 
Suspend()391 bool BluetoothAudioPortHidl::Suspend() {
392   if (!in_use()) {
393     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
394     return false;
395   }
396 
397   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
398             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
399   bool retval = false;
400   if (state_ == BluetoothStreamState::STARTED) {
401     state_ = BluetoothStreamState::SUSPENDING;
402     if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_hidl_)) {
403       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
404     } else {
405       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
406                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
407                  << " Hal fails";
408     }
409   }
410 
411   if (retval) {
412     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
413               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
414   } else {
415     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
416                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
417                << " failure";
418   }
419 
420   return retval;  // false if any failure like timeout
421 }
422 
Stop()423 void BluetoothAudioPortHidl::Stop() {
424   if (!in_use()) {
425     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
426     return;
427   }
428   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
429             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
430   state_ = BluetoothStreamState::DISABLED;
431   BluetoothAudioSessionControl_2_1::StopStream(session_type_hidl_);
432   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
433             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
434 }
435 
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const436 bool BluetoothAudioPortHidl::GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
437                                                      timespec* timestamp) const {
438   if (!in_use()) {
439     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
440     return false;
441   }
442   bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition(
443           session_type_hidl_, delay_ns, bytes, timestamp);
444   LOG(VERBOSE) << __func__ << ": session_type="
445                << StringPrintf("%#x", static_cast<unsigned>(session_type_hidl_))
446                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
447                << ", delay=" << *delay_ns << "ns, data=" << *bytes
448                << " bytes, timestamp=" << timestamp->tv_sec << "."
449                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
450 
451   return retval;
452 }
453 
UpdateTracksMetadata(const source_metadata * source_metadata) const454 void BluetoothAudioPortHidl::UpdateTracksMetadata(const source_metadata* source_metadata) const {
455   if (!in_use()) {
456     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
457     return;
458   }
459   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_hidl_)
460              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
461              << source_metadata->track_count << " track(s)";
462   if (source_metadata->track_count == 0) {
463     return;
464   }
465   BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_hidl_, source_metadata);
466 }
467 
GetState() const468 BluetoothStreamState BluetoothAudioPortHidl::GetState() const { return state_; }
469 
SetState(BluetoothStreamState state)470 void BluetoothAudioPortHidl::SetState(BluetoothStreamState state) { state_ = state; }
471 
WriteData(const void * buffer,size_t bytes) const472 size_t BluetoothAudioPortHidlOut::WriteData(const void* buffer, size_t bytes) const {
473   if (!BluetoothAudioPortHidl::in_use()) {
474     return 0;
475   }
476   if (!BluetoothAudioPortHidl::is_stereo_to_mono_) {
477     return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_hidl_, buffer, bytes);
478   }
479 
480   // WAR to mix the stereo into Mono (16 bits per sample)
481   const size_t write_frames = bytes >> 2;
482   if (write_frames == 0) {
483     return 0;
484   }
485   auto src = static_cast<const int16_t*>(buffer);
486   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
487   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
488   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
489   return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_hidl_, dst.get(),
490                                                            write_frames * 2) *
491          2;
492 }
493 
ReadData(void * buffer,size_t bytes) const494 size_t BluetoothAudioPortHidlIn::ReadData(void* buffer, size_t bytes) const {
495   if (!BluetoothAudioPortHidl::in_use()) {
496     return 0;
497   }
498   return BluetoothAudioSessionControl_2_1::InReadPcmData(session_type_hidl_, buffer, bytes);
499 }
500 
LoadAudioConfig(audio_config_t * audio_cfg) const501 bool BluetoothAudioPortHidlIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
502   if (!BluetoothAudioPortHidl::in_use()) {
503     LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use";
504     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
505     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
506     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
507     return false;
508   }
509 
510   const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& hal_audio_cfg =
511           BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
512   if (hal_audio_cfg.getDiscriminator() !=
513       ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::hidl_discriminator::
514               pcmConfig) {
515     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
516     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
517     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
518     return false;
519   }
520   const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
521           hal_audio_cfg.pcmConfig();
522   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
523                << ", cookie=" << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_)
524                << ", state=" << BluetoothAudioPortHidl::state_ << ", PcmConfig=["
525                << toString(pcm_cfg) << "]";
526   if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
527       pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
528       pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
529     return false;
530   }
531 
532   audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
533   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
534   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
535   return true;
536 }
537 
LoadAudioConfig(audio_config_t * audio_cfg) const538 bool BluetoothAudioPortHidlOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
539   if (!BluetoothAudioPortHidl::in_use()) {
540     LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
541     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
542     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
543     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
544     return false;
545   }
546 
547   const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& hal_audio_cfg =
548           BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
549   if (hal_audio_cfg.getDiscriminator() !=
550       ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::hidl_discriminator::
551               pcmConfig) {
552     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
553     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
554     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
555     return false;
556   }
557   const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
558           hal_audio_cfg.pcmConfig();
559   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
560                << ", cookie=" << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_)
561                << ", state=" << BluetoothAudioPortHidl::state_ << ", PcmConfig=["
562                << toString(pcm_cfg) << "]";
563   if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
564       pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
565       pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
566     return false;
567   }
568   audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
569   audio_cfg->channel_mask = (BluetoothAudioPortHidl::is_stereo_to_mono_
570                                      ? AUDIO_CHANNEL_OUT_STEREO
571                                      : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
572   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
573   return true;
574 }
575 
576 }  // namespace hidl
577 }  // namespace audio
578 }  // namespace bluetooth
579 }  // namespace android
580