blob: 3519ace1f924e9dd8aa1e02c737c16f801826ab5 [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>
Mikhail Naganovd5f0d132023-07-26 17:26:02 -070023#include <hardware/audio.h>
Josh Wu20bac522021-12-29 23:52:39 -080024
25#include "BluetoothAudioSession.h"
26
27namespace aidl {
28namespace android {
29namespace hardware {
30namespace bluetooth {
31namespace audio {
32
33static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
34static constexpr int kFmqReceiveTimeoutMs =
35 1000; // 1000 ms timeout for receiving
36static constexpr int kWritePollMs = 1; // polled non-blocking interval
37static constexpr int kReadPollMs = 1; // polled non-blocking interval
38
Josh Wu20bac522021-12-29 23:52:39 -080039BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080040 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080041
42/***
43 *
44 * Callback methods
45 *
46 ***/
47
48void BluetoothAudioSession::OnSessionStarted(
49 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080050 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
51 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080052 std::lock_guard<std::recursive_mutex> guard(mutex_);
53 if (stack_iface == nullptr) {
54 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
55 << ", IBluetoothAudioPort Invalid";
56 } else if (!UpdateAudioConfig(audio_config)) {
57 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
58 << ", AudioConfiguration=" << audio_config.toString()
59 << " Invalid";
60 } else if (!UpdateDataPath(mq_desc)) {
61 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
62 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080063 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080064 } else {
65 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080066 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080067 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
68 << ", AudioConfiguration=" << audio_config.toString();
69 ReportSessionStatus();
70 }
71}
72
73void BluetoothAudioSession::OnSessionEnded() {
74 std::lock_guard<std::recursive_mutex> guard(mutex_);
75 bool toggled = IsSessionReady();
76 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080077 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080078 stack_iface_ = nullptr;
79 UpdateDataPath(nullptr);
80 if (toggled) {
81 ReportSessionStatus();
82 }
83}
84
85/***
86 *
87 * Util methods
88 *
89 ***/
90
Josh Wu75462aa2022-01-21 21:51:21 -080091const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080092 std::lock_guard<std::recursive_mutex> guard(mutex_);
93 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080094 switch (session_type_) {
95 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +080096 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080097 return AudioConfiguration(CodecConfiguration{});
Yuyang Huangaa70c112023-10-26 16:01:45 -070098 case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
99 return AudioConfiguration(HfpConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800100 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
101 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800102 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800103 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
104 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800105 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800106 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800107 }
108 }
109 return *audio_config_;
110}
111
112void BluetoothAudioSession::ReportAudioConfigChanged(
113 const AudioConfiguration& audio_config) {
114 if (session_type_ !=
115 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
116 session_type_ !=
Alice Kuo851ef342022-08-25 02:45:02 +0800117 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800118 return;
119 }
Alice Kuo851ef342022-08-25 02:45:02 +0800120
Josh Wu20bac522021-12-29 23:52:39 -0800121 std::lock_guard<std::recursive_mutex> guard(mutex_);
Alice Kuo851ef342022-08-25 02:45:02 +0800122 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
123 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
124 << toString(session_type_);
125 return;
126 }
127
Patty Huangf5b38af2023-03-23 23:19:00 +0800128 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
Alice Kuo851ef342022-08-25 02:45:02 +0800129
Josh Wu20bac522021-12-29 23:52:39 -0800130 if (observers_.empty()) {
131 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
132 << " has NO port state observer";
133 return;
134 }
135 for (auto& observer : observers_) {
136 uint16_t cookie = observer.first;
137 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
138 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
139 << ", bluetooth_audio=0x"
140 << ::android::base::StringPrintf("%04x", cookie);
Patty Huangf5b38af2023-03-23 23:19:00 +0800141 if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800142 cb->audio_configuration_changed_cb_(cookie);
143 }
144 }
145}
146
147bool BluetoothAudioSession::IsSessionReady() {
148 std::lock_guard<std::recursive_mutex> guard(mutex_);
149
150 bool is_mq_valid =
151 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
152 session_type_ ==
153 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
154 session_type_ ==
155 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800156 session_type_ ==
157 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800158 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700159 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800160 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800161 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800162}
163
164/***
165 *
166 * Status callback methods
167 *
168 ***/
169
170uint16_t BluetoothAudioSession::RegisterStatusCback(
171 const PortStatusCallbacks& callbacks) {
172 std::lock_guard<std::recursive_mutex> guard(mutex_);
173 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
174 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
175
176 while (cookie < cookie_upper_bound) {
177 if (observers_.find(cookie) == observers_.end()) {
178 break;
179 }
180 ++cookie;
181 }
182 if (cookie >= cookie_upper_bound) {
183 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
184 << " has " << observers_.size()
185 << " observers already (No Resource)";
186 return kObserversCookieUndefined;
187 }
188 std::shared_ptr<PortStatusCallbacks> cb =
189 std::make_shared<PortStatusCallbacks>();
190 *cb = callbacks;
191 observers_[cookie] = cb;
192 return cookie;
193}
194
195void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
196 std::lock_guard<std::recursive_mutex> guard(mutex_);
197 if (observers_.erase(cookie) != 1) {
198 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
199 << " no such provider=0x"
200 << ::android::base::StringPrintf("%04x", cookie);
201 }
202}
203
204/***
205 *
206 * Stream methods
207 *
208 ***/
209
Cheney Ni6ecbc762022-03-03 00:12:48 +0800210bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800211 std::lock_guard<std::recursive_mutex> guard(mutex_);
212 if (!IsSessionReady()) {
213 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
214 << " has NO session";
215 return false;
216 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800217 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800218 if (!hal_retval.isOk()) {
219 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
220 << toString(session_type_) << " failed";
221 return false;
222 }
223 return true;
224}
225
226bool BluetoothAudioSession::SuspendStream() {
227 std::lock_guard<std::recursive_mutex> guard(mutex_);
228 if (!IsSessionReady()) {
229 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
230 << " has NO session";
231 return false;
232 }
233 auto hal_retval = stack_iface_->suspendStream();
234 if (!hal_retval.isOk()) {
235 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
236 << toString(session_type_) << " failed";
237 return false;
238 }
239 return true;
240}
241
242void BluetoothAudioSession::StopStream() {
243 std::lock_guard<std::recursive_mutex> guard(mutex_);
244 if (!IsSessionReady()) {
245 return;
246 }
247 auto hal_retval = stack_iface_->stopStream();
248 if (!hal_retval.isOk()) {
249 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
250 << toString(session_type_) << " failed";
251 }
252}
253
254/***
255 *
256 * Private methods
257 *
258 ***/
259
260bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
261 if (mq_desc == nullptr) {
262 // usecase of reset by nullptr
263 data_mq_ = nullptr;
264 return true;
265 }
266 std::unique_ptr<DataMQ> temp_mq;
267 temp_mq.reset(new DataMQ(*mq_desc));
268 if (!temp_mq || !temp_mq->isValid()) {
269 data_mq_ = nullptr;
270 return false;
271 }
272 data_mq_ = std::move(temp_mq);
273 return true;
274}
275
276bool BluetoothAudioSession::UpdateAudioConfig(
277 const AudioConfiguration& audio_config) {
278 bool is_software_session =
279 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
280 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700281 session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
282 session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800283 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800284 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
285 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800286 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
287 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800288 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800289 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
290 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Yuyang Huangaa70c112023-10-26 16:01:45 -0700291 bool is_offload_hfp_session =
292 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH;
Alice Kuoee398a92022-07-10 23:59:18 +0800293 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800294 (session_type_ ==
295 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
296 session_type_ ==
297 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800298 bool is_offload_le_audio_broadcast_session =
299 (session_type_ ==
300 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800301 auto audio_config_tag = audio_config.getTag();
302 bool is_software_audio_config =
303 (is_software_session &&
304 audio_config_tag == AudioConfiguration::pcmConfig);
305 bool is_a2dp_offload_audio_config =
306 (is_offload_a2dp_session &&
Antoine SOULIER4e34d052023-09-29 19:10:07 +0000307 (audio_config_tag == AudioConfiguration::a2dp ||
308 audio_config_tag == AudioConfiguration::a2dpConfig));
Yuyang Huangaa70c112023-10-26 16:01:45 -0700309 bool is_hfp_offload_audio_config =
310 (is_offload_hfp_session &&
311 audio_config_tag == AudioConfiguration::hfpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800312 bool is_le_audio_offload_unicast_audio_config =
313 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800314 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800315 bool is_le_audio_offload_broadcast_audio_config =
316 (is_offload_le_audio_broadcast_session &&
317 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800318 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Yuyang Huangaa70c112023-10-26 16:01:45 -0700319 !is_hfp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800320 !is_le_audio_offload_unicast_audio_config &&
321 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800322 return false;
323 }
324 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
325 return true;
326}
327
328void BluetoothAudioSession::ReportSessionStatus() {
329 // This is locked already by OnSessionStarted / OnSessionEnded
330 if (observers_.empty()) {
331 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
332 << " has NO port state observer";
333 return;
334 }
335 for (auto& observer : observers_) {
336 uint16_t cookie = observer.first;
337 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
338 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
339 << " notify to bluetooth_audio=0x"
340 << ::android::base::StringPrintf("%04x", cookie);
341 callback->session_changed_cb_(cookie);
342 }
343}
344
345/***
346 *
347 * PCM methods
348 *
349 ***/
350
351size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
352 size_t bytes) {
353 if (buffer == nullptr || bytes <= 0) {
354 return 0;
355 }
356 size_t total_written = 0;
357 int timeout_ms = kFmqSendTimeoutMs;
358 do {
359 std::unique_lock<std::recursive_mutex> lock(mutex_);
360 if (!IsSessionReady()) {
361 break;
362 }
363 size_t num_bytes_to_write = data_mq_->availableToWrite();
364 if (num_bytes_to_write) {
365 if (num_bytes_to_write > (bytes - total_written)) {
366 num_bytes_to_write = bytes - total_written;
367 }
368
369 if (!data_mq_->write(
370 static_cast<const MQDataType*>(buffer) + total_written,
371 num_bytes_to_write)) {
372 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
373 << " failed";
374 return total_written;
375 }
376 total_written += num_bytes_to_write;
377 } else if (timeout_ms >= kWritePollMs) {
378 lock.unlock();
379 usleep(kWritePollMs * 1000);
380 timeout_ms -= kWritePollMs;
381 } else {
382 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
383 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
384 return total_written;
385 }
386 } while (total_written < bytes);
387 return total_written;
388}
389
390size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
391 if (buffer == nullptr || bytes <= 0) {
392 return 0;
393 }
394 size_t total_read = 0;
395 int timeout_ms = kFmqReceiveTimeoutMs;
396 do {
397 std::unique_lock<std::recursive_mutex> lock(mutex_);
398 if (!IsSessionReady()) {
399 break;
400 }
401 size_t num_bytes_to_read = data_mq_->availableToRead();
402 if (num_bytes_to_read) {
403 if (num_bytes_to_read > (bytes - total_read)) {
404 num_bytes_to_read = bytes - total_read;
405 }
406 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
407 num_bytes_to_read)) {
408 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
409 << " failed";
410 return total_read;
411 }
412 total_read += num_bytes_to_read;
413 } else if (timeout_ms >= kReadPollMs) {
414 lock.unlock();
415 usleep(kReadPollMs * 1000);
416 timeout_ms -= kReadPollMs;
417 continue;
418 } else {
419 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
420 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
421 return total_read;
422 }
423 } while (total_read < bytes);
424 return total_read;
425}
426
427/***
428 *
429 * Other methods
430 *
431 ***/
432
433void BluetoothAudioSession::ReportControlStatus(bool start_resp,
434 BluetoothAudioStatus status) {
435 std::lock_guard<std::recursive_mutex> guard(mutex_);
436 if (observers_.empty()) {
437 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
438 << " has NO port state observer";
439 return;
440 }
441 for (auto& observer : observers_) {
442 uint16_t cookie = observer.first;
443 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
444 LOG(INFO) << __func__ << " - status=" << toString(status)
445 << " for SessionType=" << toString(session_type_)
446 << ", bluetooth_audio=0x"
447 << ::android::base::StringPrintf("%04x", cookie)
448 << (start_resp ? " started" : " suspended");
449 callback->control_result_cb_(cookie, start_resp, status);
450 }
451}
452
Chen Chen81f38e52022-02-09 13:27:35 -0800453void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
Alice Kuo42b85ab2023-11-20 14:28:41 +0800454 if (session_type_ != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
455 return;
456 }
Chen Chen81f38e52022-02-09 13:27:35 -0800457 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800458 low_latency_allowed_ = allowed;
kuanyuhuang25b48192023-08-07 05:05:52 +0000459 // TODO(b/294498919): Remove this after there is API to update latency mode
460 // after audio session started. If low_latency_allowed_ is true, the session
461 // can support LOW_LATENCY and FREE LatencyMode.
462 if (low_latency_allowed_) {
463 if (std::find(latency_modes_.begin(), latency_modes_.end(),
464 LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
465 LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
466 latency_modes_.push_back(LatencyMode::LOW_LATENCY);
467 }
468 }
Chen Chen81f38e52022-02-09 13:27:35 -0800469 if (observers_.empty()) {
470 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
471 << " has NO port state observer";
472 return;
473 }
474 for (auto& observer : observers_) {
475 uint16_t cookie = observer.first;
476 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800477 LOG(INFO) << __func__
478 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700479 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
480 callback->low_latency_mode_allowed_cb_(cookie, allowed);
481 }
Chen Chen81f38e52022-02-09 13:27:35 -0800482 }
483}
484
Josh Wu20bac522021-12-29 23:52:39 -0800485bool BluetoothAudioSession::GetPresentationPosition(
486 PresentationPosition& presentation_position) {
487 std::lock_guard<std::recursive_mutex> guard(mutex_);
488 if (!IsSessionReady()) {
489 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
490 << " has NO session";
491 return false;
492 }
493 bool retval = false;
494
495 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
496 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
497 << toString(session_type_) << " failed";
498 return false;
499 }
500 return retval;
501}
502
503void BluetoothAudioSession::UpdateSourceMetadata(
504 const struct source_metadata& source_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800505 ssize_t track_count = source_metadata.track_count;
506 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
507 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800508 SourceMetadata hal_source_metadata;
509 hal_source_metadata.tracks.resize(track_count);
510 for (int i = 0; i < track_count; i++) {
511 hal_source_metadata.tracks[i].usage =
512 static_cast<media::audio::common::AudioUsage>(
513 source_metadata.tracks[i].usage);
514 hal_source_metadata.tracks[i].contentType =
515 static_cast<media::audio::common::AudioContentType>(
516 source_metadata.tracks[i].content_type);
517 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
518 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
519 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
520 << ", content="
521 << toString(hal_source_metadata.tracks[i].contentType)
522 << ", gain=" << hal_source_metadata.tracks[i].gain;
523 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700524 UpdateSourceMetadata(hal_source_metadata);
Josh Wu20bac522021-12-29 23:52:39 -0800525}
526
527void BluetoothAudioSession::UpdateSinkMetadata(
528 const struct sink_metadata& sink_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800529 ssize_t track_count = sink_metadata.track_count;
530 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
531 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800532 SinkMetadata hal_sink_metadata;
533 hal_sink_metadata.tracks.resize(track_count);
534 for (int i = 0; i < track_count; i++) {
535 hal_sink_metadata.tracks[i].source =
536 static_cast<media::audio::common::AudioSource>(
537 sink_metadata.tracks[i].source);
538 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
539 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
540 << ", source=" << sink_metadata.tracks[i].source
541 << ", dest_device=" << sink_metadata.tracks[i].dest_device
542 << ", gain=" << sink_metadata.tracks[i].gain
543 << ", dest_device_address="
544 << sink_metadata.tracks[i].dest_device_address;
545 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700546 UpdateSinkMetadata(hal_sink_metadata);
547}
548
549bool BluetoothAudioSession::UpdateSourceMetadata(
550 const SourceMetadata& hal_source_metadata) {
551 std::lock_guard<std::recursive_mutex> guard(mutex_);
552 if (!IsSessionReady()) {
553 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
554 << " has NO session";
555 return false;
556 }
557
558 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
559 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
560 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
561 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
562 return false;
563 }
564
565 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
566 if (!hal_retval.isOk()) {
567 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
568 << toString(session_type_) << " failed";
569 return false;
570 }
571 return true;
572}
573
574bool BluetoothAudioSession::UpdateSinkMetadata(
575 const SinkMetadata& hal_sink_metadata) {
576 std::lock_guard<std::recursive_mutex> guard(mutex_);
577 if (!IsSessionReady()) {
578 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
579 << " has NO session";
580 return false;
581 }
582
583 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
584 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
585 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
586 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
587 return false;
588 }
Josh Wu20bac522021-12-29 23:52:39 -0800589
590 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
591 if (!hal_retval.isOk()) {
592 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
593 << toString(session_type_) << " failed";
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700594 return false;
Josh Wu20bac522021-12-29 23:52:39 -0800595 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700596 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800597}
598
Cheney Ni6ecbc762022-03-03 00:12:48 +0800599std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
600 std::lock_guard<std::recursive_mutex> guard(mutex_);
601 if (!IsSessionReady()) {
602 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
603 << " has NO session";
604 return std::vector<LatencyMode>();
605 }
Limon Mia7c480342023-11-20 03:59:49 +0000606
607 std::vector<LatencyMode> supported_latency_modes;
608 if (session_type_ ==
609 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
610 for (LatencyMode mode : latency_modes_) {
611 if (mode == LatencyMode::LOW_LATENCY) {
612 // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
613 continue;
614 }
615 supported_latency_modes.push_back(mode);
616 }
617 } else {
618 for (LatencyMode mode : latency_modes_) {
619 if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
620 // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
621 continue;
622 }
623 if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
624 mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
625 // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC sessions
626 continue;
627 }
628 supported_latency_modes.push_back(mode);
629 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800630 }
Limon Mia7c480342023-11-20 03:59:49 +0000631 return supported_latency_modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800632}
633
634void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800635 std::lock_guard<std::recursive_mutex> guard(mutex_);
636 if (!IsSessionReady()) {
637 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
638 << " has NO session";
639 return;
640 }
641
642 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
643 if (!hal_retval.isOk()) {
644 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
645 << toString(session_type_) << " failed";
646 }
647}
648
Josh Wu20bac522021-12-29 23:52:39 -0800649bool BluetoothAudioSession::IsAidlAvailable() {
650 if (is_aidl_checked) return is_aidl_available;
651 is_aidl_available =
652 (AServiceManager_checkService(
653 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
654 is_aidl_checked = true;
655 return is_aidl_available;
656}
657
658/***
659 *
660 * BluetoothAudioSessionInstance
661 *
662 ***/
663std::mutex BluetoothAudioSessionInstance::mutex_;
664std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
665 BluetoothAudioSessionInstance::sessions_map_;
666
667std::shared_ptr<BluetoothAudioSession>
668BluetoothAudioSessionInstance::GetSessionInstance(
669 const SessionType& session_type) {
670 std::lock_guard<std::mutex> guard(mutex_);
671
672 if (!sessions_map_.empty()) {
673 auto entry = sessions_map_.find(session_type);
674 if (entry != sessions_map_.end()) {
675 return entry->second;
676 }
677 }
678 std::shared_ptr<BluetoothAudioSession> session_ptr =
679 std::make_shared<BluetoothAudioSession>(session_type);
680 sessions_map_[session_type] = session_ptr;
681 return session_ptr;
682}
683
684} // namespace audio
685} // namespace bluetooth
686} // namespace hardware
687} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800688} // namespace aidl