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 "BTAudioHalDeviceProxyAIDL"
18
19 #include "device_port_proxy.h"
20
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.h>
23 #include <audio_utils/primitives.h>
24 #include <stdlib.h>
25
26 #include <vector>
27
28 #include "BluetoothAudioSessionControl.h"
29 #include "stream_apis.h"
30
31 namespace android {
32 namespace bluetooth {
33 namespace audio {
34 namespace aidl {
35
36 using ::aidl::android::hardware::audio::common::SinkMetadata;
37 using ::aidl::android::hardware::audio::common::SourceMetadata;
38 using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
39 using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
40 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
41 using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
42 using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
43 using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
44 using ::aidl::android::media::audio::common::AudioContentType;
45 using ::aidl::android::media::audio::common::AudioSource;
46 using ::aidl::android::media::audio::common::AudioUsage;
47
48 using ::android::base::StringPrintf;
49 using ControlResultCallback =
50 std::function<void(uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>;
51 using SessionChangedCallback = std::function<void(uint16_t cookie)>;
52
53 namespace {
54
OutputChannelModeToAudioFormat(ChannelMode channel_mode)55 audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
56 switch (channel_mode) {
57 case ChannelMode::MONO:
58 return AUDIO_CHANNEL_OUT_MONO;
59 case ChannelMode::STEREO:
60 return AUDIO_CHANNEL_OUT_STEREO;
61 default:
62 return kBluetoothDefaultOutputChannelModeMask;
63 }
64 }
65
InputChannelModeToAudioFormat(ChannelMode channel_mode)66 audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) {
67 switch (channel_mode) {
68 case ChannelMode::MONO:
69 return AUDIO_CHANNEL_IN_MONO;
70 case ChannelMode::STEREO:
71 return AUDIO_CHANNEL_IN_STEREO;
72 default:
73 return kBluetoothDefaultInputChannelModeMask;
74 }
75 }
76
BitsPerSampleToAudioFormat(uint8_t bits_per_sample,const SessionType & session_type)77 audio_format_t BitsPerSampleToAudioFormat(uint8_t bits_per_sample,
78 const SessionType& session_type) {
79 switch (bits_per_sample) {
80 case 16:
81 return AUDIO_FORMAT_PCM_16_BIT;
82 case 24:
83 /* Now we use knowledge that Classic sessions used packed, and LE Audio
84 * LC3 encoder uses unpacked as input. This should be passed as parameter
85 * from BT stack through AIDL, but it would require new interface version,
86 * so sticking with this workaround for now. */
87 if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
88 session_type == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
89 return AUDIO_FORMAT_PCM_24_BIT_PACKED;
90 } else {
91 return AUDIO_FORMAT_PCM_8_24_BIT;
92 }
93 case 32:
94 return AUDIO_FORMAT_PCM_32_BIT;
95 default:
96 return kBluetoothDefaultAudioFormatBitsPerSample;
97 }
98 }
99
CovertAudioTagFromV7(char * tags_v7)100 std::vector<std::string> CovertAudioTagFromV7(char* tags_v7) {
101 std::vector<std::string> tags;
102 char tags_copy[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE];
103 strlcpy(tags_copy, tags_v7, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
104 char* tmpstr;
105 char* tag = strtok_r(tags_copy, ";", &tmpstr);
106 while (tag != NULL) {
107 tags.push_back(tag);
108 tag = strtok_r(NULL, ";", &tmpstr);
109 }
110
111 return tags;
112 }
113
114 // The maximum time to wait in std::condition_variable::wait_for()
115 constexpr unsigned int kMaxWaitingTimeMs = 4500;
116
117 } // namespace
118
BluetoothAudioPortAidl()119 BluetoothAudioPortAidl::BluetoothAudioPortAidl()
120 : cookie_(::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined),
121 state_(BluetoothStreamState::DISABLED),
122 session_type_(SessionType::UNKNOWN),
123 latency_mode_callback_(NULL) {}
124
~BluetoothAudioPortAidlOut()125 BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
126 if (in_use()) {
127 TearDown();
128 }
129 }
130
~BluetoothAudioPortAidlIn()131 BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
132 if (in_use()) {
133 TearDown();
134 }
135 }
136
SetUp(audio_devices_t devices)137 bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
138 if (!init_session_type(devices)) {
139 return false;
140 }
141
142 state_ = BluetoothStreamState::STANDBY;
143
144 auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/,
145 const BluetoothAudioStatus& status) {
146 if (!port->in_use()) {
147 LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
148 return;
149 }
150 if (port->cookie_ != cookie) {
151 LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
152 << StringPrintf("%#hx", cookie) << ") is corrupted";
153 return;
154 }
155 port->ControlResultHandler(status);
156 };
157 auto session_changed_cb = [port = this](uint16_t cookie) {
158 if (!port->in_use()) {
159 LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
160 return;
161 }
162 if (port->cookie_ != cookie) {
163 LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
164 << StringPrintf("%#hx", cookie) << ") is corrupted";
165 return;
166 }
167 port->SessionChangedHandler();
168 };
169
170 auto low_latency_allowed_cb = [port = this](uint16_t cookie, bool allowed) {
171 if (!port->in_use()) {
172 LOG(ERROR) << "low_latency_allowed_cb: BluetoothAudioPortAidl is not in use";
173 return;
174 }
175 if (port->cookie_ != cookie) {
176 LOG(ERROR) << "low_latency_allowed_cb: proxy of device port (cookie="
177 << StringPrintf("%#hx", cookie) << ") is corrupted";
178 return;
179 }
180 port->LowLatencyAllowedHander(allowed);
181 };
182
183 // TODO: Add audio_config_changed_cb
184 PortStatusCallbacks cbacks = {
185 .control_result_cb_ = control_result_cb,
186 .session_changed_cb_ = session_changed_cb,
187 .low_latency_mode_allowed_cb_ = low_latency_allowed_cb,
188 };
189 cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(session_type_, cbacks);
190 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
191 << ", cookie=" << StringPrintf("%#hx", cookie_);
192
193 return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
194 }
195
init_session_type(audio_devices_t device)196 bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) {
197 switch (device) {
198 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
199 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
200 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
201 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
202 << StringPrintf("%#x", device) << ")";
203 session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
204 break;
205 case AUDIO_DEVICE_OUT_HEARING_AID:
206 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
207 << StringPrintf("%#x", device) << ")";
208 session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
209 break;
210 case AUDIO_DEVICE_OUT_BLE_HEADSET:
211 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
212 << StringPrintf("%#x", device) << ")";
213 session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
214 break;
215 case AUDIO_DEVICE_OUT_BLE_SPEAKER:
216 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
217 << StringPrintf("%#x", device) << ")";
218 session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
219 break;
220 case AUDIO_DEVICE_IN_BLE_HEADSET:
221 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
222 << StringPrintf("%#x", device) << ")";
223 session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
224 break;
225 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
226 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
227 << StringPrintf("%#x", device) << ")";
228 session_type_ = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
229 break;
230 default:
231 LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
232 return false;
233 }
234
235 if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
236 LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
237 << ", session_type=" << toString(session_type_) << " is not ready";
238 return false;
239 }
240 return true;
241 }
242
TearDown()243 void BluetoothAudioPortAidl::TearDown() {
244 if (!in_use()) {
245 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
246 << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
247 return;
248 }
249
250 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
251 << ", cookie=" << StringPrintf("%#hx", cookie_);
252 BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_, cookie_);
253 cookie_ = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
254 }
255
ControlResultHandler(const BluetoothAudioStatus & status)256 void BluetoothAudioPortAidl::ControlResultHandler(const BluetoothAudioStatus& status) {
257 if (!in_use()) {
258 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use";
259 return;
260 }
261 std::unique_lock<std::mutex> port_lock(cv_mutex_);
262 BluetoothStreamState previous_state = state_;
263 LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
264 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
265 << ", status=" << toString(status);
266
267 switch (previous_state) {
268 case BluetoothStreamState::STARTED:
269 /* Only Suspend signal can be send in STARTED state*/
270 if (status == BluetoothAudioStatus::RECONFIGURATION ||
271 status == BluetoothAudioStatus::SUCCESS) {
272 state_ = BluetoothStreamState::STANDBY;
273 } else {
274 // Set to standby since the stack may be busy switching between outputs
275 LOG(WARNING) << "control_result_cb: status=" << toString(status)
276 << " failure for session_type=" << toString(session_type_)
277 << ", cookie=" << StringPrintf("%#hx", cookie_)
278 << ", previous_state=" << previous_state;
279 }
280 break;
281 case BluetoothStreamState::STARTING:
282 if (status == BluetoothAudioStatus::SUCCESS) {
283 state_ = BluetoothStreamState::STARTED;
284 } else {
285 // Set to standby since the stack may be busy switching between outputs
286 LOG(WARNING) << "control_result_cb: status=" << toString(status)
287 << " failure for session_type=" << toString(session_type_)
288 << ", cookie=" << StringPrintf("%#hx", cookie_)
289 << ", previous_state=" << previous_state;
290 state_ = BluetoothStreamState::STANDBY;
291 }
292 break;
293 case BluetoothStreamState::SUSPENDING:
294 if (status == BluetoothAudioStatus::SUCCESS) {
295 state_ = BluetoothStreamState::STANDBY;
296 } else {
297 // It will be failed if the headset is disconnecting, and set to disable
298 // to wait for re-init again
299 LOG(WARNING) << "control_result_cb: status=" << toString(status)
300 << " failure for session_type=" << toString(session_type_)
301 << ", cookie=" << StringPrintf("%#hx", cookie_)
302 << ", previous_state=" << previous_state;
303 state_ = BluetoothStreamState::DISABLED;
304 }
305 break;
306 default:
307 LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
308 << " for session_type=" << toString(session_type_)
309 << ", cookie=" << StringPrintf("%#hx", cookie_)
310 << ", previous_state=" << previous_state;
311 return;
312 }
313 port_lock.unlock();
314 internal_cv_.notify_all();
315 }
316
SessionChangedHandler()317 void BluetoothAudioPortAidl::SessionChangedHandler() {
318 if (!in_use()) {
319 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
320 return;
321 }
322 std::unique_lock<std::mutex> port_lock(cv_mutex_);
323 BluetoothStreamState previous_state = state_;
324 LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
325 << ", cookie=" << StringPrintf("%#hx", cookie_)
326 << ", previous_state=" << previous_state;
327 state_ = BluetoothStreamState::DISABLED;
328 port_lock.unlock();
329 internal_cv_.notify_all();
330 }
331
LowLatencyAllowedHander(bool allowed)332 void BluetoothAudioPortAidl::LowLatencyAllowedHander(bool allowed) {
333 if (!in_use()) {
334 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
335 return;
336 }
337 LOG(INFO) << __func__ << ": allowed=" << allowed;
338 std::unique_lock<std::mutex> port_lock(cv_mutex_);
339 if (latency_mode_callback_) {
340 audio_latency_mode_t modes[2];
341 size_t num_modes = 2;
342 GetRecommendedLatencyModes(modes, &num_modes);
343 latency_mode_callback_(modes, num_modes, latency_mode_callback_cookie_);
344 }
345 port_lock.unlock();
346 }
347
in_use() const348 bool BluetoothAudioPortAidl::in_use() const {
349 return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
350 }
351
GetPreferredDataIntervalUs(size_t * interval_us) const352 bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(size_t* interval_us) const {
353 if (!in_use()) {
354 return false;
355 }
356
357 const AudioConfiguration& hal_audio_cfg =
358 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
359 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
360 return false;
361 }
362
363 const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
364 *interval_us = pcm_cfg.dataIntervalUs;
365 return true;
366 }
367
LoadAudioConfig(audio_config_t * audio_cfg) const368 bool BluetoothAudioPortAidlOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
369 if (!in_use()) {
370 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
371 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
372 audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
373 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
374 return false;
375 }
376
377 const AudioConfiguration& hal_audio_cfg =
378 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
379 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
380 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
381 audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
382 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
383 return false;
384 }
385 const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
386 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
387 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
388 << ", PcmConfig=[" << pcm_cfg.toString() << "]";
389 if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
390 return false;
391 }
392 audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
393 audio_cfg->channel_mask =
394 (is_stereo_to_mono_ ? AUDIO_CHANNEL_OUT_STEREO
395 : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
396 audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
397 return true;
398 }
399
LoadAudioConfig(audio_config_t * audio_cfg) const400 bool BluetoothAudioPortAidlIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
401 if (!in_use()) {
402 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
403 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
404 audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
405 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
406 return false;
407 }
408
409 const AudioConfiguration& hal_audio_cfg =
410 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
411 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
412 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
413 audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
414 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
415 return false;
416 }
417 const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
418 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
419 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
420 << ", PcmConfig=[" << pcm_cfg.toString() << "]";
421 if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
422 return false;
423 }
424
425 audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
426 audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
427 audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
428 return true;
429 }
430
CondwaitState(BluetoothStreamState state)431 bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
432 bool retval;
433 std::unique_lock<std::mutex> port_lock(cv_mutex_);
434 switch (state) {
435 case BluetoothStreamState::STARTING:
436 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
437 << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
438 retval = internal_cv_.wait_for(
439 port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
440 [this] { return this->state_ != BluetoothStreamState::STARTING; });
441 retval = retval && state_ == BluetoothStreamState::STARTED;
442 break;
443 case BluetoothStreamState::SUSPENDING:
444 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
445 << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
446 retval = internal_cv_.wait_for(
447 port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
448 [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
449 retval = retval && state_ == BluetoothStreamState::STANDBY;
450 break;
451 default:
452 LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
453 << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
454 return false;
455 }
456
457 return retval; // false if any failure like timeout
458 }
459
Start(bool low_latency)460 bool BluetoothAudioPortAidl::Start(bool low_latency) {
461 if (!in_use()) {
462 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
463 return false;
464 }
465
466 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
467 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
468 << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
469 bool retval = false;
470 if (state_ == BluetoothStreamState::STANDBY) {
471 state_ = BluetoothStreamState::STARTING;
472 if (BluetoothAudioSessionControl::StartStream(session_type_, low_latency)) {
473 retval = CondwaitState(BluetoothStreamState::STARTING);
474 } else {
475 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
476 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
477 << " Hal fails";
478 }
479 }
480
481 if (retval) {
482 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
483 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
484 << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
485 } else {
486 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
487 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
488 << " failure";
489 }
490
491 return retval; // false if any failure like timeout
492 }
493
Suspend()494 bool BluetoothAudioPortAidl::Suspend() {
495 if (!in_use()) {
496 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
497 return false;
498 }
499
500 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
501 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
502 bool retval = false;
503 if (state_ == BluetoothStreamState::STARTED) {
504 state_ = BluetoothStreamState::SUSPENDING;
505 if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
506 retval = CondwaitState(BluetoothStreamState::SUSPENDING);
507 } else {
508 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
509 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
510 << " Hal fails";
511 }
512 }
513
514 if (retval) {
515 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
516 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
517 } else {
518 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
519 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
520 << " failure";
521 }
522
523 return retval; // false if any failure like timeout
524 }
525
Stop()526 void BluetoothAudioPortAidl::Stop() {
527 if (!in_use()) {
528 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
529 return;
530 }
531 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
532 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
533 state_ = BluetoothStreamState::DISABLED;
534 BluetoothAudioSessionControl::StopStream(session_type_);
535 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
536 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
537 }
538
539 using ::aidl::android::hardware::bluetooth::audio::LatencyMode;
540
hidl_latency_mode_to_aidl(audio_latency_mode_t mode)541 static LatencyMode hidl_latency_mode_to_aidl(audio_latency_mode_t mode) {
542 LatencyMode a2dp_latency_mode = LatencyMode::UNKNOWN;
543 switch (mode) {
544 case AUDIO_LATENCY_MODE_FREE:
545 a2dp_latency_mode = LatencyMode::FREE;
546 break;
547 case AUDIO_LATENCY_MODE_LOW:
548 a2dp_latency_mode = LatencyMode::LOW_LATENCY;
549 break;
550 default:
551 a2dp_latency_mode = LatencyMode::UNKNOWN;
552 break;
553 }
554 return a2dp_latency_mode;
555 }
556
SetLatencyMode(audio_latency_mode_t mode)557 bool BluetoothAudioPortAidl::SetLatencyMode(audio_latency_mode_t mode) {
558 if (!in_use()) {
559 return false;
560 }
561
562 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", mode=" << mode;
563
564 BluetoothAudioSessionControl::SetLatencyMode(session_type_, hidl_latency_mode_to_aidl(mode));
565
566 return true;
567 }
568
GetRecommendedLatencyModes(audio_latency_mode_t * modes,size_t * num_modes)569 int BluetoothAudioPortAidl::GetRecommendedLatencyModes(audio_latency_mode_t* modes,
570 size_t* num_modes) {
571 if (!in_use()) {
572 return -ENOSYS;
573 }
574
575 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_);
576
577 std::vector<LatencyMode> a2dp_modes =
578 BluetoothAudioSessionControl::GetSupportedLatencyModes(session_type_);
579
580 size_t num_buffer = *num_modes;
581 if (num_buffer < a2dp_modes.size()) {
582 LOG(WARNING) << __func__ << ": audio buffer size " << num_buffer << " < " << a2dp_modes.size()
583 << " A2DP latency modes";
584 } else {
585 num_buffer = a2dp_modes.size();
586 LOG(DEBUG) << __func__ << ": get " << num_buffer << " A2DP latency modes";
587 }
588 *num_modes = 0;
589 for (int i = 0; i < num_buffer; i++) {
590 switch (a2dp_modes[i]) {
591 case LatencyMode::FREE:
592 *(modes + *num_modes) = AUDIO_LATENCY_MODE_FREE;
593 ++(*num_modes);
594 break;
595 case LatencyMode::LOW_LATENCY:
596 *(modes + *num_modes) = AUDIO_LATENCY_MODE_LOW;
597 ++(*num_modes);
598 break;
599 case LatencyMode::UNKNOWN:
600 default:
601 LOG(WARNING) << __func__ << ": ignore the " << i << "-th mode "
602 << toString(a2dp_modes[i]).c_str() << "%s unknown";
603 }
604 }
605 if (*num_modes != num_buffer) {
606 LOG(WARNING) << __func__ << ": correct num_modes " << num_buffer << " to " << *num_modes;
607 }
608 return 0;
609 }
610
SetLatencyModeCallback(stream_latency_mode_callback_t callback,void * cookie)611 int BluetoothAudioPortAidl::SetLatencyModeCallback(stream_latency_mode_callback_t callback,
612 void* cookie) {
613 if (!in_use()) {
614 return -ENOSYS;
615 }
616
617 if (callback != NULL && cookie == NULL) {
618 return -EINVAL;
619 }
620
621 std::unique_lock<std::mutex> port_lock(cv_mutex_);
622 latency_mode_callback_ = callback;
623 latency_mode_callback_cookie_ = cookie;
624 port_lock.unlock();
625
626 return 0;
627 }
628
WriteData(const void * buffer,size_t bytes) const629 size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer, size_t bytes) const {
630 if (!in_use()) {
631 return 0;
632 }
633 if (!is_stereo_to_mono_) {
634 return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
635 }
636
637 // WAR to mix the stereo into Mono (16 bits per sample)
638 const size_t write_frames = bytes >> 2;
639 if (write_frames == 0) {
640 return 0;
641 }
642 auto src = static_cast<const int16_t*>(buffer);
643 std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
644 downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
645 // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
646 return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) *
647 2;
648 }
649
ReadData(void * buffer,size_t bytes) const650 size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
651 if (!in_use()) {
652 return 0;
653 }
654 return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer, bytes);
655 }
656
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const657 bool BluetoothAudioPortAidl::GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
658 timespec* timestamp) const {
659 if (!in_use()) {
660 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
661 return false;
662 }
663 PresentationPosition presentation_position;
664 bool retval = BluetoothAudioSessionControl::GetPresentationPosition(session_type_,
665 presentation_position);
666 *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
667 *bytes = presentation_position.transmittedOctets;
668 *timestamp = {
669 .tv_sec = static_cast<__kernel_old_time_t>(
670 presentation_position.transmittedOctetsTimestamp.tvSec),
671 .tv_nsec = static_cast<long>(presentation_position.transmittedOctetsTimestamp.tvNSec)};
672 LOG(VERBOSE) << __func__
673 << ": session_type=" << StringPrintf("%#x", static_cast<unsigned>(session_type_))
674 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
675 << ", delay=" << *delay_ns << "ns, data=" << *bytes
676 << " bytes, timestamp=" << timestamp->tv_sec << "."
677 << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
678
679 return retval;
680 }
681
UpdateSourceMetadata(const source_metadata_v7 * source_metadata) const682 void BluetoothAudioPortAidl::UpdateSourceMetadata(const source_metadata_v7* source_metadata) const {
683 if (!in_use()) {
684 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
685 return;
686 }
687 LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
688 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
689 << source_metadata->track_count << " track(s)";
690 ssize_t track_count = source_metadata->track_count;
691 SourceMetadata hal_source_metadata;
692
693 if (track_count != 0) {
694 hal_source_metadata.tracks.resize(track_count);
695 for (int i = 0; i < track_count; i++) {
696 hal_source_metadata.tracks[i].usage =
697 static_cast<AudioUsage>(source_metadata->tracks[i].base.usage);
698 hal_source_metadata.tracks[i].contentType =
699 static_cast<AudioContentType>(source_metadata->tracks[i].base.content_type);
700 hal_source_metadata.tracks[i].tags = CovertAudioTagFromV7(source_metadata->tracks[i].tags);
701 }
702 }
703
704 BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_, hal_source_metadata);
705 }
706
UpdateSinkMetadata(const sink_metadata_v7 * sink_metadata) const707 void BluetoothAudioPortAidl::UpdateSinkMetadata(const sink_metadata_v7* sink_metadata) const {
708 if (!in_use()) {
709 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
710 return;
711 }
712 LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
713 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
714 << sink_metadata->track_count << " track(s)";
715 ssize_t track_count = sink_metadata->track_count;
716 SinkMetadata hal_sink_metadata;
717
718 if (track_count != 0) {
719 hal_sink_metadata.tracks.resize(track_count);
720 for (int i = 0; i < track_count; i++) {
721 hal_sink_metadata.tracks[i].source =
722 static_cast<AudioSource>(sink_metadata->tracks[i].base.source);
723 hal_sink_metadata.tracks[i].gain = sink_metadata->tracks[i].base.gain;
724 hal_sink_metadata.tracks[i].tags = CovertAudioTagFromV7(sink_metadata->tracks[i].tags);
725 }
726 }
727
728 BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_, hal_sink_metadata);
729 }
730
GetState() const731 BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
732
SetState(BluetoothStreamState state)733 void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) { state_ = state; }
734
735 } // namespace aidl
736 } // namespace audio
737 } // namespace bluetooth
738 } // namespace android
739