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 = std::function<void(
50 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 ==
88 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
89 session_type == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
90 return AUDIO_FORMAT_PCM_24_BIT_PACKED;
91 } else {
92 return AUDIO_FORMAT_PCM_8_24_BIT;
93 }
94 case 32:
95 return AUDIO_FORMAT_PCM_32_BIT;
96 default:
97 return kBluetoothDefaultAudioFormatBitsPerSample;
98 }
99 }
100
CovertAudioTagFromV7(char * tags_v7)101 std::vector<std::string> CovertAudioTagFromV7(char* tags_v7) {
102 std::vector<std::string> tags;
103 char tags_copy[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE];
104 strlcpy(tags_copy, tags_v7, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
105 char* tag = strtok(tags_copy, ";");
106
107 while (tag != NULL) {
108 tags.push_back(tag);
109 tag = strtok(NULL, ";");
110 }
111
112 return tags;
113 }
114
115 // The maximum time to wait in std::condition_variable::wait_for()
116 constexpr unsigned int kMaxWaitingTimeMs = 4500;
117
118 } // namespace
119
BluetoothAudioPortAidl()120 BluetoothAudioPortAidl::BluetoothAudioPortAidl()
121 : cookie_(::aidl::android::hardware::bluetooth::audio::
122 kObserversCookieUndefined),
123 state_(BluetoothStreamState::DISABLED),
124 session_type_(SessionType::UNKNOWN) {}
125
~BluetoothAudioPortAidlOut()126 BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
127 if (in_use()) TearDown();
128 }
129
~BluetoothAudioPortAidlIn()130 BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
131 if (in_use()) TearDown();
132 }
133
SetUp(audio_devices_t devices)134 bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
135 if (!init_session_type(devices)) return false;
136
137 state_ = BluetoothStreamState::STANDBY;
138
139 auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
140 const BluetoothAudioStatus& status) {
141 if (!port->in_use()) {
142 LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
143 return;
144 }
145 if (port->cookie_ != cookie) {
146 LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
147 << StringPrintf("%#hx", cookie) << ") is corrupted";
148 return;
149 }
150 port->ControlResultHandler(status);
151 };
152 auto session_changed_cb = [port = this](uint16_t cookie) {
153 if (!port->in_use()) {
154 LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
155 return;
156 }
157 if (port->cookie_ != cookie) {
158 LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
159 << StringPrintf("%#hx", cookie) << ") is corrupted";
160 return;
161 }
162 port->SessionChangedHandler();
163 };
164 // TODO: Add audio_config_changed_cb
165 PortStatusCallbacks cbacks = {
166 .control_result_cb_ = control_result_cb,
167 .session_changed_cb_ = session_changed_cb,
168 };
169 cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
170 session_type_, cbacks);
171 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
172 << ", cookie=" << StringPrintf("%#hx", cookie_);
173
174 return (
175 cookie_ !=
176 ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
177 }
178
init_session_type(audio_devices_t device)179 bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) {
180 switch (device) {
181 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
182 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
183 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
184 LOG(VERBOSE)
185 << __func__
186 << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
187 << StringPrintf("%#x", device) << ")";
188 session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
189 break;
190 case AUDIO_DEVICE_OUT_HEARING_AID:
191 LOG(VERBOSE) << __func__
192 << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
193 << StringPrintf("%#x", device) << ")";
194 session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
195 break;
196 case AUDIO_DEVICE_OUT_BLE_HEADSET:
197 LOG(VERBOSE) << __func__
198 << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
199 << StringPrintf("%#x", device) << ")";
200 session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
201 break;
202 case AUDIO_DEVICE_OUT_BLE_SPEAKER:
203 LOG(VERBOSE) << __func__
204 << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
205 << StringPrintf("%#x", device) << ")";
206 session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
207 break;
208 case AUDIO_DEVICE_IN_BLE_HEADSET:
209 LOG(VERBOSE) << __func__
210 << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
211 << StringPrintf("%#x", device) << ")";
212 session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
213 break;
214 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
215 LOG(VERBOSE) << __func__
216 << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
217 << StringPrintf("%#x", device) << ")";
218 session_type_ =
219 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
220 break;
221 default:
222 LOG(ERROR) << __func__
223 << ": unknown device=" << StringPrintf("%#x", device);
224 return false;
225 }
226
227 if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
228 LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
229 << ", session_type=" << toString(session_type_)
230 << " is not ready";
231 return false;
232 }
233 return true;
234 }
235
TearDown()236 void BluetoothAudioPortAidl::TearDown() {
237 if (!in_use()) {
238 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
239 << ", cookie=" << StringPrintf("%#hx", cookie_)
240 << " unknown monitor";
241 return;
242 }
243
244 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
245 << ", cookie=" << StringPrintf("%#hx", cookie_);
246 BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
247 cookie_);
248 cookie_ =
249 ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
250 }
251
ControlResultHandler(const BluetoothAudioStatus & status)252 void BluetoothAudioPortAidl::ControlResultHandler(
253 const BluetoothAudioStatus& status) {
254 if (!in_use()) {
255 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use";
256 return;
257 }
258 std::unique_lock<std::mutex> port_lock(cv_mutex_);
259 BluetoothStreamState previous_state = state_;
260 LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
261 << ", cookie=" << StringPrintf("%#hx", cookie_)
262 << ", previous_state=" << previous_state
263 << ", status=" << toString(status);
264
265 switch (previous_state) {
266 case BluetoothStreamState::STARTED:
267 /* Only Suspend signal can be send in STARTED state*/
268 if (status == BluetoothAudioStatus::RECONFIGURATION ||
269 status == BluetoothAudioStatus::SUCCESS) {
270 state_ = BluetoothStreamState::STANDBY;
271 } else {
272 // Set to standby since the stack may be busy switching between outputs
273 LOG(WARNING) << "control_result_cb: status=" << toString(status)
274 << " failure for session_type=" << toString(session_type_)
275 << ", cookie=" << StringPrintf("%#hx", cookie_)
276 << ", previous_state=" << previous_state;
277 }
278 break;
279 case BluetoothStreamState::STARTING:
280 if (status == BluetoothAudioStatus::SUCCESS) {
281 state_ = BluetoothStreamState::STARTED;
282 } else {
283 // Set to standby since the stack may be busy switching between outputs
284 LOG(WARNING) << "control_result_cb: status=" << toString(status)
285 << " failure for session_type=" << toString(session_type_)
286 << ", cookie=" << StringPrintf("%#hx", cookie_)
287 << ", previous_state=" << previous_state;
288 state_ = BluetoothStreamState::STANDBY;
289 }
290 break;
291 case BluetoothStreamState::SUSPENDING:
292 if (status == BluetoothAudioStatus::SUCCESS) {
293 state_ = BluetoothStreamState::STANDBY;
294 } else {
295 // It will be failed if the headset is disconnecting, and set to disable
296 // to wait for re-init again
297 LOG(WARNING) << "control_result_cb: status=" << toString(status)
298 << " failure for session_type=" << toString(session_type_)
299 << ", cookie=" << StringPrintf("%#hx", cookie_)
300 << ", previous_state=" << previous_state;
301 state_ = BluetoothStreamState::DISABLED;
302 }
303 break;
304 default:
305 LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
306 << " for session_type=" << toString(session_type_)
307 << ", cookie=" << StringPrintf("%#hx", cookie_)
308 << ", previous_state=" << previous_state;
309 return;
310 }
311 port_lock.unlock();
312 internal_cv_.notify_all();
313 }
314
SessionChangedHandler()315 void BluetoothAudioPortAidl::SessionChangedHandler() {
316 if (!in_use()) {
317 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
318 return;
319 }
320 std::unique_lock<std::mutex> port_lock(cv_mutex_);
321 BluetoothStreamState previous_state = state_;
322 LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
323 << ", cookie=" << StringPrintf("%#hx", cookie_)
324 << ", previous_state=" << previous_state;
325 state_ = BluetoothStreamState::DISABLED;
326 port_lock.unlock();
327 internal_cv_.notify_all();
328 }
329
in_use() const330 bool BluetoothAudioPortAidl::in_use() const {
331 return (
332 cookie_ !=
333 ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
334 }
335
GetPreferredDataIntervalUs(size_t * interval_us) const336 bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(
337 size_t* interval_us) const {
338 if (!in_use()) {
339 return false;
340 }
341
342 const AudioConfiguration& hal_audio_cfg =
343 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
344 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
345 return false;
346 }
347
348 const PcmConfiguration& pcm_cfg =
349 hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
350 *interval_us = pcm_cfg.dataIntervalUs;
351 return true;
352 }
353
LoadAudioConfig(audio_config_t * audio_cfg) const354 bool BluetoothAudioPortAidlOut::LoadAudioConfig(
355 audio_config_t* audio_cfg) const {
356 if (!in_use()) {
357 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
358 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
359 audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
360 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
361 return false;
362 }
363
364 const AudioConfiguration& hal_audio_cfg =
365 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
366 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
367 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
368 audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
369 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
370 return false;
371 }
372 const PcmConfiguration& pcm_cfg =
373 hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
374 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
375 << ", cookie=" << StringPrintf("%#hx", cookie_)
376 << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
377 << "]";
378 if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
379 return false;
380 }
381 audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
382 audio_cfg->channel_mask =
383 (is_stereo_to_mono_
384 ? AUDIO_CHANNEL_OUT_STEREO
385 : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
386 audio_cfg->format =
387 BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
388 return true;
389 }
390
LoadAudioConfig(audio_config_t * audio_cfg) const391 bool BluetoothAudioPortAidlIn::LoadAudioConfig(
392 audio_config_t* audio_cfg) const {
393 if (!in_use()) {
394 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
395 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
396 audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
397 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
398 return false;
399 }
400
401 const AudioConfiguration& hal_audio_cfg =
402 BluetoothAudioSessionControl::GetAudioConfig(session_type_);
403 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
404 audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
405 audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
406 audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
407 return false;
408 }
409 const PcmConfiguration& pcm_cfg =
410 hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
411 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
412 << ", cookie=" << StringPrintf("%#hx", cookie_)
413 << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
414 << "]";
415 if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
416 return false;
417 }
418
419 audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
420 audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
421 audio_cfg->format =
422 BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
423 return true;
424 }
425
CondwaitState(BluetoothStreamState state)426 bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
427 bool retval;
428 std::unique_lock<std::mutex> port_lock(cv_mutex_);
429 switch (state) {
430 case BluetoothStreamState::STARTING:
431 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
432 << ", cookie=" << StringPrintf("%#hx", cookie_)
433 << " waiting for STARTED";
434 retval = internal_cv_.wait_for(
435 port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
436 [this] { return this->state_ != BluetoothStreamState::STARTING; });
437 retval = retval && state_ == BluetoothStreamState::STARTED;
438 break;
439 case BluetoothStreamState::SUSPENDING:
440 LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
441 << ", cookie=" << StringPrintf("%#hx", cookie_)
442 << " waiting for SUSPENDED";
443 retval = internal_cv_.wait_for(
444 port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
445 [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
446 retval = retval && state_ == BluetoothStreamState::STANDBY;
447 break;
448 default:
449 LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
450 << ", cookie=" << StringPrintf("%#hx", cookie_)
451 << " waiting for KNOWN";
452 return false;
453 }
454
455 return retval; // false if any failure like timeout
456 }
457
Start()458 bool BluetoothAudioPortAidl::Start() {
459 if (!in_use()) {
460 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
461 return false;
462 }
463
464 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
465 << ", cookie=" << StringPrintf("%#hx", cookie_)
466 << ", state=" << state_
467 << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
468 << " request";
469 bool retval = false;
470 if (state_ == BluetoothStreamState::STANDBY) {
471 state_ = BluetoothStreamState::STARTING;
472 if (BluetoothAudioSessionControl::StartStream(session_type_)) {
473 retval = CondwaitState(BluetoothStreamState::STARTING);
474 } else {
475 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
476 << ", cookie=" << StringPrintf("%#hx", cookie_)
477 << ", state=" << state_ << " Hal fails";
478 }
479 }
480
481 if (retval) {
482 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
483 << ", cookie=" << StringPrintf("%#hx", cookie_)
484 << ", state=" << state_
485 << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
486 << " done";
487 } else {
488 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
489 << ", cookie=" << StringPrintf("%#hx", cookie_)
490 << ", state=" << state_ << " failure";
491 }
492
493 return retval; // false if any failure like timeout
494 }
495
Suspend()496 bool BluetoothAudioPortAidl::Suspend() {
497 if (!in_use()) {
498 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
499 return false;
500 }
501
502 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
503 << ", cookie=" << StringPrintf("%#hx", cookie_)
504 << ", state=" << state_ << " request";
505 bool retval = false;
506 if (state_ == BluetoothStreamState::STARTED) {
507 state_ = BluetoothStreamState::SUSPENDING;
508 if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
509 retval = CondwaitState(BluetoothStreamState::SUSPENDING);
510 } else {
511 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
512 << ", cookie=" << StringPrintf("%#hx", cookie_)
513 << ", state=" << state_ << " Hal fails";
514 }
515 }
516
517 if (retval) {
518 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
519 << ", cookie=" << StringPrintf("%#hx", cookie_)
520 << ", state=" << state_ << " done";
521 } else {
522 LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
523 << ", cookie=" << StringPrintf("%#hx", cookie_)
524 << ", state=" << state_ << " failure";
525 }
526
527 return retval; // false if any failure like timeout
528 }
529
Stop()530 void BluetoothAudioPortAidl::Stop() {
531 if (!in_use()) {
532 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
533 return;
534 }
535 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
536 << ", cookie=" << StringPrintf("%#hx", cookie_)
537 << ", state=" << state_ << " request";
538 state_ = BluetoothStreamState::DISABLED;
539 BluetoothAudioSessionControl::StopStream(session_type_);
540 LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
541 << ", cookie=" << StringPrintf("%#hx", cookie_)
542 << ", state=" << state_ << " done";
543 }
544
WriteData(const void * buffer,size_t bytes) const545 size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer,
546 size_t bytes) const {
547 if (!in_use()) return 0;
548 if (!is_stereo_to_mono_) {
549 return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer,
550 bytes);
551 }
552
553 // WAR to mix the stereo into Mono (16 bits per sample)
554 const size_t write_frames = bytes >> 2;
555 if (write_frames == 0) return 0;
556 auto src = static_cast<const int16_t*>(buffer);
557 std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
558 downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
559 // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
560 return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(),
561 write_frames * 2) *
562 2;
563 }
564
ReadData(void * buffer,size_t bytes) const565 size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
566 if (!in_use()) return 0;
567 return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer,
568 bytes);
569 }
570
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const571 bool BluetoothAudioPortAidl::GetPresentationPosition(
572 uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const {
573 if (!in_use()) {
574 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
575 return false;
576 }
577 PresentationPosition presentation_position;
578 bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
579 session_type_, presentation_position);
580 *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
581 *bytes = presentation_position.transmittedOctets;
582 *timestamp = {.tv_sec = static_cast<__kernel_old_time_t>(
583 presentation_position.transmittedOctetsTimestamp.tvSec),
584 .tv_nsec = static_cast<long>(
585 presentation_position.transmittedOctetsTimestamp.tvNSec)};
586 LOG(VERBOSE) << __func__ << ": session_type="
587 << StringPrintf("%#x", static_cast<unsigned>(session_type_))
588 << ", cookie=" << StringPrintf("%#hx", cookie_)
589 << ", state=" << state_ << ", delay=" << *delay_ns
590 << "ns, data=" << *bytes
591 << " bytes, timestamp=" << timestamp->tv_sec << "."
592 << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
593
594 return retval;
595 }
596
UpdateSourceMetadata(const source_metadata_v7 * source_metadata) const597 void BluetoothAudioPortAidl::UpdateSourceMetadata(
598 const source_metadata_v7* source_metadata) const {
599 if (!in_use()) {
600 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
601 return;
602 }
603 LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
604 << ", cookie=" << StringPrintf("%#hx", cookie_)
605 << ", state=" << state_ << ", " << source_metadata->track_count
606 << " track(s)";
607 ssize_t track_count = source_metadata->track_count;
608 if (track_count == 0) return;
609 SourceMetadata hal_source_metadata;
610 hal_source_metadata.tracks.resize(track_count);
611 for (int i = 0; i < track_count; i++) {
612 hal_source_metadata.tracks[i].usage =
613 static_cast<AudioUsage>(source_metadata->tracks[i].base.usage);
614 hal_source_metadata.tracks[i].contentType = static_cast<AudioContentType>(
615 source_metadata->tracks[i].base.content_type);
616 hal_source_metadata.tracks[i].tags =
617 std::move(CovertAudioTagFromV7(source_metadata->tracks[i].tags));
618 }
619
620 BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_,
621 hal_source_metadata);
622 }
623
UpdateSinkMetadata(const sink_metadata_v7 * sink_metadata) const624 void BluetoothAudioPortAidl::UpdateSinkMetadata(
625 const sink_metadata_v7* sink_metadata) const {
626 if (!in_use()) {
627 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
628 return;
629 }
630 LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
631 << ", cookie=" << StringPrintf("%#hx", cookie_)
632 << ", state=" << state_ << ", " << sink_metadata->track_count
633 << " track(s)";
634 ssize_t track_count = sink_metadata->track_count;
635 if (track_count == 0) return;
636 SinkMetadata hal_sink_metadata;
637 hal_sink_metadata.tracks.resize(track_count);
638 for (int i = 0; i < track_count; i++) {
639 hal_sink_metadata.tracks[i].source =
640 static_cast<AudioSource>(sink_metadata->tracks[i].base.source);
641 hal_sink_metadata.tracks[i].gain = sink_metadata->tracks[i].base.gain;
642 hal_sink_metadata.tracks[i].tags =
643 std::move(CovertAudioTagFromV7(sink_metadata->tracks[i].tags));
644 }
645
646 BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_,
647 hal_sink_metadata);
648 }
649
GetState() const650 BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
651
SetState(BluetoothStreamState state)652 void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) {
653 state_ = state;
654 }
655
656 } // namespace aidl
657 } // namespace audio
658 } // namespace bluetooth
659 } // namespace android
660