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