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