xref: /aosp_15_r20/hardware/interfaces/bluetooth/audio/utils/session/BluetoothAudioSession.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright 2018 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "BTAudioProviderSession"
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include "BluetoothAudioSession.h"
20*4d7e907cSAndroid Build Coastguard Worker 
21*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
23*4d7e907cSAndroid Build Coastguard Worker 
24*4d7e907cSAndroid Build Coastguard Worker #include "../aidl_session/HidlToAidlMiddleware_2_0.h"
25*4d7e907cSAndroid Build Coastguard Worker 
26*4d7e907cSAndroid Build Coastguard Worker namespace android {
27*4d7e907cSAndroid Build Coastguard Worker namespace bluetooth {
28*4d7e907cSAndroid Build Coastguard Worker namespace audio {
29*4d7e907cSAndroid Build Coastguard Worker 
30*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
31*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::audio::common::V5_0::AudioContentType;
32*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::audio::common::V5_0::AudioUsage;
33*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
34*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::audio::common::V5_0::SourceMetadata;
35*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::CodecType;
36*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::TimeSpec;
37*4d7e907cSAndroid Build Coastguard Worker 
38*4d7e907cSAndroid Build Coastguard Worker const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {
39*4d7e907cSAndroid Build Coastguard Worker     .codecType = CodecType::UNKNOWN,
40*4d7e907cSAndroid Build Coastguard Worker     .encodedAudioBitrate = 0x00000000,
41*4d7e907cSAndroid Build Coastguard Worker     .peerMtu = 0xffff,
42*4d7e907cSAndroid Build Coastguard Worker     .isScmstEnabled = false,
43*4d7e907cSAndroid Build Coastguard Worker     .config = {}};
44*4d7e907cSAndroid Build Coastguard Worker AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration =
45*4d7e907cSAndroid Build Coastguard Worker     {};
46*4d7e907cSAndroid Build Coastguard Worker AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {};
47*4d7e907cSAndroid Build Coastguard Worker 
48*4d7e907cSAndroid Build Coastguard Worker static constexpr int kFmqSendTimeoutMs = 1000;  // 1000 ms timeout for sending
49*4d7e907cSAndroid Build Coastguard Worker static constexpr int kFmqReceiveTimeoutMs =
50*4d7e907cSAndroid Build Coastguard Worker     1000;                                       // 1000 ms timeout for receiving
51*4d7e907cSAndroid Build Coastguard Worker static constexpr int kWritePollMs = 1;          // polled non-blocking interval
52*4d7e907cSAndroid Build Coastguard Worker static constexpr int kReadPollMs = 1;           // polled non-blocking interval
53*4d7e907cSAndroid Build Coastguard Worker 
timespec_convert_from_hal(const TimeSpec & TS)54*4d7e907cSAndroid Build Coastguard Worker static inline timespec timespec_convert_from_hal(const TimeSpec& TS) {
55*4d7e907cSAndroid Build Coastguard Worker   return {.tv_sec = static_cast<long>(TS.tvSec),
56*4d7e907cSAndroid Build Coastguard Worker           .tv_nsec = static_cast<long>(TS.tvNSec)};
57*4d7e907cSAndroid Build Coastguard Worker }
58*4d7e907cSAndroid Build Coastguard Worker 
BluetoothAudioSession(const SessionType & session_type)59*4d7e907cSAndroid Build Coastguard Worker BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
60*4d7e907cSAndroid Build Coastguard Worker     : session_type_(session_type), stack_iface_(nullptr), mDataMQ(nullptr) {
61*4d7e907cSAndroid Build Coastguard Worker   invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
62*4d7e907cSAndroid Build Coastguard Worker   invalidOffloadAudioConfiguration.codecConfig(kInvalidCodecConfiguration);
63*4d7e907cSAndroid Build Coastguard Worker }
64*4d7e907cSAndroid Build Coastguard Worker 
65*4d7e907cSAndroid Build Coastguard Worker // The report function is used to report that the Bluetooth stack has started
66*4d7e907cSAndroid Build Coastguard Worker // this session without any failure, and will invoke session_changed_cb_ to
67*4d7e907cSAndroid Build Coastguard Worker // notify those registered bluetooth_audio outputs
OnSessionStarted(const sp<IBluetoothAudioPort> stack_iface,const DataMQ::Descriptor * dataMQ,const AudioConfiguration & audio_config)68*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::OnSessionStarted(
69*4d7e907cSAndroid Build Coastguard Worker     const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
70*4d7e907cSAndroid Build Coastguard Worker     const AudioConfiguration& audio_config) {
71*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
72*4d7e907cSAndroid Build Coastguard Worker   if (stack_iface == nullptr) {
73*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
74*4d7e907cSAndroid Build Coastguard Worker                << ", IBluetoothAudioPort Invalid";
75*4d7e907cSAndroid Build Coastguard Worker   } else if (!UpdateAudioConfig(audio_config)) {
76*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
77*4d7e907cSAndroid Build Coastguard Worker                << ", AudioConfiguration=" << toString(audio_config)
78*4d7e907cSAndroid Build Coastguard Worker                << " Invalid";
79*4d7e907cSAndroid Build Coastguard Worker   } else if (!UpdateDataPath(dataMQ)) {
80*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
81*4d7e907cSAndroid Build Coastguard Worker                << " DataMQ Invalid";
82*4d7e907cSAndroid Build Coastguard Worker     audio_config_ =
83*4d7e907cSAndroid Build Coastguard Worker         (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
84*4d7e907cSAndroid Build Coastguard Worker              ? kInvalidOffloadAudioConfiguration
85*4d7e907cSAndroid Build Coastguard Worker              : kInvalidSoftwareAudioConfiguration);
86*4d7e907cSAndroid Build Coastguard Worker   } else {
87*4d7e907cSAndroid Build Coastguard Worker     stack_iface_ = stack_iface;
88*4d7e907cSAndroid Build Coastguard Worker     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
89*4d7e907cSAndroid Build Coastguard Worker               << ", AudioConfiguration=" << toString(audio_config);
90*4d7e907cSAndroid Build Coastguard Worker     ReportSessionStatus();
91*4d7e907cSAndroid Build Coastguard Worker   }
92*4d7e907cSAndroid Build Coastguard Worker }
93*4d7e907cSAndroid Build Coastguard Worker 
94*4d7e907cSAndroid Build Coastguard Worker // The report function is used to report that the Bluetooth stack has ended the
95*4d7e907cSAndroid Build Coastguard Worker // session, and will invoke session_changed_cb_ to notify registered
96*4d7e907cSAndroid Build Coastguard Worker // bluetooth_audio outputs
OnSessionEnded()97*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::OnSessionEnded() {
98*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
99*4d7e907cSAndroid Build Coastguard Worker   bool toggled = IsSessionReady();
100*4d7e907cSAndroid Build Coastguard Worker   LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
101*4d7e907cSAndroid Build Coastguard Worker   audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
102*4d7e907cSAndroid Build Coastguard Worker                        ? kInvalidOffloadAudioConfiguration
103*4d7e907cSAndroid Build Coastguard Worker                        : kInvalidSoftwareAudioConfiguration);
104*4d7e907cSAndroid Build Coastguard Worker   stack_iface_ = nullptr;
105*4d7e907cSAndroid Build Coastguard Worker   UpdateDataPath(nullptr);
106*4d7e907cSAndroid Build Coastguard Worker   if (toggled) {
107*4d7e907cSAndroid Build Coastguard Worker     ReportSessionStatus();
108*4d7e907cSAndroid Build Coastguard Worker   }
109*4d7e907cSAndroid Build Coastguard Worker }
110*4d7e907cSAndroid Build Coastguard Worker 
111*4d7e907cSAndroid Build Coastguard Worker // invoking the registered session_changed_cb_
ReportSessionStatus()112*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::ReportSessionStatus() {
113*4d7e907cSAndroid Build Coastguard Worker   // This is locked already by OnSessionStarted / OnSessionEnded
114*4d7e907cSAndroid Build Coastguard Worker   if (observers_.empty()) {
115*4d7e907cSAndroid Build Coastguard Worker     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
116*4d7e907cSAndroid Build Coastguard Worker               << " has NO port state observer";
117*4d7e907cSAndroid Build Coastguard Worker     return;
118*4d7e907cSAndroid Build Coastguard Worker   }
119*4d7e907cSAndroid Build Coastguard Worker   for (auto& observer : observers_) {
120*4d7e907cSAndroid Build Coastguard Worker     uint16_t cookie = observer.first;
121*4d7e907cSAndroid Build Coastguard Worker     std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
122*4d7e907cSAndroid Build Coastguard Worker     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
123*4d7e907cSAndroid Build Coastguard Worker               << " notify to bluetooth_audio=0x"
124*4d7e907cSAndroid Build Coastguard Worker               << android::base::StringPrintf("%04x", cookie);
125*4d7e907cSAndroid Build Coastguard Worker     cb->session_changed_cb_(cookie);
126*4d7e907cSAndroid Build Coastguard Worker   }
127*4d7e907cSAndroid Build Coastguard Worker }
128*4d7e907cSAndroid Build Coastguard Worker 
129*4d7e907cSAndroid Build Coastguard Worker // The report function is used to report that the Bluetooth stack has notified
130*4d7e907cSAndroid Build Coastguard Worker // the result of startStream or suspendStream, and will invoke
131*4d7e907cSAndroid Build Coastguard Worker // control_result_cb_ to notify registered bluetooth_audio outputs
ReportControlStatus(bool start_resp,const BluetoothAudioStatus & status)132*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::ReportControlStatus(
133*4d7e907cSAndroid Build Coastguard Worker     bool start_resp, const BluetoothAudioStatus& status) {
134*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
135*4d7e907cSAndroid Build Coastguard Worker   if (observers_.empty()) {
136*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
137*4d7e907cSAndroid Build Coastguard Worker                  << " has NO port state observer";
138*4d7e907cSAndroid Build Coastguard Worker     return;
139*4d7e907cSAndroid Build Coastguard Worker   }
140*4d7e907cSAndroid Build Coastguard Worker   for (auto& observer : observers_) {
141*4d7e907cSAndroid Build Coastguard Worker     uint16_t cookie = observer.first;
142*4d7e907cSAndroid Build Coastguard Worker     std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
143*4d7e907cSAndroid Build Coastguard Worker     LOG(INFO) << __func__ << " - status=" << toString(status)
144*4d7e907cSAndroid Build Coastguard Worker               << " for SessionType=" << toString(session_type_)
145*4d7e907cSAndroid Build Coastguard Worker               << ", bluetooth_audio=0x"
146*4d7e907cSAndroid Build Coastguard Worker               << android::base::StringPrintf("%04x", cookie)
147*4d7e907cSAndroid Build Coastguard Worker               << (start_resp ? " started" : " suspended");
148*4d7e907cSAndroid Build Coastguard Worker     cb->control_result_cb_(cookie, start_resp, status);
149*4d7e907cSAndroid Build Coastguard Worker   }
150*4d7e907cSAndroid Build Coastguard Worker }
151*4d7e907cSAndroid Build Coastguard Worker 
152*4d7e907cSAndroid Build Coastguard Worker // The function helps to check if this session is ready or not
153*4d7e907cSAndroid Build Coastguard Worker // @return: true if the Bluetooth stack has started the specified session
IsSessionReady()154*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::IsSessionReady() {
155*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
156*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::IsSessionReady(session_type_);
157*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
158*4d7e907cSAndroid Build Coastguard Worker   bool dataMQ_valid =
159*4d7e907cSAndroid Build Coastguard Worker       (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
160*4d7e907cSAndroid Build Coastguard Worker        (mDataMQ != nullptr && mDataMQ->isValid()));
161*4d7e907cSAndroid Build Coastguard Worker   return stack_iface_ != nullptr && dataMQ_valid;
162*4d7e907cSAndroid Build Coastguard Worker }
163*4d7e907cSAndroid Build Coastguard Worker 
UpdateDataPath(const DataMQ::Descriptor * dataMQ)164*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::UpdateDataPath(const DataMQ::Descriptor* dataMQ) {
165*4d7e907cSAndroid Build Coastguard Worker   if (dataMQ == nullptr) {
166*4d7e907cSAndroid Build Coastguard Worker     // usecase of reset by nullptr
167*4d7e907cSAndroid Build Coastguard Worker     mDataMQ = nullptr;
168*4d7e907cSAndroid Build Coastguard Worker     return true;
169*4d7e907cSAndroid Build Coastguard Worker   }
170*4d7e907cSAndroid Build Coastguard Worker   std::unique_ptr<DataMQ> tempDataMQ;
171*4d7e907cSAndroid Build Coastguard Worker   tempDataMQ.reset(new DataMQ(*dataMQ));
172*4d7e907cSAndroid Build Coastguard Worker   if (!tempDataMQ || !tempDataMQ->isValid()) {
173*4d7e907cSAndroid Build Coastguard Worker     mDataMQ = nullptr;
174*4d7e907cSAndroid Build Coastguard Worker     return false;
175*4d7e907cSAndroid Build Coastguard Worker   }
176*4d7e907cSAndroid Build Coastguard Worker   mDataMQ = std::move(tempDataMQ);
177*4d7e907cSAndroid Build Coastguard Worker   return true;
178*4d7e907cSAndroid Build Coastguard Worker }
179*4d7e907cSAndroid Build Coastguard Worker 
UpdateAudioConfig(const AudioConfiguration & audio_config)180*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::UpdateAudioConfig(
181*4d7e907cSAndroid Build Coastguard Worker     const AudioConfiguration& audio_config) {
182*4d7e907cSAndroid Build Coastguard Worker   bool is_software_session =
183*4d7e907cSAndroid Build Coastguard Worker       (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
184*4d7e907cSAndroid Build Coastguard Worker        session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
185*4d7e907cSAndroid Build Coastguard Worker   bool is_offload_session =
186*4d7e907cSAndroid Build Coastguard Worker       (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
187*4d7e907cSAndroid Build Coastguard Worker   auto audio_config_discriminator = audio_config.getDiscriminator();
188*4d7e907cSAndroid Build Coastguard Worker   bool is_software_audio_config =
189*4d7e907cSAndroid Build Coastguard Worker       (is_software_session &&
190*4d7e907cSAndroid Build Coastguard Worker        audio_config_discriminator ==
191*4d7e907cSAndroid Build Coastguard Worker            AudioConfiguration::hidl_discriminator::pcmConfig);
192*4d7e907cSAndroid Build Coastguard Worker   bool is_offload_audio_config =
193*4d7e907cSAndroid Build Coastguard Worker       (is_offload_session &&
194*4d7e907cSAndroid Build Coastguard Worker        audio_config_discriminator ==
195*4d7e907cSAndroid Build Coastguard Worker            AudioConfiguration::hidl_discriminator::codecConfig);
196*4d7e907cSAndroid Build Coastguard Worker   if (!is_software_audio_config && !is_offload_audio_config) {
197*4d7e907cSAndroid Build Coastguard Worker     return false;
198*4d7e907cSAndroid Build Coastguard Worker   }
199*4d7e907cSAndroid Build Coastguard Worker   audio_config_ = audio_config;
200*4d7e907cSAndroid Build Coastguard Worker   return true;
201*4d7e907cSAndroid Build Coastguard Worker }
202*4d7e907cSAndroid Build Coastguard Worker 
203*4d7e907cSAndroid Build Coastguard Worker // The control function helps the bluetooth_audio module to register
204*4d7e907cSAndroid Build Coastguard Worker // PortStatusCallbacks
205*4d7e907cSAndroid Build Coastguard Worker // @return: cookie - the assigned number to this bluetooth_audio output
RegisterStatusCback(const PortStatusCallbacks & cbacks)206*4d7e907cSAndroid Build Coastguard Worker uint16_t BluetoothAudioSession::RegisterStatusCback(
207*4d7e907cSAndroid Build Coastguard Worker     const PortStatusCallbacks& cbacks) {
208*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
209*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::RegisterControlResultCback(session_type_,
210*4d7e907cSAndroid Build Coastguard Worker                                                                 cbacks);
211*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
212*4d7e907cSAndroid Build Coastguard Worker   uint16_t cookie = ObserversCookieGetInitValue(session_type_);
213*4d7e907cSAndroid Build Coastguard Worker   uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
214*4d7e907cSAndroid Build Coastguard Worker 
215*4d7e907cSAndroid Build Coastguard Worker   while (cookie < cookie_upper_bound) {
216*4d7e907cSAndroid Build Coastguard Worker     if (observers_.find(cookie) == observers_.end()) {
217*4d7e907cSAndroid Build Coastguard Worker       break;
218*4d7e907cSAndroid Build Coastguard Worker     }
219*4d7e907cSAndroid Build Coastguard Worker     ++cookie;
220*4d7e907cSAndroid Build Coastguard Worker   }
221*4d7e907cSAndroid Build Coastguard Worker   if (cookie >= cookie_upper_bound) {
222*4d7e907cSAndroid Build Coastguard Worker     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
223*4d7e907cSAndroid Build Coastguard Worker                << " has " << observers_.size()
224*4d7e907cSAndroid Build Coastguard Worker                << " observers already (No Resource)";
225*4d7e907cSAndroid Build Coastguard Worker     return kObserversCookieUndefined;
226*4d7e907cSAndroid Build Coastguard Worker   }
227*4d7e907cSAndroid Build Coastguard Worker   std::shared_ptr<struct PortStatusCallbacks> cb =
228*4d7e907cSAndroid Build Coastguard Worker       std::make_shared<struct PortStatusCallbacks>();
229*4d7e907cSAndroid Build Coastguard Worker   *cb = cbacks;
230*4d7e907cSAndroid Build Coastguard Worker   observers_[cookie] = cb;
231*4d7e907cSAndroid Build Coastguard Worker   return cookie;
232*4d7e907cSAndroid Build Coastguard Worker }
233*4d7e907cSAndroid Build Coastguard Worker 
234*4d7e907cSAndroid Build Coastguard Worker // The control function helps the bluetooth_audio module to unregister
235*4d7e907cSAndroid Build Coastguard Worker // PortStatusCallbacks
236*4d7e907cSAndroid Build Coastguard Worker // @param: cookie - indicates which bluetooth_audio output is
UnregisterStatusCback(uint16_t cookie)237*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
238*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
239*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::UnregisterControlResultCback(session_type_,
240*4d7e907cSAndroid Build Coastguard Worker                                                                   cookie);
241*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
242*4d7e907cSAndroid Build Coastguard Worker   if (observers_.erase(cookie) != 1) {
243*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
244*4d7e907cSAndroid Build Coastguard Worker                  << " no such provider=0x"
245*4d7e907cSAndroid Build Coastguard Worker                  << android::base::StringPrintf("%04x", cookie);
246*4d7e907cSAndroid Build Coastguard Worker   }
247*4d7e907cSAndroid Build Coastguard Worker }
248*4d7e907cSAndroid Build Coastguard Worker 
249*4d7e907cSAndroid Build Coastguard Worker // The control function is for the bluetooth_audio module to get the current
250*4d7e907cSAndroid Build Coastguard Worker // AudioConfiguration
GetAudioConfig()251*4d7e907cSAndroid Build Coastguard Worker const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
252*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
253*4d7e907cSAndroid Build Coastguard Worker     return (audio_config_ =
254*4d7e907cSAndroid Build Coastguard Worker                 HidlToAidlMiddleware_2_0::GetAudioConfig(session_type_));
255*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
256*4d7e907cSAndroid Build Coastguard Worker   if (IsSessionReady()) {
257*4d7e907cSAndroid Build Coastguard Worker     return audio_config_;
258*4d7e907cSAndroid Build Coastguard Worker   } else if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
259*4d7e907cSAndroid Build Coastguard Worker     return kInvalidOffloadAudioConfiguration;
260*4d7e907cSAndroid Build Coastguard Worker   } else {
261*4d7e907cSAndroid Build Coastguard Worker     return kInvalidSoftwareAudioConfiguration;
262*4d7e907cSAndroid Build Coastguard Worker   }
263*4d7e907cSAndroid Build Coastguard Worker }
264*4d7e907cSAndroid Build Coastguard Worker 
265*4d7e907cSAndroid Build Coastguard Worker // Those control functions are for the bluetooth_audio module to start, suspend,
266*4d7e907cSAndroid Build Coastguard Worker // stop stream, to check position, and to update metadata.
StartStream()267*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::StartStream() {
268*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
269*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::StartStream(session_type_);
270*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
271*4d7e907cSAndroid Build Coastguard Worker   if (!IsSessionReady()) {
272*4d7e907cSAndroid Build Coastguard Worker     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
273*4d7e907cSAndroid Build Coastguard Worker                << " has NO session";
274*4d7e907cSAndroid Build Coastguard Worker     return false;
275*4d7e907cSAndroid Build Coastguard Worker   }
276*4d7e907cSAndroid Build Coastguard Worker   auto hal_retval = stack_iface_->startStream();
277*4d7e907cSAndroid Build Coastguard Worker   if (!hal_retval.isOk()) {
278*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
279*4d7e907cSAndroid Build Coastguard Worker                  << toString(session_type_) << " failed";
280*4d7e907cSAndroid Build Coastguard Worker     return false;
281*4d7e907cSAndroid Build Coastguard Worker   }
282*4d7e907cSAndroid Build Coastguard Worker   return true;
283*4d7e907cSAndroid Build Coastguard Worker }
284*4d7e907cSAndroid Build Coastguard Worker 
SuspendStream()285*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::SuspendStream() {
286*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
287*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::SuspendStream(session_type_);
288*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
289*4d7e907cSAndroid Build Coastguard Worker   if (!IsSessionReady()) {
290*4d7e907cSAndroid Build Coastguard Worker     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
291*4d7e907cSAndroid Build Coastguard Worker                << " has NO session";
292*4d7e907cSAndroid Build Coastguard Worker     return false;
293*4d7e907cSAndroid Build Coastguard Worker   }
294*4d7e907cSAndroid Build Coastguard Worker   auto hal_retval = stack_iface_->suspendStream();
295*4d7e907cSAndroid Build Coastguard Worker   if (!hal_retval.isOk()) {
296*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
297*4d7e907cSAndroid Build Coastguard Worker                  << toString(session_type_) << " failed";
298*4d7e907cSAndroid Build Coastguard Worker     return false;
299*4d7e907cSAndroid Build Coastguard Worker   }
300*4d7e907cSAndroid Build Coastguard Worker   return true;
301*4d7e907cSAndroid Build Coastguard Worker }
302*4d7e907cSAndroid Build Coastguard Worker 
StopStream()303*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::StopStream() {
304*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
305*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::StopStream(session_type_);
306*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
307*4d7e907cSAndroid Build Coastguard Worker   if (!IsSessionReady()) {
308*4d7e907cSAndroid Build Coastguard Worker     return;
309*4d7e907cSAndroid Build Coastguard Worker   }
310*4d7e907cSAndroid Build Coastguard Worker   auto hal_retval = stack_iface_->stopStream();
311*4d7e907cSAndroid Build Coastguard Worker   if (!hal_retval.isOk()) {
312*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
313*4d7e907cSAndroid Build Coastguard Worker                  << toString(session_type_) << " failed";
314*4d7e907cSAndroid Build Coastguard Worker   }
315*4d7e907cSAndroid Build Coastguard Worker }
316*4d7e907cSAndroid Build Coastguard Worker 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_readed,timespec * data_position)317*4d7e907cSAndroid Build Coastguard Worker bool BluetoothAudioSession::GetPresentationPosition(
318*4d7e907cSAndroid Build Coastguard Worker     uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
319*4d7e907cSAndroid Build Coastguard Worker     timespec* data_position) {
320*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
321*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::GetPresentationPosition(
322*4d7e907cSAndroid Build Coastguard Worker         session_type_, remote_delay_report_ns, total_bytes_readed,
323*4d7e907cSAndroid Build Coastguard Worker         data_position);
324*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
325*4d7e907cSAndroid Build Coastguard Worker   if (!IsSessionReady()) {
326*4d7e907cSAndroid Build Coastguard Worker     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
327*4d7e907cSAndroid Build Coastguard Worker                << " has NO session";
328*4d7e907cSAndroid Build Coastguard Worker     return false;
329*4d7e907cSAndroid Build Coastguard Worker   }
330*4d7e907cSAndroid Build Coastguard Worker   bool retval = false;
331*4d7e907cSAndroid Build Coastguard Worker   auto hal_retval = stack_iface_->getPresentationPosition(
332*4d7e907cSAndroid Build Coastguard Worker       [&retval, &remote_delay_report_ns, &total_bytes_readed, &data_position](
333*4d7e907cSAndroid Build Coastguard Worker           BluetoothAudioStatus status,
334*4d7e907cSAndroid Build Coastguard Worker           const uint64_t& remoteDeviceAudioDelayNanos,
335*4d7e907cSAndroid Build Coastguard Worker           uint64_t transmittedOctets,
336*4d7e907cSAndroid Build Coastguard Worker           const TimeSpec& transmittedOctetsTimeStamp) {
337*4d7e907cSAndroid Build Coastguard Worker         if (status == BluetoothAudioStatus::SUCCESS) {
338*4d7e907cSAndroid Build Coastguard Worker           if (remote_delay_report_ns)
339*4d7e907cSAndroid Build Coastguard Worker             *remote_delay_report_ns = remoteDeviceAudioDelayNanos;
340*4d7e907cSAndroid Build Coastguard Worker           if (total_bytes_readed) *total_bytes_readed = transmittedOctets;
341*4d7e907cSAndroid Build Coastguard Worker           if (data_position)
342*4d7e907cSAndroid Build Coastguard Worker             *data_position =
343*4d7e907cSAndroid Build Coastguard Worker                 timespec_convert_from_hal(transmittedOctetsTimeStamp);
344*4d7e907cSAndroid Build Coastguard Worker           retval = true;
345*4d7e907cSAndroid Build Coastguard Worker         }
346*4d7e907cSAndroid Build Coastguard Worker       });
347*4d7e907cSAndroid Build Coastguard Worker   if (!hal_retval.isOk()) {
348*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
349*4d7e907cSAndroid Build Coastguard Worker                  << toString(session_type_) << " failed";
350*4d7e907cSAndroid Build Coastguard Worker     return false;
351*4d7e907cSAndroid Build Coastguard Worker   }
352*4d7e907cSAndroid Build Coastguard Worker   return retval;
353*4d7e907cSAndroid Build Coastguard Worker }
354*4d7e907cSAndroid Build Coastguard Worker 
UpdateTracksMetadata(const struct source_metadata * source_metadata)355*4d7e907cSAndroid Build Coastguard Worker void BluetoothAudioSession::UpdateTracksMetadata(
356*4d7e907cSAndroid Build Coastguard Worker     const struct source_metadata* source_metadata) {
357*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
358*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::UpdateTracksMetadata(session_type_,
359*4d7e907cSAndroid Build Coastguard Worker                                                           source_metadata);
360*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::recursive_mutex> guard(mutex_);
361*4d7e907cSAndroid Build Coastguard Worker   if (!IsSessionReady()) {
362*4d7e907cSAndroid Build Coastguard Worker     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
363*4d7e907cSAndroid Build Coastguard Worker                << " has NO session";
364*4d7e907cSAndroid Build Coastguard Worker     return;
365*4d7e907cSAndroid Build Coastguard Worker   }
366*4d7e907cSAndroid Build Coastguard Worker 
367*4d7e907cSAndroid Build Coastguard Worker   ssize_t track_count = source_metadata->track_count;
368*4d7e907cSAndroid Build Coastguard Worker   LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", "
369*4d7e907cSAndroid Build Coastguard Worker             << track_count << " track(s)";
370*4d7e907cSAndroid Build Coastguard Worker   if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
371*4d7e907cSAndroid Build Coastguard Worker       session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
372*4d7e907cSAndroid Build Coastguard Worker     return;
373*4d7e907cSAndroid Build Coastguard Worker   }
374*4d7e907cSAndroid Build Coastguard Worker 
375*4d7e907cSAndroid Build Coastguard Worker   struct playback_track_metadata* track = source_metadata->tracks;
376*4d7e907cSAndroid Build Coastguard Worker   SourceMetadata sourceMetadata;
377*4d7e907cSAndroid Build Coastguard Worker   PlaybackTrackMetadata* halMetadata;
378*4d7e907cSAndroid Build Coastguard Worker 
379*4d7e907cSAndroid Build Coastguard Worker   sourceMetadata.tracks.resize(track_count);
380*4d7e907cSAndroid Build Coastguard Worker   halMetadata = sourceMetadata.tracks.data();
381*4d7e907cSAndroid Build Coastguard Worker   while (track_count && track) {
382*4d7e907cSAndroid Build Coastguard Worker     halMetadata->usage = static_cast<AudioUsage>(track->usage);
383*4d7e907cSAndroid Build Coastguard Worker     halMetadata->contentType =
384*4d7e907cSAndroid Build Coastguard Worker         static_cast<AudioContentType>(track->content_type);
385*4d7e907cSAndroid Build Coastguard Worker     halMetadata->gain = track->gain;
386*4d7e907cSAndroid Build Coastguard Worker     LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
387*4d7e907cSAndroid Build Coastguard Worker                  << ", usage=" << toString(halMetadata->usage)
388*4d7e907cSAndroid Build Coastguard Worker                  << ", content=" << toString(halMetadata->contentType)
389*4d7e907cSAndroid Build Coastguard Worker                  << ", gain=" << halMetadata->gain;
390*4d7e907cSAndroid Build Coastguard Worker     --track_count;
391*4d7e907cSAndroid Build Coastguard Worker     ++track;
392*4d7e907cSAndroid Build Coastguard Worker     ++halMetadata;
393*4d7e907cSAndroid Build Coastguard Worker   }
394*4d7e907cSAndroid Build Coastguard Worker   auto hal_retval = stack_iface_->updateMetadata(sourceMetadata);
395*4d7e907cSAndroid Build Coastguard Worker   if (!hal_retval.isOk()) {
396*4d7e907cSAndroid Build Coastguard Worker     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
397*4d7e907cSAndroid Build Coastguard Worker                  << toString(session_type_) << " failed";
398*4d7e907cSAndroid Build Coastguard Worker   }
399*4d7e907cSAndroid Build Coastguard Worker }
400*4d7e907cSAndroid Build Coastguard Worker 
401*4d7e907cSAndroid Build Coastguard Worker // The control function writes stream to FMQ
OutWritePcmData(const void * buffer,size_t bytes)402*4d7e907cSAndroid Build Coastguard Worker size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
403*4d7e907cSAndroid Build Coastguard Worker                                               size_t bytes) {
404*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
405*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::OutWritePcmData(session_type_, buffer,
406*4d7e907cSAndroid Build Coastguard Worker                                                      bytes);
407*4d7e907cSAndroid Build Coastguard Worker   if (buffer == nullptr || !bytes) return 0;
408*4d7e907cSAndroid Build Coastguard Worker   size_t totalWritten = 0;
409*4d7e907cSAndroid Build Coastguard Worker   int ms_timeout = kFmqSendTimeoutMs;
410*4d7e907cSAndroid Build Coastguard Worker   do {
411*4d7e907cSAndroid Build Coastguard Worker     std::unique_lock<std::recursive_mutex> lock(mutex_);
412*4d7e907cSAndroid Build Coastguard Worker     if (!IsSessionReady()) break;
413*4d7e907cSAndroid Build Coastguard Worker     size_t availableToWrite = mDataMQ->availableToWrite();
414*4d7e907cSAndroid Build Coastguard Worker     if (availableToWrite) {
415*4d7e907cSAndroid Build Coastguard Worker       if (availableToWrite > (bytes - totalWritten)) {
416*4d7e907cSAndroid Build Coastguard Worker         availableToWrite = bytes - totalWritten;
417*4d7e907cSAndroid Build Coastguard Worker       }
418*4d7e907cSAndroid Build Coastguard Worker 
419*4d7e907cSAndroid Build Coastguard Worker       if (!mDataMQ->write(static_cast<const uint8_t*>(buffer) + totalWritten,
420*4d7e907cSAndroid Build Coastguard Worker                           availableToWrite)) {
421*4d7e907cSAndroid Build Coastguard Worker         ALOGE("FMQ datapath writting %zu/%zu failed", totalWritten, bytes);
422*4d7e907cSAndroid Build Coastguard Worker         return totalWritten;
423*4d7e907cSAndroid Build Coastguard Worker       }
424*4d7e907cSAndroid Build Coastguard Worker       totalWritten += availableToWrite;
425*4d7e907cSAndroid Build Coastguard Worker     } else if (ms_timeout >= kWritePollMs) {
426*4d7e907cSAndroid Build Coastguard Worker       lock.unlock();
427*4d7e907cSAndroid Build Coastguard Worker       usleep(kWritePollMs * 1000);
428*4d7e907cSAndroid Build Coastguard Worker       ms_timeout -= kWritePollMs;
429*4d7e907cSAndroid Build Coastguard Worker     } else {
430*4d7e907cSAndroid Build Coastguard Worker       ALOGD("data %zu/%zu overflow %d ms", totalWritten, bytes,
431*4d7e907cSAndroid Build Coastguard Worker             (kFmqSendTimeoutMs - ms_timeout));
432*4d7e907cSAndroid Build Coastguard Worker       return totalWritten;
433*4d7e907cSAndroid Build Coastguard Worker     }
434*4d7e907cSAndroid Build Coastguard Worker   } while (totalWritten < bytes);
435*4d7e907cSAndroid Build Coastguard Worker   return totalWritten;
436*4d7e907cSAndroid Build Coastguard Worker }
437*4d7e907cSAndroid Build Coastguard Worker 
438*4d7e907cSAndroid Build Coastguard Worker // The control function reads stream from FMQ
InReadPcmData(void * buffer,size_t bytes)439*4d7e907cSAndroid Build Coastguard Worker size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
440*4d7e907cSAndroid Build Coastguard Worker   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
441*4d7e907cSAndroid Build Coastguard Worker     return HidlToAidlMiddleware_2_0::InReadPcmData(session_type_, buffer,
442*4d7e907cSAndroid Build Coastguard Worker                                                    bytes);
443*4d7e907cSAndroid Build Coastguard Worker   if (buffer == nullptr || !bytes) return 0;
444*4d7e907cSAndroid Build Coastguard Worker   size_t totalRead = 0;
445*4d7e907cSAndroid Build Coastguard Worker   int ms_timeout = kFmqReceiveTimeoutMs;
446*4d7e907cSAndroid Build Coastguard Worker   do {
447*4d7e907cSAndroid Build Coastguard Worker     std::unique_lock<std::recursive_mutex> lock(mutex_);
448*4d7e907cSAndroid Build Coastguard Worker     if (!IsSessionReady()) break;
449*4d7e907cSAndroid Build Coastguard Worker     size_t availableToRead = mDataMQ->availableToRead();
450*4d7e907cSAndroid Build Coastguard Worker     if (availableToRead) {
451*4d7e907cSAndroid Build Coastguard Worker       if (availableToRead > (bytes - totalRead)) {
452*4d7e907cSAndroid Build Coastguard Worker         availableToRead = bytes - totalRead;
453*4d7e907cSAndroid Build Coastguard Worker       }
454*4d7e907cSAndroid Build Coastguard Worker       if (!mDataMQ->read(static_cast<uint8_t*>(buffer) + totalRead,
455*4d7e907cSAndroid Build Coastguard Worker                          availableToRead)) {
456*4d7e907cSAndroid Build Coastguard Worker         ALOGE("FMQ datapath reading %zu/%zu failed", totalRead, bytes);
457*4d7e907cSAndroid Build Coastguard Worker         return totalRead;
458*4d7e907cSAndroid Build Coastguard Worker       }
459*4d7e907cSAndroid Build Coastguard Worker       totalRead += availableToRead;
460*4d7e907cSAndroid Build Coastguard Worker     } else if (ms_timeout >= kReadPollMs) {
461*4d7e907cSAndroid Build Coastguard Worker       lock.unlock();
462*4d7e907cSAndroid Build Coastguard Worker       usleep(kReadPollMs * 1000);
463*4d7e907cSAndroid Build Coastguard Worker       ms_timeout -= kReadPollMs;
464*4d7e907cSAndroid Build Coastguard Worker       continue;
465*4d7e907cSAndroid Build Coastguard Worker     } else {
466*4d7e907cSAndroid Build Coastguard Worker       ALOGD("in data %zu/%zu overflow %d ms", totalRead, bytes,
467*4d7e907cSAndroid Build Coastguard Worker             (kFmqReceiveTimeoutMs - ms_timeout));
468*4d7e907cSAndroid Build Coastguard Worker       return totalRead;
469*4d7e907cSAndroid Build Coastguard Worker     }
470*4d7e907cSAndroid Build Coastguard Worker   } while (totalRead < bytes);
471*4d7e907cSAndroid Build Coastguard Worker   return totalRead;
472*4d7e907cSAndroid Build Coastguard Worker }
473*4d7e907cSAndroid Build Coastguard Worker 
474*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<BluetoothAudioSessionInstance>
475*4d7e907cSAndroid Build Coastguard Worker     BluetoothAudioSessionInstance::instance_ptr =
476*4d7e907cSAndroid Build Coastguard Worker         std::unique_ptr<BluetoothAudioSessionInstance>(
477*4d7e907cSAndroid Build Coastguard Worker             new BluetoothAudioSessionInstance());
478*4d7e907cSAndroid Build Coastguard Worker 
479*4d7e907cSAndroid Build Coastguard Worker // API to fetch the session of A2DP / Hearing Aid
480*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<BluetoothAudioSession>
GetSessionInstance(const SessionType & session_type)481*4d7e907cSAndroid Build Coastguard Worker BluetoothAudioSessionInstance::GetSessionInstance(
482*4d7e907cSAndroid Build Coastguard Worker     const SessionType& session_type) {
483*4d7e907cSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
484*4d7e907cSAndroid Build Coastguard Worker   if (!instance_ptr->sessions_map_.empty()) {
485*4d7e907cSAndroid Build Coastguard Worker     auto entry = instance_ptr->sessions_map_.find(session_type);
486*4d7e907cSAndroid Build Coastguard Worker     if (entry != instance_ptr->sessions_map_.end()) {
487*4d7e907cSAndroid Build Coastguard Worker       return entry->second;
488*4d7e907cSAndroid Build Coastguard Worker     }
489*4d7e907cSAndroid Build Coastguard Worker   }
490*4d7e907cSAndroid Build Coastguard Worker   std::shared_ptr<BluetoothAudioSession> session_ptr =
491*4d7e907cSAndroid Build Coastguard Worker       std::make_shared<BluetoothAudioSession>(session_type);
492*4d7e907cSAndroid Build Coastguard Worker   instance_ptr->sessions_map_[session_type] = session_ptr;
493*4d7e907cSAndroid Build Coastguard Worker   return session_ptr;
494*4d7e907cSAndroid Build Coastguard Worker }
495*4d7e907cSAndroid Build Coastguard Worker 
496*4d7e907cSAndroid Build Coastguard Worker }  // namespace audio
497*4d7e907cSAndroid Build Coastguard Worker }  // namespace bluetooth
498*4d7e907cSAndroid Build Coastguard Worker }  // namespace android
499