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