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