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