blob: b46b62c037c56058bb13f49dd010a652b0af40b1 [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;
Alice Kuo851ef342022-08-25 02:45:02 +080064 leaudio_connection_map_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080065 } else {
66 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080067 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080068 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
69 << ", AudioConfiguration=" << audio_config.toString();
70 ReportSessionStatus();
Alice Kuo851ef342022-08-25 02:45:02 +080071 is_streaming_ = false;
Josh Wu20bac522021-12-29 23:52:39 -080072 }
73}
74
75void BluetoothAudioSession::OnSessionEnded() {
76 std::lock_guard<std::recursive_mutex> guard(mutex_);
77 bool toggled = IsSessionReady();
78 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080079 audio_config_ = nullptr;
Alice Kuo851ef342022-08-25 02:45:02 +080080 leaudio_connection_map_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080081 stack_iface_ = nullptr;
82 UpdateDataPath(nullptr);
83 if (toggled) {
84 ReportSessionStatus();
85 }
Alice Kuo851ef342022-08-25 02:45:02 +080086 is_streaming_ = false;
Josh Wu20bac522021-12-29 23:52:39 -080087}
88
89/***
90 *
91 * Util methods
92 *
93 ***/
94
Josh Wu75462aa2022-01-21 21:51:21 -080095const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080096 std::lock_guard<std::recursive_mutex> guard(mutex_);
97 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080098 switch (session_type_) {
99 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +0800100 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800101 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800102 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
103 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800104 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800105 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
106 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800107 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800108 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800109 }
110 }
111 return *audio_config_;
112}
113
Alice Kuo851ef342022-08-25 02:45:02 +0800114const AudioConfiguration BluetoothAudioSession::GetLeAudioConnectionMap() {
115 std::lock_guard<std::recursive_mutex> guard(mutex_);
116 if (!IsSessionReady()) {
117 return AudioConfiguration(LeAudioConfiguration{});
118 }
119 return *leaudio_connection_map_;
120}
121
Josh Wu20bac522021-12-29 23:52:39 -0800122void 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
138 if (is_streaming_) {
139 if (audio_config_ == nullptr) {
140 LOG(ERROR) << __func__ << " for SessionType=" << toString(session_type_)
141 << " audio_config_ is nullptr during streaming. It shouldn't "
142 "be happened";
143 return;
144 }
145
146 auto new_leaudio_config =
147 audio_config.get<AudioConfiguration::leAudioConfig>();
148 auto current_leaudio_config =
149 (*audio_config_).get<AudioConfiguration::leAudioConfig>();
150 if (new_leaudio_config.codecType != current_leaudio_config.codecType) {
151 LOG(ERROR)
152 << __func__ << " for SessionType=" << toString(session_type_)
153 << " codec type changed during streaming. It shouldn't be happened ";
154 }
155 auto new_lc3_config = new_leaudio_config.leAudioCodecConfig
156 .get<LeAudioCodecConfiguration::lc3Config>();
157 auto current_lc3_config = current_leaudio_config.leAudioCodecConfig
158 .get<LeAudioCodecConfiguration::lc3Config>();
159 if ((new_lc3_config.pcmBitDepth != current_lc3_config.pcmBitDepth) ||
160 (new_lc3_config.samplingFrequencyHz !=
161 current_lc3_config.samplingFrequencyHz) ||
162 (new_lc3_config.frameDurationUs !=
163 current_lc3_config.frameDurationUs) ||
164 (new_lc3_config.octetsPerFrame != current_lc3_config.octetsPerFrame) ||
165 (new_lc3_config.blocksPerSdu != current_lc3_config.blocksPerSdu)) {
166 LOG(ERROR)
167 << __func__ << " for SessionType=" << toString(session_type_)
168 << " lc3 config changed during streaming. It shouldn't be happened";
169 return;
170 }
171
172 leaudio_connection_map_ =
173 std::make_unique<AudioConfiguration>(audio_config);
174 } else {
175 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
176 leaudio_connection_map_ =
177 std::make_unique<AudioConfiguration>(audio_config);
178 }
179
Josh Wu20bac522021-12-29 23:52:39 -0800180 if (observers_.empty()) {
181 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
182 << " has NO port state observer";
183 return;
184 }
185 for (auto& observer : observers_) {
186 uint16_t cookie = observer.first;
187 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
188 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
189 << ", bluetooth_audio=0x"
190 << ::android::base::StringPrintf("%04x", cookie);
Alice Kuo851ef342022-08-25 02:45:02 +0800191 if (is_streaming_) {
192 if (cb->soft_audio_configuration_changed_cb_ != nullptr) {
193 cb->soft_audio_configuration_changed_cb_(cookie);
194 }
195 } else if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800196 cb->audio_configuration_changed_cb_(cookie);
197 }
198 }
199}
200
201bool BluetoothAudioSession::IsSessionReady() {
202 std::lock_guard<std::recursive_mutex> guard(mutex_);
203
204 bool is_mq_valid =
205 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
206 session_type_ ==
207 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
208 session_type_ ==
209 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800210 session_type_ ==
211 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800212 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800213 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800214 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800215}
216
217/***
218 *
219 * Status callback methods
220 *
221 ***/
222
223uint16_t BluetoothAudioSession::RegisterStatusCback(
224 const PortStatusCallbacks& callbacks) {
225 std::lock_guard<std::recursive_mutex> guard(mutex_);
226 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
227 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
228
229 while (cookie < cookie_upper_bound) {
230 if (observers_.find(cookie) == observers_.end()) {
231 break;
232 }
233 ++cookie;
234 }
235 if (cookie >= cookie_upper_bound) {
236 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
237 << " has " << observers_.size()
238 << " observers already (No Resource)";
239 return kObserversCookieUndefined;
240 }
241 std::shared_ptr<PortStatusCallbacks> cb =
242 std::make_shared<PortStatusCallbacks>();
243 *cb = callbacks;
244 observers_[cookie] = cb;
245 return cookie;
246}
247
248void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
249 std::lock_guard<std::recursive_mutex> guard(mutex_);
250 if (observers_.erase(cookie) != 1) {
251 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
252 << " no such provider=0x"
253 << ::android::base::StringPrintf("%04x", cookie);
254 }
255}
256
257/***
258 *
259 * Stream methods
260 *
261 ***/
262
Cheney Ni6ecbc762022-03-03 00:12:48 +0800263bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800264 std::lock_guard<std::recursive_mutex> guard(mutex_);
265 if (!IsSessionReady()) {
266 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
267 << " has NO session";
268 return false;
269 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800270 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800271 if (!hal_retval.isOk()) {
272 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
273 << toString(session_type_) << " failed";
274 return false;
275 }
276 return true;
277}
278
279bool BluetoothAudioSession::SuspendStream() {
280 std::lock_guard<std::recursive_mutex> guard(mutex_);
281 if (!IsSessionReady()) {
282 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
283 << " has NO session";
284 return false;
285 }
286 auto hal_retval = stack_iface_->suspendStream();
287 if (!hal_retval.isOk()) {
288 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
289 << toString(session_type_) << " failed";
290 return false;
291 }
292 return true;
293}
294
295void BluetoothAudioSession::StopStream() {
296 std::lock_guard<std::recursive_mutex> guard(mutex_);
297 if (!IsSessionReady()) {
298 return;
299 }
300 auto hal_retval = stack_iface_->stopStream();
301 if (!hal_retval.isOk()) {
302 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
303 << toString(session_type_) << " failed";
304 }
305}
306
307/***
308 *
309 * Private methods
310 *
311 ***/
312
313bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
314 if (mq_desc == nullptr) {
315 // usecase of reset by nullptr
316 data_mq_ = nullptr;
317 return true;
318 }
319 std::unique_ptr<DataMQ> temp_mq;
320 temp_mq.reset(new DataMQ(*mq_desc));
321 if (!temp_mq || !temp_mq->isValid()) {
322 data_mq_ = nullptr;
323 return false;
324 }
325 data_mq_ = std::move(temp_mq);
326 return true;
327}
328
329bool BluetoothAudioSession::UpdateAudioConfig(
330 const AudioConfiguration& audio_config) {
331 bool is_software_session =
332 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
333 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
334 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800335 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
336 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800337 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
338 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800339 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800340 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
341 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800342 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800343 (session_type_ ==
344 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
345 session_type_ ==
346 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800347 bool is_offload_le_audio_broadcast_session =
348 (session_type_ ==
349 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800350 auto audio_config_tag = audio_config.getTag();
351 bool is_software_audio_config =
352 (is_software_session &&
353 audio_config_tag == AudioConfiguration::pcmConfig);
354 bool is_a2dp_offload_audio_config =
355 (is_offload_a2dp_session &&
356 audio_config_tag == AudioConfiguration::a2dpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800357 bool is_le_audio_offload_unicast_audio_config =
358 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800359 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800360 bool is_le_audio_offload_broadcast_audio_config =
361 (is_offload_le_audio_broadcast_session &&
362 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800363 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800364 !is_le_audio_offload_unicast_audio_config &&
365 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800366 return false;
367 }
368 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
369 return true;
370}
371
372void BluetoothAudioSession::ReportSessionStatus() {
373 // This is locked already by OnSessionStarted / OnSessionEnded
374 if (observers_.empty()) {
375 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
376 << " has NO port state observer";
377 return;
378 }
379 for (auto& observer : observers_) {
380 uint16_t cookie = observer.first;
381 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
382 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
383 << " notify to bluetooth_audio=0x"
384 << ::android::base::StringPrintf("%04x", cookie);
385 callback->session_changed_cb_(cookie);
386 }
387}
388
389/***
390 *
391 * PCM methods
392 *
393 ***/
394
395size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
396 size_t bytes) {
397 if (buffer == nullptr || bytes <= 0) {
398 return 0;
399 }
400 size_t total_written = 0;
401 int timeout_ms = kFmqSendTimeoutMs;
402 do {
403 std::unique_lock<std::recursive_mutex> lock(mutex_);
404 if (!IsSessionReady()) {
405 break;
406 }
407 size_t num_bytes_to_write = data_mq_->availableToWrite();
408 if (num_bytes_to_write) {
409 if (num_bytes_to_write > (bytes - total_written)) {
410 num_bytes_to_write = bytes - total_written;
411 }
412
413 if (!data_mq_->write(
414 static_cast<const MQDataType*>(buffer) + total_written,
415 num_bytes_to_write)) {
416 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
417 << " failed";
418 return total_written;
419 }
420 total_written += num_bytes_to_write;
421 } else if (timeout_ms >= kWritePollMs) {
422 lock.unlock();
423 usleep(kWritePollMs * 1000);
424 timeout_ms -= kWritePollMs;
425 } else {
426 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
427 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
428 return total_written;
429 }
430 } while (total_written < bytes);
431 return total_written;
432}
433
434size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
435 if (buffer == nullptr || bytes <= 0) {
436 return 0;
437 }
438 size_t total_read = 0;
439 int timeout_ms = kFmqReceiveTimeoutMs;
440 do {
441 std::unique_lock<std::recursive_mutex> lock(mutex_);
442 if (!IsSessionReady()) {
443 break;
444 }
445 size_t num_bytes_to_read = data_mq_->availableToRead();
446 if (num_bytes_to_read) {
447 if (num_bytes_to_read > (bytes - total_read)) {
448 num_bytes_to_read = bytes - total_read;
449 }
450 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
451 num_bytes_to_read)) {
452 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
453 << " failed";
454 return total_read;
455 }
456 total_read += num_bytes_to_read;
457 } else if (timeout_ms >= kReadPollMs) {
458 lock.unlock();
459 usleep(kReadPollMs * 1000);
460 timeout_ms -= kReadPollMs;
461 continue;
462 } else {
463 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
464 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
465 return total_read;
466 }
467 } while (total_read < bytes);
468 return total_read;
469}
470
471/***
472 *
473 * Other methods
474 *
475 ***/
476
477void BluetoothAudioSession::ReportControlStatus(bool start_resp,
478 BluetoothAudioStatus status) {
479 std::lock_guard<std::recursive_mutex> guard(mutex_);
480 if (observers_.empty()) {
481 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
482 << " has NO port state observer";
483 return;
484 }
Alice Kuo851ef342022-08-25 02:45:02 +0800485 if (start_resp && status == BluetoothAudioStatus::SUCCESS) {
486 is_streaming_ = true;
487 } else if (!start_resp && (status == BluetoothAudioStatus::SUCCESS ||
488 status == BluetoothAudioStatus::RECONFIGURATION)) {
489 is_streaming_ = false;
490 }
Josh Wu20bac522021-12-29 23:52:39 -0800491 for (auto& observer : observers_) {
492 uint16_t cookie = observer.first;
493 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
494 LOG(INFO) << __func__ << " - status=" << toString(status)
495 << " for SessionType=" << toString(session_type_)
496 << ", bluetooth_audio=0x"
497 << ::android::base::StringPrintf("%04x", cookie)
498 << (start_resp ? " started" : " suspended");
499 callback->control_result_cb_(cookie, start_resp, status);
500 }
501}
502
Chen Chen81f38e52022-02-09 13:27:35 -0800503void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
504 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800505 low_latency_allowed_ = allowed;
Chen Chen81f38e52022-02-09 13:27:35 -0800506 if (observers_.empty()) {
507 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
508 << " has NO port state observer";
509 return;
510 }
511 for (auto& observer : observers_) {
512 uint16_t cookie = observer.first;
513 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800514 LOG(INFO) << __func__
515 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700516 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
517 callback->low_latency_mode_allowed_cb_(cookie, allowed);
518 }
Chen Chen81f38e52022-02-09 13:27:35 -0800519 }
520}
521
Josh Wu20bac522021-12-29 23:52:39 -0800522bool BluetoothAudioSession::GetPresentationPosition(
523 PresentationPosition& presentation_position) {
524 std::lock_guard<std::recursive_mutex> guard(mutex_);
525 if (!IsSessionReady()) {
526 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
527 << " has NO session";
528 return false;
529 }
530 bool retval = false;
531
532 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
533 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
534 << toString(session_type_) << " failed";
535 return false;
536 }
537 return retval;
538}
539
540void BluetoothAudioSession::UpdateSourceMetadata(
541 const struct source_metadata& source_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800542 ssize_t track_count = source_metadata.track_count;
543 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
544 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800545 SourceMetadata hal_source_metadata;
546 hal_source_metadata.tracks.resize(track_count);
547 for (int i = 0; i < track_count; i++) {
548 hal_source_metadata.tracks[i].usage =
549 static_cast<media::audio::common::AudioUsage>(
550 source_metadata.tracks[i].usage);
551 hal_source_metadata.tracks[i].contentType =
552 static_cast<media::audio::common::AudioContentType>(
553 source_metadata.tracks[i].content_type);
554 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
555 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
556 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
557 << ", content="
558 << toString(hal_source_metadata.tracks[i].contentType)
559 << ", gain=" << hal_source_metadata.tracks[i].gain;
560 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700561 UpdateSourceMetadata(hal_source_metadata);
Josh Wu20bac522021-12-29 23:52:39 -0800562}
563
564void BluetoothAudioSession::UpdateSinkMetadata(
565 const struct sink_metadata& sink_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800566 ssize_t track_count = sink_metadata.track_count;
567 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
568 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800569 SinkMetadata hal_sink_metadata;
570 hal_sink_metadata.tracks.resize(track_count);
571 for (int i = 0; i < track_count; i++) {
572 hal_sink_metadata.tracks[i].source =
573 static_cast<media::audio::common::AudioSource>(
574 sink_metadata.tracks[i].source);
575 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
576 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
577 << ", source=" << sink_metadata.tracks[i].source
578 << ", dest_device=" << sink_metadata.tracks[i].dest_device
579 << ", gain=" << sink_metadata.tracks[i].gain
580 << ", dest_device_address="
581 << sink_metadata.tracks[i].dest_device_address;
582 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700583 UpdateSinkMetadata(hal_sink_metadata);
584}
585
586bool BluetoothAudioSession::UpdateSourceMetadata(
587 const SourceMetadata& hal_source_metadata) {
588 std::lock_guard<std::recursive_mutex> guard(mutex_);
589 if (!IsSessionReady()) {
590 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
591 << " has NO session";
592 return false;
593 }
594
595 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
596 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
597 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
598 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
599 return false;
600 }
601
602 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
603 if (!hal_retval.isOk()) {
604 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
605 << toString(session_type_) << " failed";
606 return false;
607 }
608 return true;
609}
610
611bool BluetoothAudioSession::UpdateSinkMetadata(
612 const SinkMetadata& hal_sink_metadata) {
613 std::lock_guard<std::recursive_mutex> guard(mutex_);
614 if (!IsSessionReady()) {
615 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
616 << " has NO session";
617 return false;
618 }
619
620 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
621 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
622 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
623 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
624 return false;
625 }
Josh Wu20bac522021-12-29 23:52:39 -0800626
627 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
628 if (!hal_retval.isOk()) {
629 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
630 << toString(session_type_) << " failed";
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700631 return false;
Josh Wu20bac522021-12-29 23:52:39 -0800632 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700633 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800634}
635
Cheney Ni6ecbc762022-03-03 00:12:48 +0800636std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
637 std::lock_guard<std::recursive_mutex> guard(mutex_);
638 if (!IsSessionReady()) {
639 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
640 << " has NO session";
641 return std::vector<LatencyMode>();
642 }
643 if (low_latency_allowed_) return latency_modes_;
644 std::vector<LatencyMode> modes;
645 for (LatencyMode mode : latency_modes_) {
646 if (mode == LatencyMode::LOW_LATENCY)
647 // ignore those low latency mode if Bluetooth stack doesn't allow
648 continue;
649 modes.push_back(mode);
650 }
651 return modes;
652}
653
654void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800655 std::lock_guard<std::recursive_mutex> guard(mutex_);
656 if (!IsSessionReady()) {
657 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
658 << " has NO session";
659 return;
660 }
661
662 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
663 if (!hal_retval.isOk()) {
664 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
665 << toString(session_type_) << " failed";
666 }
667}
668
Josh Wu20bac522021-12-29 23:52:39 -0800669bool BluetoothAudioSession::IsAidlAvailable() {
670 if (is_aidl_checked) return is_aidl_available;
671 is_aidl_available =
672 (AServiceManager_checkService(
673 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
674 is_aidl_checked = true;
675 return is_aidl_available;
676}
677
678/***
679 *
680 * BluetoothAudioSessionInstance
681 *
682 ***/
683std::mutex BluetoothAudioSessionInstance::mutex_;
684std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
685 BluetoothAudioSessionInstance::sessions_map_;
686
687std::shared_ptr<BluetoothAudioSession>
688BluetoothAudioSessionInstance::GetSessionInstance(
689 const SessionType& session_type) {
690 std::lock_guard<std::mutex> guard(mutex_);
691
692 if (!sessions_map_.empty()) {
693 auto entry = sessions_map_.find(session_type);
694 if (entry != sessions_map_.end()) {
695 return entry->second;
696 }
697 }
698 std::shared_ptr<BluetoothAudioSession> session_ptr =
699 std::make_shared<BluetoothAudioSession>(session_type);
700 sessions_map_[session_type] = session_ptr;
701 return session_ptr;
702}
703
704} // namespace audio
705} // namespace bluetooth
706} // namespace hardware
707} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800708} // namespace aidl