xref: /aosp_15_r20/hardware/interfaces/bluetooth/audio/utils/session/BluetoothAudioSession.h (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 #pragma once
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include <mutex>
20*4d7e907cSAndroid Build Coastguard Worker #include <unordered_map>
21*4d7e907cSAndroid Build Coastguard Worker 
22*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <fmq/MessageQueue.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <hardware/audio.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <hidl/MQDescriptor.h>
26*4d7e907cSAndroid Build Coastguard Worker 
27*4d7e907cSAndroid Build Coastguard Worker namespace android {
28*4d7e907cSAndroid Build Coastguard Worker namespace bluetooth {
29*4d7e907cSAndroid Build Coastguard Worker namespace audio {
30*4d7e907cSAndroid Build Coastguard Worker 
31*4d7e907cSAndroid Build Coastguard Worker using ::android::sp;
32*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::kSynchronizedReadWrite;
33*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::MessageQueue;
34*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
35*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
36*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
37*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
38*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
39*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
40*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
41*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::bluetooth::audio::V2_0::SessionType;
42*4d7e907cSAndroid Build Coastguard Worker 
43*4d7e907cSAndroid Build Coastguard Worker using BluetoothAudioStatus =
44*4d7e907cSAndroid Build Coastguard Worker     ::android::hardware::bluetooth::audio::V2_0::Status;
45*4d7e907cSAndroid Build Coastguard Worker 
46*4d7e907cSAndroid Build Coastguard Worker using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
47*4d7e907cSAndroid Build Coastguard Worker 
48*4d7e907cSAndroid Build Coastguard Worker static constexpr uint16_t kObserversCookieSize = 0x0010;  // 0x0000 ~ 0x000f
49*4d7e907cSAndroid Build Coastguard Worker constexpr uint16_t kObserversCookieUndefined =
50*4d7e907cSAndroid Build Coastguard Worker     (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
ObserversCookieGetSessionType(uint16_t cookie)51*4d7e907cSAndroid Build Coastguard Worker inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
52*4d7e907cSAndroid Build Coastguard Worker   return static_cast<SessionType>(cookie >> 8 & 0x00ff);
53*4d7e907cSAndroid Build Coastguard Worker }
ObserversCookieGetInitValue(SessionType session_type)54*4d7e907cSAndroid Build Coastguard Worker inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
55*4d7e907cSAndroid Build Coastguard Worker   return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
56*4d7e907cSAndroid Build Coastguard Worker }
ObserversCookieGetUpperBound(SessionType session_type)57*4d7e907cSAndroid Build Coastguard Worker inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
58*4d7e907cSAndroid Build Coastguard Worker   return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
59*4d7e907cSAndroid Build Coastguard Worker          kObserversCookieSize;
60*4d7e907cSAndroid Build Coastguard Worker }
61*4d7e907cSAndroid Build Coastguard Worker 
62*4d7e907cSAndroid Build Coastguard Worker // This presents the callbacks of started / suspended and session changed,
63*4d7e907cSAndroid Build Coastguard Worker // and the bluetooth_audio module uses to receive the status notification
64*4d7e907cSAndroid Build Coastguard Worker struct PortStatusCallbacks {
65*4d7e907cSAndroid Build Coastguard Worker   // control_result_cb_ - when the Bluetooth stack reports results of
66*4d7e907cSAndroid Build Coastguard Worker   // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
67*4d7e907cSAndroid Build Coastguard Worker   // this callback to report to the bluetooth_audio module.
68*4d7e907cSAndroid Build Coastguard Worker   // @param: cookie - indicates which bluetooth_audio output should handle
69*4d7e907cSAndroid Build Coastguard Worker   // @param: start_resp - this report is for startStream or not
70*4d7e907cSAndroid Build Coastguard Worker   // @param: status - the result of startStream
71*4d7e907cSAndroid Build Coastguard Worker   std::function<void(uint16_t cookie, bool start_resp,
72*4d7e907cSAndroid Build Coastguard Worker                      const BluetoothAudioStatus& status)>
73*4d7e907cSAndroid Build Coastguard Worker       control_result_cb_;
74*4d7e907cSAndroid Build Coastguard Worker   // session_changed_cb_ - when the Bluetooth stack start / end session, the
75*4d7e907cSAndroid Build Coastguard Worker   // BluetoothAudioProvider will invoke this callback to notify to the
76*4d7e907cSAndroid Build Coastguard Worker   // bluetooth_audio module.
77*4d7e907cSAndroid Build Coastguard Worker   // @param: cookie - indicates which bluetooth_audio output should handle
78*4d7e907cSAndroid Build Coastguard Worker   std::function<void(uint16_t cookie)> session_changed_cb_;
79*4d7e907cSAndroid Build Coastguard Worker };
80*4d7e907cSAndroid Build Coastguard Worker 
81*4d7e907cSAndroid Build Coastguard Worker class BluetoothAudioSession {
82*4d7e907cSAndroid Build Coastguard Worker   friend class BluetoothAudioSession_2_1;
83*4d7e907cSAndroid Build Coastguard Worker   friend class BluetoothAudioSession_2_2;
84*4d7e907cSAndroid Build Coastguard Worker 
85*4d7e907cSAndroid Build Coastguard Worker  private:
86*4d7e907cSAndroid Build Coastguard Worker   // using recursive_mutex to allow hwbinder to re-enter agian.
87*4d7e907cSAndroid Build Coastguard Worker   std::recursive_mutex mutex_;
88*4d7e907cSAndroid Build Coastguard Worker   SessionType session_type_;
89*4d7e907cSAndroid Build Coastguard Worker 
90*4d7e907cSAndroid Build Coastguard Worker   // audio control path to use for both software and offloading
91*4d7e907cSAndroid Build Coastguard Worker   sp<IBluetoothAudioPort> stack_iface_;
92*4d7e907cSAndroid Build Coastguard Worker   // audio data path (FMQ) for software encoding
93*4d7e907cSAndroid Build Coastguard Worker   std::unique_ptr<DataMQ> mDataMQ;
94*4d7e907cSAndroid Build Coastguard Worker   // audio data configuration for both software and offloading
95*4d7e907cSAndroid Build Coastguard Worker   AudioConfiguration audio_config_;
96*4d7e907cSAndroid Build Coastguard Worker 
97*4d7e907cSAndroid Build Coastguard Worker   static AudioConfiguration invalidSoftwareAudioConfiguration;
98*4d7e907cSAndroid Build Coastguard Worker   static AudioConfiguration invalidOffloadAudioConfiguration;
99*4d7e907cSAndroid Build Coastguard Worker 
100*4d7e907cSAndroid Build Coastguard Worker   // saving those registered bluetooth_audio's callbacks
101*4d7e907cSAndroid Build Coastguard Worker   std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
102*4d7e907cSAndroid Build Coastguard Worker       observers_;
103*4d7e907cSAndroid Build Coastguard Worker 
104*4d7e907cSAndroid Build Coastguard Worker   bool UpdateDataPath(const DataMQ::Descriptor* dataMQ);
105*4d7e907cSAndroid Build Coastguard Worker   bool UpdateAudioConfig(const AudioConfiguration& audio_config);
106*4d7e907cSAndroid Build Coastguard Worker   // invoking the registered session_changed_cb_
107*4d7e907cSAndroid Build Coastguard Worker   void ReportSessionStatus();
108*4d7e907cSAndroid Build Coastguard Worker 
109*4d7e907cSAndroid Build Coastguard Worker  public:
110*4d7e907cSAndroid Build Coastguard Worker   BluetoothAudioSession(const SessionType& session_type);
111*4d7e907cSAndroid Build Coastguard Worker 
112*4d7e907cSAndroid Build Coastguard Worker   // The function helps to check if this session is ready or not
113*4d7e907cSAndroid Build Coastguard Worker   // @return: true if the Bluetooth stack has started the specified session
114*4d7e907cSAndroid Build Coastguard Worker   bool IsSessionReady();
115*4d7e907cSAndroid Build Coastguard Worker 
116*4d7e907cSAndroid Build Coastguard Worker   // The report function is used to report that the Bluetooth stack has started
117*4d7e907cSAndroid Build Coastguard Worker   // this session without any failure, and will invoke session_changed_cb_ to
118*4d7e907cSAndroid Build Coastguard Worker   // notify those registered bluetooth_audio outputs
119*4d7e907cSAndroid Build Coastguard Worker   void OnSessionStarted(const sp<IBluetoothAudioPort> stack_iface,
120*4d7e907cSAndroid Build Coastguard Worker                         const DataMQ::Descriptor* dataMQ,
121*4d7e907cSAndroid Build Coastguard Worker                         const AudioConfiguration& audio_config);
122*4d7e907cSAndroid Build Coastguard Worker 
123*4d7e907cSAndroid Build Coastguard Worker   // The report function is used to report that the Bluetooth stack has ended
124*4d7e907cSAndroid Build Coastguard Worker   // the session, and will invoke session_changed_cb_ to notify registered
125*4d7e907cSAndroid Build Coastguard Worker   // bluetooth_audio outputs
126*4d7e907cSAndroid Build Coastguard Worker   void OnSessionEnded();
127*4d7e907cSAndroid Build Coastguard Worker 
128*4d7e907cSAndroid Build Coastguard Worker   // The report function is used to report that the Bluetooth stack has notified
129*4d7e907cSAndroid Build Coastguard Worker   // the result of startStream or suspendStream, and will invoke
130*4d7e907cSAndroid Build Coastguard Worker   // control_result_cb_ to notify registered bluetooth_audio outputs
131*4d7e907cSAndroid Build Coastguard Worker   void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
132*4d7e907cSAndroid Build Coastguard Worker 
133*4d7e907cSAndroid Build Coastguard Worker   // The control function helps the bluetooth_audio module to register
134*4d7e907cSAndroid Build Coastguard Worker   // PortStatusCallbacks
135*4d7e907cSAndroid Build Coastguard Worker   // @return: cookie - the assigned number to this bluetooth_audio output
136*4d7e907cSAndroid Build Coastguard Worker   uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
137*4d7e907cSAndroid Build Coastguard Worker 
138*4d7e907cSAndroid Build Coastguard Worker   // The control function helps the bluetooth_audio module to unregister
139*4d7e907cSAndroid Build Coastguard Worker   // PortStatusCallbacks
140*4d7e907cSAndroid Build Coastguard Worker   // @param: cookie - indicates which bluetooth_audio output is
141*4d7e907cSAndroid Build Coastguard Worker   void UnregisterStatusCback(uint16_t cookie);
142*4d7e907cSAndroid Build Coastguard Worker 
143*4d7e907cSAndroid Build Coastguard Worker   // The control function is for the bluetooth_audio module to get the current
144*4d7e907cSAndroid Build Coastguard Worker   // AudioConfiguration
145*4d7e907cSAndroid Build Coastguard Worker   const AudioConfiguration& GetAudioConfig();
146*4d7e907cSAndroid Build Coastguard Worker 
147*4d7e907cSAndroid Build Coastguard Worker   // Those control functions are for the bluetooth_audio module to start,
148*4d7e907cSAndroid Build Coastguard Worker   // suspend, stop stream, to check position, and to update metadata.
149*4d7e907cSAndroid Build Coastguard Worker   bool StartStream();
150*4d7e907cSAndroid Build Coastguard Worker   bool SuspendStream();
151*4d7e907cSAndroid Build Coastguard Worker   void StopStream();
152*4d7e907cSAndroid Build Coastguard Worker   bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
153*4d7e907cSAndroid Build Coastguard Worker                                uint64_t* total_bytes_readed,
154*4d7e907cSAndroid Build Coastguard Worker                                timespec* data_position);
155*4d7e907cSAndroid Build Coastguard Worker   void UpdateTracksMetadata(const struct source_metadata* source_metadata);
156*4d7e907cSAndroid Build Coastguard Worker 
157*4d7e907cSAndroid Build Coastguard Worker   // The control function writes stream to FMQ
158*4d7e907cSAndroid Build Coastguard Worker   size_t OutWritePcmData(const void* buffer, size_t bytes);
159*4d7e907cSAndroid Build Coastguard Worker   // The control function read stream from FMQ
160*4d7e907cSAndroid Build Coastguard Worker   size_t InReadPcmData(void* buffer, size_t bytes);
161*4d7e907cSAndroid Build Coastguard Worker 
162*4d7e907cSAndroid Build Coastguard Worker   static constexpr PcmParameters kInvalidPcmParameters = {
163*4d7e907cSAndroid Build Coastguard Worker       .sampleRate = SampleRate::RATE_UNKNOWN,
164*4d7e907cSAndroid Build Coastguard Worker       .channelMode = ChannelMode::UNKNOWN,
165*4d7e907cSAndroid Build Coastguard Worker       .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
166*4d7e907cSAndroid Build Coastguard Worker   };
167*4d7e907cSAndroid Build Coastguard Worker   // can't be constexpr because of non-literal type
168*4d7e907cSAndroid Build Coastguard Worker   static const CodecConfiguration kInvalidCodecConfiguration;
169*4d7e907cSAndroid Build Coastguard Worker 
170*4d7e907cSAndroid Build Coastguard Worker   static constexpr AudioConfiguration& kInvalidSoftwareAudioConfiguration =
171*4d7e907cSAndroid Build Coastguard Worker       invalidSoftwareAudioConfiguration;
172*4d7e907cSAndroid Build Coastguard Worker   static constexpr AudioConfiguration& kInvalidOffloadAudioConfiguration =
173*4d7e907cSAndroid Build Coastguard Worker       invalidOffloadAudioConfiguration;
174*4d7e907cSAndroid Build Coastguard Worker };
175*4d7e907cSAndroid Build Coastguard Worker 
176*4d7e907cSAndroid Build Coastguard Worker class BluetoothAudioSessionInstance {
177*4d7e907cSAndroid Build Coastguard Worker  public:
178*4d7e907cSAndroid Build Coastguard Worker   // The API is to fetch the specified session of A2DP / Hearing Aid
179*4d7e907cSAndroid Build Coastguard Worker   static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
180*4d7e907cSAndroid Build Coastguard Worker       const SessionType& session_type);
181*4d7e907cSAndroid Build Coastguard Worker 
182*4d7e907cSAndroid Build Coastguard Worker  private:
183*4d7e907cSAndroid Build Coastguard Worker   static std::unique_ptr<BluetoothAudioSessionInstance> instance_ptr;
184*4d7e907cSAndroid Build Coastguard Worker   std::mutex mutex_;
185*4d7e907cSAndroid Build Coastguard Worker   std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
186*4d7e907cSAndroid Build Coastguard Worker       sessions_map_;
187*4d7e907cSAndroid Build Coastguard Worker };
188*4d7e907cSAndroid Build Coastguard Worker 
189*4d7e907cSAndroid Build Coastguard Worker }  // namespace audio
190*4d7e907cSAndroid Build Coastguard Worker }  // namespace bluetooth
191*4d7e907cSAndroid Build Coastguard Worker }  // namespace android
192