blob: 37ac9678e8858a992113a18af5deceea09d5caa7 [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:
Josh Wu75462aa2022-01-21 21:51:21 -080095 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -080096 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
97 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080098 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +080099 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
100 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800101 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800102 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800103 }
104 }
105 return *audio_config_;
106}
107
108void BluetoothAudioSession::ReportAudioConfigChanged(
109 const AudioConfiguration& audio_config) {
110 if (session_type_ !=
111 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
112 session_type_ !=
113 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
114 return;
115 }
116 std::lock_guard<std::recursive_mutex> guard(mutex_);
117 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
118 if (observers_.empty()) {
119 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
120 << " has NO port state observer";
121 return;
122 }
123 for (auto& observer : observers_) {
124 uint16_t cookie = observer.first;
125 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
126 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
127 << ", bluetooth_audio=0x"
128 << ::android::base::StringPrintf("%04x", cookie);
129 if (cb->audio_configuration_changed_cb_ != nullptr) {
130 cb->audio_configuration_changed_cb_(cookie);
131 }
132 }
133}
134
135bool BluetoothAudioSession::IsSessionReady() {
136 std::lock_guard<std::recursive_mutex> guard(mutex_);
137
138 bool is_mq_valid =
139 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
140 session_type_ ==
141 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
142 session_type_ ==
143 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800144 session_type_ ==
145 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800146 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800147 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800148}
149
150/***
151 *
152 * Status callback methods
153 *
154 ***/
155
156uint16_t BluetoothAudioSession::RegisterStatusCback(
157 const PortStatusCallbacks& callbacks) {
158 std::lock_guard<std::recursive_mutex> guard(mutex_);
159 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
160 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
161
162 while (cookie < cookie_upper_bound) {
163 if (observers_.find(cookie) == observers_.end()) {
164 break;
165 }
166 ++cookie;
167 }
168 if (cookie >= cookie_upper_bound) {
169 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
170 << " has " << observers_.size()
171 << " observers already (No Resource)";
172 return kObserversCookieUndefined;
173 }
174 std::shared_ptr<PortStatusCallbacks> cb =
175 std::make_shared<PortStatusCallbacks>();
176 *cb = callbacks;
177 observers_[cookie] = cb;
178 return cookie;
179}
180
181void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
182 std::lock_guard<std::recursive_mutex> guard(mutex_);
183 if (observers_.erase(cookie) != 1) {
184 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
185 << " no such provider=0x"
186 << ::android::base::StringPrintf("%04x", cookie);
187 }
188}
189
190/***
191 *
192 * Stream methods
193 *
194 ***/
195
Cheney Ni6ecbc762022-03-03 00:12:48 +0800196bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800197 std::lock_guard<std::recursive_mutex> guard(mutex_);
198 if (!IsSessionReady()) {
199 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
200 << " has NO session";
201 return false;
202 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800203 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800204 if (!hal_retval.isOk()) {
205 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
206 << toString(session_type_) << " failed";
207 return false;
208 }
209 return true;
210}
211
212bool BluetoothAudioSession::SuspendStream() {
213 std::lock_guard<std::recursive_mutex> guard(mutex_);
214 if (!IsSessionReady()) {
215 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
216 << " has NO session";
217 return false;
218 }
219 auto hal_retval = stack_iface_->suspendStream();
220 if (!hal_retval.isOk()) {
221 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
222 << toString(session_type_) << " failed";
223 return false;
224 }
225 return true;
226}
227
228void BluetoothAudioSession::StopStream() {
229 std::lock_guard<std::recursive_mutex> guard(mutex_);
230 if (!IsSessionReady()) {
231 return;
232 }
233 auto hal_retval = stack_iface_->stopStream();
234 if (!hal_retval.isOk()) {
235 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
236 << toString(session_type_) << " failed";
237 }
238}
239
240/***
241 *
242 * Private methods
243 *
244 ***/
245
246bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
247 if (mq_desc == nullptr) {
248 // usecase of reset by nullptr
249 data_mq_ = nullptr;
250 return true;
251 }
252 std::unique_ptr<DataMQ> temp_mq;
253 temp_mq.reset(new DataMQ(*mq_desc));
254 if (!temp_mq || !temp_mq->isValid()) {
255 data_mq_ = nullptr;
256 return false;
257 }
258 data_mq_ = std::move(temp_mq);
259 return true;
260}
261
262bool BluetoothAudioSession::UpdateAudioConfig(
263 const AudioConfiguration& audio_config) {
264 bool is_software_session =
265 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
266 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
267 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800268 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
269 session_type_ ==
270 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800271 bool is_offload_a2dp_session =
272 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
273 bool is_offload_le_audio_session =
274 (session_type_ ==
275 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
276 session_type_ ==
277 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
278 auto audio_config_tag = audio_config.getTag();
279 bool is_software_audio_config =
280 (is_software_session &&
281 audio_config_tag == AudioConfiguration::pcmConfig);
282 bool is_a2dp_offload_audio_config =
283 (is_offload_a2dp_session &&
284 audio_config_tag == AudioConfiguration::a2dpConfig);
285 bool is_le_audio_offload_audio_config =
286 (is_offload_le_audio_session &&
287 audio_config_tag == AudioConfiguration::leAudioConfig);
288 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
289 !is_le_audio_offload_audio_config) {
290 return false;
291 }
292 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
293 return true;
294}
295
296void BluetoothAudioSession::ReportSessionStatus() {
297 // This is locked already by OnSessionStarted / OnSessionEnded
298 if (observers_.empty()) {
299 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
300 << " has NO port state observer";
301 return;
302 }
303 for (auto& observer : observers_) {
304 uint16_t cookie = observer.first;
305 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
306 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
307 << " notify to bluetooth_audio=0x"
308 << ::android::base::StringPrintf("%04x", cookie);
309 callback->session_changed_cb_(cookie);
310 }
311}
312
313/***
314 *
315 * PCM methods
316 *
317 ***/
318
319size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
320 size_t bytes) {
321 if (buffer == nullptr || bytes <= 0) {
322 return 0;
323 }
324 size_t total_written = 0;
325 int timeout_ms = kFmqSendTimeoutMs;
326 do {
327 std::unique_lock<std::recursive_mutex> lock(mutex_);
328 if (!IsSessionReady()) {
329 break;
330 }
331 size_t num_bytes_to_write = data_mq_->availableToWrite();
332 if (num_bytes_to_write) {
333 if (num_bytes_to_write > (bytes - total_written)) {
334 num_bytes_to_write = bytes - total_written;
335 }
336
337 if (!data_mq_->write(
338 static_cast<const MQDataType*>(buffer) + total_written,
339 num_bytes_to_write)) {
340 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
341 << " failed";
342 return total_written;
343 }
344 total_written += num_bytes_to_write;
345 } else if (timeout_ms >= kWritePollMs) {
346 lock.unlock();
347 usleep(kWritePollMs * 1000);
348 timeout_ms -= kWritePollMs;
349 } else {
350 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
351 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
352 return total_written;
353 }
354 } while (total_written < bytes);
355 return total_written;
356}
357
358size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
359 if (buffer == nullptr || bytes <= 0) {
360 return 0;
361 }
362 size_t total_read = 0;
363 int timeout_ms = kFmqReceiveTimeoutMs;
364 do {
365 std::unique_lock<std::recursive_mutex> lock(mutex_);
366 if (!IsSessionReady()) {
367 break;
368 }
369 size_t num_bytes_to_read = data_mq_->availableToRead();
370 if (num_bytes_to_read) {
371 if (num_bytes_to_read > (bytes - total_read)) {
372 num_bytes_to_read = bytes - total_read;
373 }
374 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
375 num_bytes_to_read)) {
376 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
377 << " failed";
378 return total_read;
379 }
380 total_read += num_bytes_to_read;
381 } else if (timeout_ms >= kReadPollMs) {
382 lock.unlock();
383 usleep(kReadPollMs * 1000);
384 timeout_ms -= kReadPollMs;
385 continue;
386 } else {
387 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
388 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
389 return total_read;
390 }
391 } while (total_read < bytes);
392 return total_read;
393}
394
395/***
396 *
397 * Other methods
398 *
399 ***/
400
401void BluetoothAudioSession::ReportControlStatus(bool start_resp,
402 BluetoothAudioStatus status) {
403 std::lock_guard<std::recursive_mutex> guard(mutex_);
404 if (observers_.empty()) {
405 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
406 << " has NO port state observer";
407 return;
408 }
409 for (auto& observer : observers_) {
410 uint16_t cookie = observer.first;
411 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
412 LOG(INFO) << __func__ << " - status=" << toString(status)
413 << " for SessionType=" << toString(session_type_)
414 << ", bluetooth_audio=0x"
415 << ::android::base::StringPrintf("%04x", cookie)
416 << (start_resp ? " started" : " suspended");
417 callback->control_result_cb_(cookie, start_resp, status);
418 }
419}
420
Chen Chen81f38e52022-02-09 13:27:35 -0800421void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
422 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800423 low_latency_allowed_ = allowed;
Chen Chen81f38e52022-02-09 13:27:35 -0800424 if (observers_.empty()) {
425 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
426 << " has NO port state observer";
427 return;
428 }
429 for (auto& observer : observers_) {
430 uint16_t cookie = observer.first;
431 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800432 LOG(INFO) << __func__
433 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen81f38e52022-02-09 13:27:35 -0800434 callback->low_latency_mode_allowed_cb_(cookie, allowed);
435 }
436}
437
Josh Wu20bac522021-12-29 23:52:39 -0800438bool BluetoothAudioSession::GetPresentationPosition(
439 PresentationPosition& presentation_position) {
440 std::lock_guard<std::recursive_mutex> guard(mutex_);
441 if (!IsSessionReady()) {
442 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
443 << " has NO session";
444 return false;
445 }
446 bool retval = false;
447
448 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
449 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
450 << toString(session_type_) << " failed";
451 return false;
452 }
453 return retval;
454}
455
456void BluetoothAudioSession::UpdateSourceMetadata(
457 const struct source_metadata& source_metadata) {
458 std::lock_guard<std::recursive_mutex> guard(mutex_);
459 if (!IsSessionReady()) {
460 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
461 << " has NO session";
462 return;
463 }
464
465 ssize_t track_count = source_metadata.track_count;
466 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
467 << track_count << " track(s)";
468 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
469 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
470 return;
471 }
472
473 SourceMetadata hal_source_metadata;
474 hal_source_metadata.tracks.resize(track_count);
475 for (int i = 0; i < track_count; i++) {
476 hal_source_metadata.tracks[i].usage =
477 static_cast<media::audio::common::AudioUsage>(
478 source_metadata.tracks[i].usage);
479 hal_source_metadata.tracks[i].contentType =
480 static_cast<media::audio::common::AudioContentType>(
481 source_metadata.tracks[i].content_type);
482 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
483 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
484 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
485 << ", content="
486 << toString(hal_source_metadata.tracks[i].contentType)
487 << ", gain=" << hal_source_metadata.tracks[i].gain;
488 }
489
490 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
491 if (!hal_retval.isOk()) {
492 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
493 << toString(session_type_) << " failed";
494 }
495}
496
497void BluetoothAudioSession::UpdateSinkMetadata(
498 const struct sink_metadata& sink_metadata) {
499 std::lock_guard<std::recursive_mutex> guard(mutex_);
500 if (!IsSessionReady()) {
501 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
502 << " has NO session";
503 return;
504 }
505
506 ssize_t track_count = sink_metadata.track_count;
507 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
508 << track_count << " track(s)";
509 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
510 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
511 return;
512 }
513
514 SinkMetadata hal_sink_metadata;
515 hal_sink_metadata.tracks.resize(track_count);
516 for (int i = 0; i < track_count; i++) {
517 hal_sink_metadata.tracks[i].source =
518 static_cast<media::audio::common::AudioSource>(
519 sink_metadata.tracks[i].source);
520 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
521 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
522 << ", source=" << sink_metadata.tracks[i].source
523 << ", dest_device=" << sink_metadata.tracks[i].dest_device
524 << ", gain=" << sink_metadata.tracks[i].gain
525 << ", dest_device_address="
526 << sink_metadata.tracks[i].dest_device_address;
527 }
528
529 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
530 if (!hal_retval.isOk()) {
531 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
532 << toString(session_type_) << " failed";
533 }
534}
535
Cheney Ni6ecbc762022-03-03 00:12:48 +0800536std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
537 std::lock_guard<std::recursive_mutex> guard(mutex_);
538 if (!IsSessionReady()) {
539 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
540 << " has NO session";
541 return std::vector<LatencyMode>();
542 }
543 if (low_latency_allowed_) return latency_modes_;
544 std::vector<LatencyMode> modes;
545 for (LatencyMode mode : latency_modes_) {
546 if (mode == LatencyMode::LOW_LATENCY)
547 // ignore those low latency mode if Bluetooth stack doesn't allow
548 continue;
549 modes.push_back(mode);
550 }
551 return modes;
552}
553
554void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800555 std::lock_guard<std::recursive_mutex> guard(mutex_);
556 if (!IsSessionReady()) {
557 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
558 << " has NO session";
559 return;
560 }
561
562 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
563 if (!hal_retval.isOk()) {
564 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
565 << toString(session_type_) << " failed";
566 }
567}
568
Josh Wu20bac522021-12-29 23:52:39 -0800569bool BluetoothAudioSession::IsAidlAvailable() {
570 if (is_aidl_checked) return is_aidl_available;
571 is_aidl_available =
572 (AServiceManager_checkService(
573 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
574 is_aidl_checked = true;
575 return is_aidl_available;
576}
577
578/***
579 *
580 * BluetoothAudioSessionInstance
581 *
582 ***/
583std::mutex BluetoothAudioSessionInstance::mutex_;
584std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
585 BluetoothAudioSessionInstance::sessions_map_;
586
587std::shared_ptr<BluetoothAudioSession>
588BluetoothAudioSessionInstance::GetSessionInstance(
589 const SessionType& session_type) {
590 std::lock_guard<std::mutex> guard(mutex_);
591
592 if (!sessions_map_.empty()) {
593 auto entry = sessions_map_.find(session_type);
594 if (entry != sessions_map_.end()) {
595 return entry->second;
596 }
597 }
598 std::shared_ptr<BluetoothAudioSession> session_ptr =
599 std::make_shared<BluetoothAudioSession>(session_type);
600 sessions_map_[session_type] = session_ptr;
601 return session_ptr;
602}
603
604} // namespace audio
605} // namespace bluetooth
606} // namespace hardware
607} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800608} // namespace aidl