blob: 3214bf222818f230f451a29715de196443894d9b [file] [log] [blame]
Josh Wu20bac522021-12-29 23:52:39 -08001/*
2 * Copyright (C) 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#include <sys/types.h>
18#define LOG_TAG "BTAudioSessionAidl"
19
20#include <android-base/logging.h>
21#include <android-base/stringprintf.h>
22#include <android/binder_manager.h>
23
24#include "BluetoothAudioSession.h"
25
26namespace aidl {
27namespace android {
28namespace hardware {
29namespace bluetooth {
30namespace audio {
31
32static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
33static constexpr int kFmqReceiveTimeoutMs =
34 1000; // 1000 ms timeout for receiving
35static constexpr int kWritePollMs = 1; // polled non-blocking interval
36static constexpr int kReadPollMs = 1; // polled non-blocking interval
37
Josh Wu20bac522021-12-29 23:52:39 -080038BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080039 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080040
41/***
42 *
43 * Callback methods
44 *
45 ***/
46
47void BluetoothAudioSession::OnSessionStarted(
48 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080049 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
50 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080051 std::lock_guard<std::recursive_mutex> guard(mutex_);
52 if (stack_iface == nullptr) {
53 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
54 << ", IBluetoothAudioPort Invalid";
55 } else if (!UpdateAudioConfig(audio_config)) {
56 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
57 << ", AudioConfiguration=" << audio_config.toString()
58 << " Invalid";
59 } else if (!UpdateDataPath(mq_desc)) {
60 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
61 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080062 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080063 } else {
64 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080065 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080066 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
67 << ", AudioConfiguration=" << audio_config.toString();
68 ReportSessionStatus();
69 }
70}
71
72void BluetoothAudioSession::OnSessionEnded() {
73 std::lock_guard<std::recursive_mutex> guard(mutex_);
74 bool toggled = IsSessionReady();
75 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080076 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080077 stack_iface_ = nullptr;
78 UpdateDataPath(nullptr);
79 if (toggled) {
80 ReportSessionStatus();
81 }
82}
83
84/***
85 *
86 * Util methods
87 *
88 ***/
89
Josh Wu75462aa2022-01-21 21:51:21 -080090const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080091 std::lock_guard<std::recursive_mutex> guard(mutex_);
92 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080093 switch (session_type_) {
94 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +080095 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080096 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -080097 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
98 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080099 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800100 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
101 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800102 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800103 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800104 }
105 }
106 return *audio_config_;
107}
108
109void BluetoothAudioSession::ReportAudioConfigChanged(
110 const AudioConfiguration& audio_config) {
111 if (session_type_ !=
112 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
113 session_type_ !=
114 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
115 return;
116 }
117 std::lock_guard<std::recursive_mutex> guard(mutex_);
118 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
119 if (observers_.empty()) {
120 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
121 << " has NO port state observer";
122 return;
123 }
124 for (auto& observer : observers_) {
125 uint16_t cookie = observer.first;
126 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
127 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
128 << ", bluetooth_audio=0x"
129 << ::android::base::StringPrintf("%04x", cookie);
130 if (cb->audio_configuration_changed_cb_ != nullptr) {
131 cb->audio_configuration_changed_cb_(cookie);
132 }
133 }
134}
135
136bool BluetoothAudioSession::IsSessionReady() {
137 std::lock_guard<std::recursive_mutex> guard(mutex_);
138
139 bool is_mq_valid =
140 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
141 session_type_ ==
142 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
143 session_type_ ==
144 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800145 session_type_ ==
146 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800147 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800148 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800149 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800150}
151
152/***
153 *
154 * Status callback methods
155 *
156 ***/
157
158uint16_t BluetoothAudioSession::RegisterStatusCback(
159 const PortStatusCallbacks& callbacks) {
160 std::lock_guard<std::recursive_mutex> guard(mutex_);
161 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
162 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
163
164 while (cookie < cookie_upper_bound) {
165 if (observers_.find(cookie) == observers_.end()) {
166 break;
167 }
168 ++cookie;
169 }
170 if (cookie >= cookie_upper_bound) {
171 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
172 << " has " << observers_.size()
173 << " observers already (No Resource)";
174 return kObserversCookieUndefined;
175 }
176 std::shared_ptr<PortStatusCallbacks> cb =
177 std::make_shared<PortStatusCallbacks>();
178 *cb = callbacks;
179 observers_[cookie] = cb;
180 return cookie;
181}
182
183void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
184 std::lock_guard<std::recursive_mutex> guard(mutex_);
185 if (observers_.erase(cookie) != 1) {
186 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
187 << " no such provider=0x"
188 << ::android::base::StringPrintf("%04x", cookie);
189 }
190}
191
192/***
193 *
194 * Stream methods
195 *
196 ***/
197
Cheney Ni6ecbc762022-03-03 00:12:48 +0800198bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800199 std::lock_guard<std::recursive_mutex> guard(mutex_);
200 if (!IsSessionReady()) {
201 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
202 << " has NO session";
203 return false;
204 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800205 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800206 if (!hal_retval.isOk()) {
207 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
208 << toString(session_type_) << " failed";
209 return false;
210 }
211 return true;
212}
213
214bool BluetoothAudioSession::SuspendStream() {
215 std::lock_guard<std::recursive_mutex> guard(mutex_);
216 if (!IsSessionReady()) {
217 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
218 << " has NO session";
219 return false;
220 }
221 auto hal_retval = stack_iface_->suspendStream();
222 if (!hal_retval.isOk()) {
223 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
224 << toString(session_type_) << " failed";
225 return false;
226 }
227 return true;
228}
229
230void BluetoothAudioSession::StopStream() {
231 std::lock_guard<std::recursive_mutex> guard(mutex_);
232 if (!IsSessionReady()) {
233 return;
234 }
235 auto hal_retval = stack_iface_->stopStream();
236 if (!hal_retval.isOk()) {
237 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
238 << toString(session_type_) << " failed";
239 }
240}
241
242/***
243 *
244 * Private methods
245 *
246 ***/
247
248bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
249 if (mq_desc == nullptr) {
250 // usecase of reset by nullptr
251 data_mq_ = nullptr;
252 return true;
253 }
254 std::unique_ptr<DataMQ> temp_mq;
255 temp_mq.reset(new DataMQ(*mq_desc));
256 if (!temp_mq || !temp_mq->isValid()) {
257 data_mq_ = nullptr;
258 return false;
259 }
260 data_mq_ = std::move(temp_mq);
261 return true;
262}
263
264bool BluetoothAudioSession::UpdateAudioConfig(
265 const AudioConfiguration& audio_config) {
266 bool is_software_session =
267 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
268 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
269 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800270 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
271 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800272 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
273 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800274 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800275 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
276 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800277 bool is_offload_le_audio_session =
278 (session_type_ ==
279 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
280 session_type_ ==
281 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
282 auto audio_config_tag = audio_config.getTag();
283 bool is_software_audio_config =
284 (is_software_session &&
285 audio_config_tag == AudioConfiguration::pcmConfig);
286 bool is_a2dp_offload_audio_config =
287 (is_offload_a2dp_session &&
288 audio_config_tag == AudioConfiguration::a2dpConfig);
289 bool is_le_audio_offload_audio_config =
290 (is_offload_le_audio_session &&
291 audio_config_tag == AudioConfiguration::leAudioConfig);
292 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
293 !is_le_audio_offload_audio_config) {
294 return false;
295 }
296 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
297 return true;
298}
299
300void BluetoothAudioSession::ReportSessionStatus() {
301 // This is locked already by OnSessionStarted / OnSessionEnded
302 if (observers_.empty()) {
303 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
304 << " has NO port state observer";
305 return;
306 }
307 for (auto& observer : observers_) {
308 uint16_t cookie = observer.first;
309 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
310 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
311 << " notify to bluetooth_audio=0x"
312 << ::android::base::StringPrintf("%04x", cookie);
313 callback->session_changed_cb_(cookie);
314 }
315}
316
317/***
318 *
319 * PCM methods
320 *
321 ***/
322
323size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
324 size_t bytes) {
325 if (buffer == nullptr || bytes <= 0) {
326 return 0;
327 }
328 size_t total_written = 0;
329 int timeout_ms = kFmqSendTimeoutMs;
330 do {
331 std::unique_lock<std::recursive_mutex> lock(mutex_);
332 if (!IsSessionReady()) {
333 break;
334 }
335 size_t num_bytes_to_write = data_mq_->availableToWrite();
336 if (num_bytes_to_write) {
337 if (num_bytes_to_write > (bytes - total_written)) {
338 num_bytes_to_write = bytes - total_written;
339 }
340
341 if (!data_mq_->write(
342 static_cast<const MQDataType*>(buffer) + total_written,
343 num_bytes_to_write)) {
344 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
345 << " failed";
346 return total_written;
347 }
348 total_written += num_bytes_to_write;
349 } else if (timeout_ms >= kWritePollMs) {
350 lock.unlock();
351 usleep(kWritePollMs * 1000);
352 timeout_ms -= kWritePollMs;
353 } else {
354 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
355 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
356 return total_written;
357 }
358 } while (total_written < bytes);
359 return total_written;
360}
361
362size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
363 if (buffer == nullptr || bytes <= 0) {
364 return 0;
365 }
366 size_t total_read = 0;
367 int timeout_ms = kFmqReceiveTimeoutMs;
368 do {
369 std::unique_lock<std::recursive_mutex> lock(mutex_);
370 if (!IsSessionReady()) {
371 break;
372 }
373 size_t num_bytes_to_read = data_mq_->availableToRead();
374 if (num_bytes_to_read) {
375 if (num_bytes_to_read > (bytes - total_read)) {
376 num_bytes_to_read = bytes - total_read;
377 }
378 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
379 num_bytes_to_read)) {
380 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
381 << " failed";
382 return total_read;
383 }
384 total_read += num_bytes_to_read;
385 } else if (timeout_ms >= kReadPollMs) {
386 lock.unlock();
387 usleep(kReadPollMs * 1000);
388 timeout_ms -= kReadPollMs;
389 continue;
390 } else {
391 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
392 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
393 return total_read;
394 }
395 } while (total_read < bytes);
396 return total_read;
397}
398
399/***
400 *
401 * Other methods
402 *
403 ***/
404
405void BluetoothAudioSession::ReportControlStatus(bool start_resp,
406 BluetoothAudioStatus status) {
407 std::lock_guard<std::recursive_mutex> guard(mutex_);
408 if (observers_.empty()) {
409 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
410 << " has NO port state observer";
411 return;
412 }
413 for (auto& observer : observers_) {
414 uint16_t cookie = observer.first;
415 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
416 LOG(INFO) << __func__ << " - status=" << toString(status)
417 << " for SessionType=" << toString(session_type_)
418 << ", bluetooth_audio=0x"
419 << ::android::base::StringPrintf("%04x", cookie)
420 << (start_resp ? " started" : " suspended");
421 callback->control_result_cb_(cookie, start_resp, status);
422 }
423}
424
Chen Chen81f38e52022-02-09 13:27:35 -0800425void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
426 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800427 low_latency_allowed_ = allowed;
Chen Chen81f38e52022-02-09 13:27:35 -0800428 if (observers_.empty()) {
429 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
430 << " has NO port state observer";
431 return;
432 }
433 for (auto& observer : observers_) {
434 uint16_t cookie = observer.first;
435 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800436 LOG(INFO) << __func__
437 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700438 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
439 callback->low_latency_mode_allowed_cb_(cookie, allowed);
440 }
Chen Chen81f38e52022-02-09 13:27:35 -0800441 }
442}
443
Josh Wu20bac522021-12-29 23:52:39 -0800444bool BluetoothAudioSession::GetPresentationPosition(
445 PresentationPosition& presentation_position) {
446 std::lock_guard<std::recursive_mutex> guard(mutex_);
447 if (!IsSessionReady()) {
448 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
449 << " has NO session";
450 return false;
451 }
452 bool retval = false;
453
454 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
455 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
456 << toString(session_type_) << " failed";
457 return false;
458 }
459 return retval;
460}
461
462void BluetoothAudioSession::UpdateSourceMetadata(
463 const struct source_metadata& source_metadata) {
464 std::lock_guard<std::recursive_mutex> guard(mutex_);
465 if (!IsSessionReady()) {
466 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
467 << " has NO session";
468 return;
469 }
470
471 ssize_t track_count = source_metadata.track_count;
472 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
473 << track_count << " track(s)";
474 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800475 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
476 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
477 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800478 return;
479 }
480
481 SourceMetadata hal_source_metadata;
482 hal_source_metadata.tracks.resize(track_count);
483 for (int i = 0; i < track_count; i++) {
484 hal_source_metadata.tracks[i].usage =
485 static_cast<media::audio::common::AudioUsage>(
486 source_metadata.tracks[i].usage);
487 hal_source_metadata.tracks[i].contentType =
488 static_cast<media::audio::common::AudioContentType>(
489 source_metadata.tracks[i].content_type);
490 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
491 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
492 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
493 << ", content="
494 << toString(hal_source_metadata.tracks[i].contentType)
495 << ", gain=" << hal_source_metadata.tracks[i].gain;
496 }
497
498 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
499 if (!hal_retval.isOk()) {
500 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
501 << toString(session_type_) << " failed";
502 }
503}
504
505void BluetoothAudioSession::UpdateSinkMetadata(
506 const struct sink_metadata& sink_metadata) {
507 std::lock_guard<std::recursive_mutex> guard(mutex_);
508 if (!IsSessionReady()) {
509 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
510 << " has NO session";
511 return;
512 }
513
514 ssize_t track_count = sink_metadata.track_count;
515 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
516 << track_count << " track(s)";
517 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800518 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
519 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
520 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800521 return;
522 }
523
524 SinkMetadata hal_sink_metadata;
525 hal_sink_metadata.tracks.resize(track_count);
526 for (int i = 0; i < track_count; i++) {
527 hal_sink_metadata.tracks[i].source =
528 static_cast<media::audio::common::AudioSource>(
529 sink_metadata.tracks[i].source);
530 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
531 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
532 << ", source=" << sink_metadata.tracks[i].source
533 << ", dest_device=" << sink_metadata.tracks[i].dest_device
534 << ", gain=" << sink_metadata.tracks[i].gain
535 << ", dest_device_address="
536 << sink_metadata.tracks[i].dest_device_address;
537 }
538
539 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
540 if (!hal_retval.isOk()) {
541 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
542 << toString(session_type_) << " failed";
543 }
544}
545
Cheney Ni6ecbc762022-03-03 00:12:48 +0800546std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
547 std::lock_guard<std::recursive_mutex> guard(mutex_);
548 if (!IsSessionReady()) {
549 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
550 << " has NO session";
551 return std::vector<LatencyMode>();
552 }
553 if (low_latency_allowed_) return latency_modes_;
554 std::vector<LatencyMode> modes;
555 for (LatencyMode mode : latency_modes_) {
556 if (mode == LatencyMode::LOW_LATENCY)
557 // ignore those low latency mode if Bluetooth stack doesn't allow
558 continue;
559 modes.push_back(mode);
560 }
561 return modes;
562}
563
564void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800565 std::lock_guard<std::recursive_mutex> guard(mutex_);
566 if (!IsSessionReady()) {
567 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
568 << " has NO session";
569 return;
570 }
571
572 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
573 if (!hal_retval.isOk()) {
574 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
575 << toString(session_type_) << " failed";
576 }
577}
578
Josh Wu20bac522021-12-29 23:52:39 -0800579bool BluetoothAudioSession::IsAidlAvailable() {
580 if (is_aidl_checked) return is_aidl_available;
581 is_aidl_available =
582 (AServiceManager_checkService(
583 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
584 is_aidl_checked = true;
585 return is_aidl_available;
586}
587
588/***
589 *
590 * BluetoothAudioSessionInstance
591 *
592 ***/
593std::mutex BluetoothAudioSessionInstance::mutex_;
594std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
595 BluetoothAudioSessionInstance::sessions_map_;
596
597std::shared_ptr<BluetoothAudioSession>
598BluetoothAudioSessionInstance::GetSessionInstance(
599 const SessionType& session_type) {
600 std::lock_guard<std::mutex> guard(mutex_);
601
602 if (!sessions_map_.empty()) {
603 auto entry = sessions_map_.find(session_type);
604 if (entry != sessions_map_.end()) {
605 return entry->second;
606 }
607 }
608 std::shared_ptr<BluetoothAudioSession> session_ptr =
609 std::make_shared<BluetoothAudioSession>(session_type);
610 sessions_map_[session_type] = session_ptr;
611 return session_ptr;
612}
613
614} // namespace audio
615} // namespace bluetooth
616} // namespace hardware
617} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800618} // namespace aidl