blob: 67ba93cdd7ef76f1cde949471edd49769638c286 [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>
Limon Miab58cee42023-12-01 12:16:00 +000023#include <com_android_btaudio_hal_flags.h>
Mikhail Naganovd5f0d132023-07-26 17:26:02 -070024#include <hardware/audio.h>
Josh Wu20bac522021-12-29 23:52:39 -080025
26#include "BluetoothAudioSession.h"
27
28namespace aidl {
29namespace android {
30namespace hardware {
31namespace bluetooth {
32namespace audio {
33
34static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
35static constexpr int kFmqReceiveTimeoutMs =
36 1000; // 1000 ms timeout for receiving
37static constexpr int kWritePollMs = 1; // polled non-blocking interval
38static constexpr int kReadPollMs = 1; // polled non-blocking interval
39
Limon Miab58cee42023-12-01 12:16:00 +000040static std::string toString(const std::vector<LatencyMode>& latencies) {
41 std::stringstream latencyModesStr;
42 for (LatencyMode mode : latencies) {
43 latencyModesStr << " " << toString(mode);
44 }
45 return latencyModesStr.str();
46}
47
Josh Wu20bac522021-12-29 23:52:39 -080048BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080049 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080050
51/***
52 *
53 * Callback methods
54 *
55 ***/
56
57void BluetoothAudioSession::OnSessionStarted(
58 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080059 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
60 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080061 std::lock_guard<std::recursive_mutex> guard(mutex_);
62 if (stack_iface == nullptr) {
63 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
64 << ", IBluetoothAudioPort Invalid";
65 } else if (!UpdateAudioConfig(audio_config)) {
66 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
67 << ", AudioConfiguration=" << audio_config.toString()
68 << " Invalid";
69 } else if (!UpdateDataPath(mq_desc)) {
70 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
71 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080072 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080073 } else {
74 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080075 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080076 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
Limon Miab58cee42023-12-01 12:16:00 +000077 << " - All LatencyModes=" << toString(latency_modes)
Josh Wu20bac522021-12-29 23:52:39 -080078 << ", AudioConfiguration=" << audio_config.toString();
79 ReportSessionStatus();
80 }
81}
82
83void BluetoothAudioSession::OnSessionEnded() {
84 std::lock_guard<std::recursive_mutex> guard(mutex_);
85 bool toggled = IsSessionReady();
86 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080087 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080088 stack_iface_ = nullptr;
89 UpdateDataPath(nullptr);
90 if (toggled) {
91 ReportSessionStatus();
92 }
93}
94
95/***
96 *
97 * Util methods
98 *
99 ***/
100
Josh Wu75462aa2022-01-21 21:51:21 -0800101const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -0800102 std::lock_guard<std::recursive_mutex> guard(mutex_);
103 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -0800104 switch (session_type_) {
105 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +0800106 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800107 return AudioConfiguration(CodecConfiguration{});
Yuyang Huangaa70c112023-10-26 16:01:45 -0700108 case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
109 return AudioConfiguration(HfpConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800110 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
111 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800112 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800113 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
114 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800115 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800116 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800117 }
118 }
119 return *audio_config_;
120}
121
122void BluetoothAudioSession::ReportAudioConfigChanged(
123 const AudioConfiguration& audio_config) {
124 if (session_type_ !=
125 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
126 session_type_ !=
Alice Kuo851ef342022-08-25 02:45:02 +0800127 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800128 return;
129 }
Alice Kuo851ef342022-08-25 02:45:02 +0800130
Josh Wu20bac522021-12-29 23:52:39 -0800131 std::lock_guard<std::recursive_mutex> guard(mutex_);
Alice Kuo851ef342022-08-25 02:45:02 +0800132 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
133 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
134 << toString(session_type_);
135 return;
136 }
137
Patty Huangf5b38af2023-03-23 23:19:00 +0800138 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
Alice Kuo851ef342022-08-25 02:45:02 +0800139
Josh Wu20bac522021-12-29 23:52:39 -0800140 if (observers_.empty()) {
141 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
142 << " has NO port state observer";
143 return;
144 }
145 for (auto& observer : observers_) {
146 uint16_t cookie = observer.first;
147 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
148 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
149 << ", bluetooth_audio=0x"
150 << ::android::base::StringPrintf("%04x", cookie);
Patty Huangf5b38af2023-03-23 23:19:00 +0800151 if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800152 cb->audio_configuration_changed_cb_(cookie);
153 }
154 }
155}
156
157bool BluetoothAudioSession::IsSessionReady() {
158 std::lock_guard<std::recursive_mutex> guard(mutex_);
159
160 bool is_mq_valid =
161 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
162 session_type_ ==
163 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
164 session_type_ ==
165 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800166 session_type_ ==
167 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800168 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700169 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800170 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800171 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800172}
173
174/***
175 *
176 * Status callback methods
177 *
178 ***/
179
180uint16_t BluetoothAudioSession::RegisterStatusCback(
181 const PortStatusCallbacks& callbacks) {
182 std::lock_guard<std::recursive_mutex> guard(mutex_);
183 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
184 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
185
186 while (cookie < cookie_upper_bound) {
187 if (observers_.find(cookie) == observers_.end()) {
188 break;
189 }
190 ++cookie;
191 }
192 if (cookie >= cookie_upper_bound) {
193 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
194 << " has " << observers_.size()
195 << " observers already (No Resource)";
196 return kObserversCookieUndefined;
197 }
198 std::shared_ptr<PortStatusCallbacks> cb =
199 std::make_shared<PortStatusCallbacks>();
200 *cb = callbacks;
201 observers_[cookie] = cb;
202 return cookie;
203}
204
205void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
206 std::lock_guard<std::recursive_mutex> guard(mutex_);
207 if (observers_.erase(cookie) != 1) {
208 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
209 << " no such provider=0x"
210 << ::android::base::StringPrintf("%04x", cookie);
211 }
212}
213
214/***
215 *
216 * Stream methods
217 *
218 ***/
219
Cheney Ni6ecbc762022-03-03 00:12:48 +0800220bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800221 std::lock_guard<std::recursive_mutex> guard(mutex_);
222 if (!IsSessionReady()) {
223 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
224 << " has NO session";
225 return false;
226 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800227 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800228 if (!hal_retval.isOk()) {
229 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
230 << toString(session_type_) << " failed";
231 return false;
232 }
233 return true;
234}
235
236bool BluetoothAudioSession::SuspendStream() {
237 std::lock_guard<std::recursive_mutex> guard(mutex_);
238 if (!IsSessionReady()) {
239 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
240 << " has NO session";
241 return false;
242 }
243 auto hal_retval = stack_iface_->suspendStream();
244 if (!hal_retval.isOk()) {
245 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
246 << toString(session_type_) << " failed";
247 return false;
248 }
249 return true;
250}
251
252void BluetoothAudioSession::StopStream() {
253 std::lock_guard<std::recursive_mutex> guard(mutex_);
254 if (!IsSessionReady()) {
255 return;
256 }
257 auto hal_retval = stack_iface_->stopStream();
258 if (!hal_retval.isOk()) {
259 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
260 << toString(session_type_) << " failed";
261 }
262}
263
264/***
265 *
266 * Private methods
267 *
268 ***/
269
270bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
271 if (mq_desc == nullptr) {
272 // usecase of reset by nullptr
273 data_mq_ = nullptr;
274 return true;
275 }
276 std::unique_ptr<DataMQ> temp_mq;
277 temp_mq.reset(new DataMQ(*mq_desc));
278 if (!temp_mq || !temp_mq->isValid()) {
279 data_mq_ = nullptr;
280 return false;
281 }
282 data_mq_ = std::move(temp_mq);
283 return true;
284}
285
286bool BluetoothAudioSession::UpdateAudioConfig(
287 const AudioConfiguration& audio_config) {
288 bool is_software_session =
289 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
290 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700291 session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
292 session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800293 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800294 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
295 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800296 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
297 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800298 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800299 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
300 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Yuyang Huangaa70c112023-10-26 16:01:45 -0700301 bool is_offload_hfp_session =
302 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH;
Alice Kuoee398a92022-07-10 23:59:18 +0800303 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800304 (session_type_ ==
305 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
306 session_type_ ==
307 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800308 bool is_offload_le_audio_broadcast_session =
309 (session_type_ ==
310 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800311 auto audio_config_tag = audio_config.getTag();
312 bool is_software_audio_config =
313 (is_software_session &&
314 audio_config_tag == AudioConfiguration::pcmConfig);
315 bool is_a2dp_offload_audio_config =
316 (is_offload_a2dp_session &&
Antoine SOULIER4e34d052023-09-29 19:10:07 +0000317 (audio_config_tag == AudioConfiguration::a2dp ||
318 audio_config_tag == AudioConfiguration::a2dpConfig));
Yuyang Huangaa70c112023-10-26 16:01:45 -0700319 bool is_hfp_offload_audio_config =
320 (is_offload_hfp_session &&
321 audio_config_tag == AudioConfiguration::hfpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800322 bool is_le_audio_offload_unicast_audio_config =
323 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800324 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800325 bool is_le_audio_offload_broadcast_audio_config =
326 (is_offload_le_audio_broadcast_session &&
327 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800328 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Yuyang Huangaa70c112023-10-26 16:01:45 -0700329 !is_hfp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800330 !is_le_audio_offload_unicast_audio_config &&
331 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800332 return false;
333 }
334 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
335 return true;
336}
337
338void BluetoothAudioSession::ReportSessionStatus() {
339 // This is locked already by OnSessionStarted / OnSessionEnded
340 if (observers_.empty()) {
341 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
342 << " has NO port state observer";
343 return;
344 }
345 for (auto& observer : observers_) {
346 uint16_t cookie = observer.first;
347 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
348 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
349 << " notify to bluetooth_audio=0x"
350 << ::android::base::StringPrintf("%04x", cookie);
351 callback->session_changed_cb_(cookie);
352 }
353}
354
355/***
356 *
357 * PCM methods
358 *
359 ***/
360
361size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
362 size_t bytes) {
363 if (buffer == nullptr || bytes <= 0) {
364 return 0;
365 }
366 size_t total_written = 0;
367 int timeout_ms = kFmqSendTimeoutMs;
368 do {
369 std::unique_lock<std::recursive_mutex> lock(mutex_);
370 if (!IsSessionReady()) {
371 break;
372 }
373 size_t num_bytes_to_write = data_mq_->availableToWrite();
374 if (num_bytes_to_write) {
375 if (num_bytes_to_write > (bytes - total_written)) {
376 num_bytes_to_write = bytes - total_written;
377 }
378
379 if (!data_mq_->write(
380 static_cast<const MQDataType*>(buffer) + total_written,
381 num_bytes_to_write)) {
382 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
383 << " failed";
384 return total_written;
385 }
386 total_written += num_bytes_to_write;
387 } else if (timeout_ms >= kWritePollMs) {
388 lock.unlock();
389 usleep(kWritePollMs * 1000);
390 timeout_ms -= kWritePollMs;
391 } else {
392 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
393 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
394 return total_written;
395 }
396 } while (total_written < bytes);
397 return total_written;
398}
399
400size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
401 if (buffer == nullptr || bytes <= 0) {
402 return 0;
403 }
404 size_t total_read = 0;
405 int timeout_ms = kFmqReceiveTimeoutMs;
406 do {
407 std::unique_lock<std::recursive_mutex> lock(mutex_);
408 if (!IsSessionReady()) {
409 break;
410 }
411 size_t num_bytes_to_read = data_mq_->availableToRead();
412 if (num_bytes_to_read) {
413 if (num_bytes_to_read > (bytes - total_read)) {
414 num_bytes_to_read = bytes - total_read;
415 }
416 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
417 num_bytes_to_read)) {
418 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
419 << " failed";
420 return total_read;
421 }
422 total_read += num_bytes_to_read;
423 } else if (timeout_ms >= kReadPollMs) {
424 lock.unlock();
425 usleep(kReadPollMs * 1000);
426 timeout_ms -= kReadPollMs;
427 continue;
428 } else {
429 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
430 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
431 return total_read;
432 }
433 } while (total_read < bytes);
434 return total_read;
435}
436
437/***
438 *
439 * Other methods
440 *
441 ***/
442
443void BluetoothAudioSession::ReportControlStatus(bool start_resp,
444 BluetoothAudioStatus status) {
445 std::lock_guard<std::recursive_mutex> guard(mutex_);
446 if (observers_.empty()) {
447 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
448 << " has NO port state observer";
449 return;
450 }
451 for (auto& observer : observers_) {
452 uint16_t cookie = observer.first;
453 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
454 LOG(INFO) << __func__ << " - status=" << toString(status)
455 << " for SessionType=" << toString(session_type_)
456 << ", bluetooth_audio=0x"
457 << ::android::base::StringPrintf("%04x", cookie)
458 << (start_resp ? " started" : " suspended");
459 callback->control_result_cb_(cookie, start_resp, status);
460 }
461}
462
Chen Chen81f38e52022-02-09 13:27:35 -0800463void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
Alice Kuo42b85ab2023-11-20 14:28:41 +0800464 if (session_type_ != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
465 return;
466 }
Chen Chen81f38e52022-02-09 13:27:35 -0800467 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800468 low_latency_allowed_ = allowed;
kuanyuhuang25b48192023-08-07 05:05:52 +0000469 // TODO(b/294498919): Remove this after there is API to update latency mode
470 // after audio session started. If low_latency_allowed_ is true, the session
471 // can support LOW_LATENCY and FREE LatencyMode.
472 if (low_latency_allowed_) {
473 if (std::find(latency_modes_.begin(), latency_modes_.end(),
474 LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
475 LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
476 latency_modes_.push_back(LatencyMode::LOW_LATENCY);
477 }
478 }
Chen Chen81f38e52022-02-09 13:27:35 -0800479 if (observers_.empty()) {
480 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
481 << " has NO port state observer";
482 return;
483 }
484 for (auto& observer : observers_) {
485 uint16_t cookie = observer.first;
486 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800487 LOG(INFO) << __func__
488 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700489 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
490 callback->low_latency_mode_allowed_cb_(cookie, allowed);
491 }
Chen Chen81f38e52022-02-09 13:27:35 -0800492 }
493}
494
Josh Wu20bac522021-12-29 23:52:39 -0800495bool BluetoothAudioSession::GetPresentationPosition(
496 PresentationPosition& presentation_position) {
497 std::lock_guard<std::recursive_mutex> guard(mutex_);
498 if (!IsSessionReady()) {
499 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
500 << " has NO session";
501 return false;
502 }
Josh Wu20bac522021-12-29 23:52:39 -0800503 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
504 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
505 << toString(session_type_) << " failed";
506 return false;
507 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800508 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800509}
510
511void BluetoothAudioSession::UpdateSourceMetadata(
512 const struct source_metadata& source_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800513 ssize_t track_count = source_metadata.track_count;
514 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
515 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800516 SourceMetadata hal_source_metadata;
517 hal_source_metadata.tracks.resize(track_count);
518 for (int i = 0; i < track_count; i++) {
519 hal_source_metadata.tracks[i].usage =
520 static_cast<media::audio::common::AudioUsage>(
521 source_metadata.tracks[i].usage);
522 hal_source_metadata.tracks[i].contentType =
523 static_cast<media::audio::common::AudioContentType>(
524 source_metadata.tracks[i].content_type);
525 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
526 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
527 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
528 << ", content="
529 << toString(hal_source_metadata.tracks[i].contentType)
530 << ", gain=" << hal_source_metadata.tracks[i].gain;
531 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700532 UpdateSourceMetadata(hal_source_metadata);
Josh Wu20bac522021-12-29 23:52:39 -0800533}
534
535void BluetoothAudioSession::UpdateSinkMetadata(
536 const struct sink_metadata& sink_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800537 ssize_t track_count = sink_metadata.track_count;
538 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
539 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800540 SinkMetadata hal_sink_metadata;
541 hal_sink_metadata.tracks.resize(track_count);
542 for (int i = 0; i < track_count; i++) {
543 hal_sink_metadata.tracks[i].source =
544 static_cast<media::audio::common::AudioSource>(
545 sink_metadata.tracks[i].source);
546 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
547 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
548 << ", source=" << sink_metadata.tracks[i].source
549 << ", dest_device=" << sink_metadata.tracks[i].dest_device
550 << ", gain=" << sink_metadata.tracks[i].gain
551 << ", dest_device_address="
552 << sink_metadata.tracks[i].dest_device_address;
553 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700554 UpdateSinkMetadata(hal_sink_metadata);
555}
556
557bool BluetoothAudioSession::UpdateSourceMetadata(
558 const SourceMetadata& hal_source_metadata) {
559 std::lock_guard<std::recursive_mutex> guard(mutex_);
560 if (!IsSessionReady()) {
561 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
562 << " has NO session";
563 return false;
564 }
565
566 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
567 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
568 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
569 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
570 return false;
571 }
572
573 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
574 if (!hal_retval.isOk()) {
575 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
576 << toString(session_type_) << " failed";
577 return false;
578 }
579 return true;
580}
581
582bool BluetoothAudioSession::UpdateSinkMetadata(
583 const SinkMetadata& hal_sink_metadata) {
584 std::lock_guard<std::recursive_mutex> guard(mutex_);
585 if (!IsSessionReady()) {
586 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
587 << " has NO session";
588 return false;
589 }
590
591 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
592 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
593 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
594 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
595 return false;
596 }
Josh Wu20bac522021-12-29 23:52:39 -0800597
598 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
599 if (!hal_retval.isOk()) {
600 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
601 << toString(session_type_) << " failed";
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700602 return false;
Josh Wu20bac522021-12-29 23:52:39 -0800603 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700604 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800605}
606
Cheney Ni6ecbc762022-03-03 00:12:48 +0800607std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
608 std::lock_guard<std::recursive_mutex> guard(mutex_);
609 if (!IsSessionReady()) {
610 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
611 << " has NO session";
612 return std::vector<LatencyMode>();
613 }
Limon Mia7c480342023-11-20 03:59:49 +0000614
Limon Miab58cee42023-12-01 12:16:00 +0000615 if (com::android::btaudio::hal::flags::dsa_lea()) {
616 std::vector<LatencyMode> supported_latency_modes;
617 if (session_type_ ==
618 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
619 for (LatencyMode mode : latency_modes_) {
620 if (mode == LatencyMode::LOW_LATENCY) {
621 // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
622 continue;
623 }
624 supported_latency_modes.push_back(mode);
Limon Mia7c480342023-11-20 03:59:49 +0000625 }
Limon Miab58cee42023-12-01 12:16:00 +0000626 } else {
627 for (LatencyMode mode : latency_modes_) {
628 if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
629 // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
630 continue;
631 }
632 if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
633 mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
634 // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC
635 // sessions
636 continue;
637 }
638 supported_latency_modes.push_back(mode);
639 }
Limon Mia7c480342023-11-20 03:59:49 +0000640 }
Limon Miab58cee42023-12-01 12:16:00 +0000641 LOG(DEBUG) << __func__ << " - Supported LatencyMode="
642 << toString(supported_latency_modes);
643 return supported_latency_modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800644 }
Limon Miab58cee42023-12-01 12:16:00 +0000645
646 if (low_latency_allowed_) return latency_modes_;
647 std::vector<LatencyMode> modes;
648 for (LatencyMode mode : latency_modes_) {
649 if (mode == LatencyMode::LOW_LATENCY)
650 // ignore those low latency mode if Bluetooth stack doesn't allow
651 continue;
652 modes.push_back(mode);
653 }
654 return modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800655}
656
657void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800658 std::lock_guard<std::recursive_mutex> guard(mutex_);
659 if (!IsSessionReady()) {
660 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
661 << " has NO session";
662 return;
663 }
664
665 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
666 if (!hal_retval.isOk()) {
667 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
668 << toString(session_type_) << " failed";
669 }
670}
671
Josh Wu20bac522021-12-29 23:52:39 -0800672bool BluetoothAudioSession::IsAidlAvailable() {
673 if (is_aidl_checked) return is_aidl_available;
674 is_aidl_available =
675 (AServiceManager_checkService(
676 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
677 is_aidl_checked = true;
678 return is_aidl_available;
679}
680
681/***
682 *
683 * BluetoothAudioSessionInstance
684 *
685 ***/
686std::mutex BluetoothAudioSessionInstance::mutex_;
687std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
688 BluetoothAudioSessionInstance::sessions_map_;
689
690std::shared_ptr<BluetoothAudioSession>
691BluetoothAudioSessionInstance::GetSessionInstance(
692 const SessionType& session_type) {
693 std::lock_guard<std::mutex> guard(mutex_);
694
695 if (!sessions_map_.empty()) {
696 auto entry = sessions_map_.find(session_type);
697 if (entry != sessions_map_.end()) {
698 return entry->second;
699 }
700 }
701 std::shared_ptr<BluetoothAudioSession> session_ptr =
702 std::make_shared<BluetoothAudioSession>(session_type);
703 sessions_map_[session_type] = session_ptr;
704 return session_ptr;
705}
706
707} // namespace audio
708} // namespace bluetooth
709} // namespace hardware
710} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800711} // namespace aidl