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