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