blob: 25c676a3acf1913bf7fc4270bf38f92a8b766174 [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#pragma once
18
19#include <aidl/android/hardware/audio/common/SinkMetadata.h>
20#include <aidl/android/hardware/audio/common/SourceMetadata.h>
21#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
22#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
Chen Chena4c4c612022-02-07 18:01:05 -080023#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
Josh Wu20bac522021-12-29 23:52:39 -080024#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
25#include <fmq/AidlMessageQueue.h>
Josh Wu20bac522021-12-29 23:52:39 -080026
27#include <mutex>
28#include <unordered_map>
Cheney Ni6ecbc762022-03-03 00:12:48 +080029#include <vector>
Josh Wu20bac522021-12-29 23:52:39 -080030
Mikhail Naganovd5f0d132023-07-26 17:26:02 -070031// To avoid inclusion of hardware/audio.h
32struct sink_metadata;
33struct source_metadata;
34
Josh Wu20bac522021-12-29 23:52:39 -080035namespace aidl {
36namespace android {
37namespace hardware {
38namespace bluetooth {
39namespace audio {
40
41using ::aidl::android::hardware::common::fmq::MQDescriptor;
42using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
43using ::android::AidlMessageQueue;
44
45using ::aidl::android::hardware::audio::common::SinkMetadata;
46using ::aidl::android::hardware::audio::common::SourceMetadata;
47
48using MQDataType = int8_t;
49using MQDataMode = SynchronizedReadWrite;
50using DataMQ = AidlMessageQueue<MQDataType, MQDataMode>;
51using DataMQDesc =
52 ::aidl::android::hardware::common::fmq::MQDescriptor<MQDataType,
53 MQDataMode>;
54
55static constexpr uint16_t kObserversCookieSize = 0x0010; // 0x0000 ~ 0x000f
56static constexpr uint16_t kObserversCookieUndefined =
57 (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
58inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
59 return static_cast<SessionType>(cookie >> 8 & 0x00ff);
60}
61inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
62 return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
63}
64inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
65 return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
66 kObserversCookieSize;
67}
68
69/***
70 * This presents the callbacks of started / suspended and session changed,
71 * and the bluetooth_audio module uses to receive the status notification
72 ***/
73struct PortStatusCallbacks {
74 /***
75 * control_result_cb_ - when the Bluetooth stack reports results of
76 * streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
77 * this callback to report to the bluetooth_audio module.
78 * @param: cookie - indicates which bluetooth_audio output should handle
79 * @param: start_resp - this report is for startStream or not
80 * @param: status - the result of startStream
81 ***/
82 std::function<void(uint16_t cookie, bool start_resp,
83 BluetoothAudioStatus status)>
84 control_result_cb_;
85 /***
86 * session_changed_cb_ - when the Bluetooth stack start / end session, the
87 * BluetoothAudioProvider will invoke this callback to notify to the
88 * bluetooth_audio module.
89 * @param: cookie - indicates which bluetooth_audio output should handle
90 ***/
91 std::function<void(uint16_t cookie)> session_changed_cb_;
92 /***
93 * audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
94 * configuration, the BluetoothAudioProvider will invoke this callback to
95 * notify to the bluetooth_audio module.
96 * @param: cookie - indicates which bluetooth_audio output should handle
97 ***/
98 std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
Chen Chen81f38e52022-02-09 13:27:35 -080099 /***
100 * low_latency_mode_allowed_cb_ - when the Bluetooth stack low latency mode
101 * allowed or disallowed, the BluetoothAudioProvider will invoke
102 * this callback to report to the bluetooth_audio module.
103 * @param: cookie - indicates which bluetooth_audio output should handle
104 * @param: allowed - indicates if low latency mode is allowed
105 ***/
106 std::function<void(uint16_t cookie, bool allowed)>
107 low_latency_mode_allowed_cb_;
Alice Kuo851ef342022-08-25 02:45:02 +0800108 /***
109 * soft_audio_configuration_changed_cb_ - when the Bluetooth stack change
110 * the streamMap during the streaming, the BluetoothAudioProvider will invoke
111 * this callback to report to the bluetooth_audio module.
112 * @param: cookie - indicates which bluetooth_audio output should handle
113 ***/
114 std::function<void(uint16_t cookie)> soft_audio_configuration_changed_cb_;
Josh Wu20bac522021-12-29 23:52:39 -0800115};
116
117class BluetoothAudioSession {
118 public:
119 BluetoothAudioSession(const SessionType& session_type);
120
121 /***
122 * The function helps to check if this session is ready or not
123 * @return: true if the Bluetooth stack has started the specified session
124 ***/
125 bool IsSessionReady();
126
127 /***
128 * The report function is used to report that the Bluetooth stack has started
129 * this session without any failure, and will invoke session_changed_cb_ to
130 * notify those registered bluetooth_audio outputs
131 ***/
132 void OnSessionStarted(const std::shared_ptr<IBluetoothAudioPort> stack_iface,
133 const DataMQDesc* mq_desc,
Cheney Ni6ecbc762022-03-03 00:12:48 +0800134 const AudioConfiguration& audio_config,
135 const std::vector<LatencyMode>& latency_modes);
Josh Wu20bac522021-12-29 23:52:39 -0800136
137 /***
138 * The report function is used to report that the Bluetooth stack has ended
139 * the session, and will invoke session_changed_cb_ to notify registered
140 * bluetooth_audio outputs
141 ***/
142 void OnSessionEnded();
143
144 /***
145 * The report function is used to report that the Bluetooth stack has notified
146 * the result of startStream or suspendStream, and will invoke
147 * control_result_cb_ to notify registered bluetooth_audio outputs
148 ***/
149 void ReportControlStatus(bool start_resp, BluetoothAudioStatus status);
150
151 /***
152 * The control function helps the bluetooth_audio module to register
153 * PortStatusCallbacks
154 * @return: cookie - the assigned number to this bluetooth_audio output
155 ***/
156 uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
157
158 /***
159 * The control function helps the bluetooth_audio module to unregister
160 * PortStatusCallbacks
161 * @param: cookie - indicates which bluetooth_audio output is
162 ***/
163 void UnregisterStatusCback(uint16_t cookie);
164
165 /***
166 * The control function is for the bluetooth_audio module to get the current
167 * AudioConfiguration
168 ***/
Josh Wu75462aa2022-01-21 21:51:21 -0800169 const AudioConfiguration GetAudioConfig();
Josh Wu20bac522021-12-29 23:52:39 -0800170
171 /***
Alice Kuo851ef342022-08-25 02:45:02 +0800172 * The control function is for the bluetooth_audio module to get the current
173 * LE audio connection map
174 ***/
175 const AudioConfiguration GetLeAudioConnectionMap();
176
177 /***
Josh Wu20bac522021-12-29 23:52:39 -0800178 * The report function is used to report that the Bluetooth stack has notified
179 * the audio configuration changed, and will invoke
180 * audio_configuration_changed_cb_ to notify registered bluetooth_audio
181 * outputs
182 ***/
183 void ReportAudioConfigChanged(const AudioConfiguration& audio_config);
184
185 /***
Chen Chen81f38e52022-02-09 13:27:35 -0800186 * The report function is used to report that the Bluetooth stack has notified
187 * the low latency mode allowed changed, and will invoke
188 * low_latency_mode_allowed_changed_cb to notify registered bluetooth_audio
189 * outputs
190 ***/
191 void ReportLowLatencyModeAllowedChanged(bool allowed);
192 /***
Josh Wu20bac522021-12-29 23:52:39 -0800193 * Those control functions are for the bluetooth_audio module to start,
194 * suspend, stop stream, to check position, and to update metadata.
195 ***/
Cheney Ni6ecbc762022-03-03 00:12:48 +0800196 bool StartStream(bool low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800197 bool SuspendStream();
198 void StopStream();
199 bool GetPresentationPosition(PresentationPosition& presentation_position);
200 void UpdateSourceMetadata(const struct source_metadata& source_metadata);
201 void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700202 // New versions for AIDL-only clients.
203 bool UpdateSourceMetadata(const SourceMetadata& hal_source_metadata);
204 bool UpdateSinkMetadata(const SinkMetadata& hal_sink_metadata);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800205
206 std::vector<LatencyMode> GetSupportedLatencyModes();
207 void SetLatencyMode(const LatencyMode& latency_mode);
Josh Wu20bac522021-12-29 23:52:39 -0800208
209 // The control function writes stream to FMQ
210 size_t OutWritePcmData(const void* buffer, size_t bytes);
211 // The control function read stream from FMQ
212 size_t InReadPcmData(void* buffer, size_t bytes);
213
214 // Return if IBluetoothAudioProviderFactory implementation existed
215 static bool IsAidlAvailable();
216
Josh Wu20bac522021-12-29 23:52:39 -0800217 private:
218 // using recursive_mutex to allow hwbinder to re-enter again.
219 std::recursive_mutex mutex_;
220 SessionType session_type_;
221
222 // audio control path to use for both software and offloading
223 std::shared_ptr<IBluetoothAudioPort> stack_iface_;
224 // audio data path (FMQ) for software encoding
225 std::unique_ptr<DataMQ> data_mq_;
226 // audio data configuration for both software and offloading
227 std::unique_ptr<AudioConfiguration> audio_config_;
Alice Kuo851ef342022-08-25 02:45:02 +0800228 std::unique_ptr<AudioConfiguration> leaudio_connection_map_;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800229 std::vector<LatencyMode> latency_modes_;
230 bool low_latency_allowed_ = true;
Alice Kuo851ef342022-08-25 02:45:02 +0800231 // saving those steaming state based on the session_type
232 bool is_streaming_ = false;
Josh Wu20bac522021-12-29 23:52:39 -0800233
234 // saving those registered bluetooth_audio's callbacks
235 std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
236 observers_;
237
238 bool UpdateDataPath(const DataMQDesc* mq_desc);
239 bool UpdateAudioConfig(const AudioConfiguration& audio_config);
240 // invoking the registered session_changed_cb_
241 void ReportSessionStatus();
242
243 static inline std::atomic<bool> is_aidl_checked = false;
244 static inline std::atomic<bool> is_aidl_available = false;
245 static inline const std::string kDefaultAudioProviderFactoryInterface =
246 std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
247};
248
249class BluetoothAudioSessionInstance {
250 public:
251 // The API is to fetch the specified session of A2DP / Hearing Aid
252 static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
253 const SessionType& session_type);
254
255 private:
256 static std::mutex mutex_;
257 static std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
258 sessions_map_;
259};
260
261} // namespace audio
262} // namespace bluetooth
263} // namespace hardware
264} // namespace android
Cheney Ni6ecbc762022-03-03 00:12:48 +0800265} // namespace aidl