1 /*
2 * Copyright 2021 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 "a2dp_encoding_host.h"
18
19 #include <bluetooth/log.h>
20 #include <grp.h>
21 #include <sys/stat.h>
22
23 #include <memory>
24 #include <vector>
25
26 #include "a2dp_encoding.h"
27 #include "btif/include/btif_a2dp_source.h"
28 #include "btif/include/btif_av.h"
29 #include "btif/include/btif_hf.h"
30 #include "stack/include/avdt_api.h"
31 #include "types/raw_address.h"
32 #include "udrv/include/uipc.h"
33
34 #define A2DP_DATA_READ_POLL_MS 10
35 #define A2DP_HOST_DATA_PATH "/var/run/bluetooth/audio/.a2dp_data"
36 // TODO(b/198260375): Make A2DP data owner group configurable.
37 #define A2DP_HOST_DATA_GROUP "bluetooth-audio"
38
39 typedef enum {
40 A2DP_CTRL_CMD_NONE,
41 A2DP_CTRL_CMD_CHECK_READY,
42 A2DP_CTRL_CMD_START,
43 A2DP_CTRL_CMD_STOP,
44 A2DP_CTRL_CMD_SUSPEND,
45 A2DP_CTRL_GET_INPUT_AUDIO_CONFIG,
46 A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG,
47 A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG,
48 A2DP_CTRL_GET_PRESENTATION_POSITION,
49 } tA2DP_CTRL_CMD;
50
51 namespace std {
52 template <>
53 struct formatter<tUIPC_EVENT> : enum_formatter<tUIPC_EVENT> {};
54 template <>
55 struct formatter<tA2DP_CTRL_CMD> : enum_formatter<tA2DP_CTRL_CMD> {};
56 } // namespace std
57
58 namespace {
59
60 std::unique_ptr<tUIPC_STATE> a2dp_uipc = nullptr;
61
btif_a2dp_data_cb(tUIPC_CH_ID ch_id,tUIPC_EVENT event)62 static void btif_a2dp_data_cb([[maybe_unused]] tUIPC_CH_ID ch_id, tUIPC_EVENT event) {
63 bluetooth::log::warn("BTIF MEDIA (A2DP-DATA) EVENT {}", dump_uipc_event(event));
64
65 switch (event) {
66 case UIPC_OPEN_EVT:
67 /*
68 * Read directly from media task from here on (keep callback for
69 * connection events.
70 */
71 UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
72 UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
73 reinterpret_cast<void*>(A2DP_DATA_READ_POLL_MS));
74
75 // Will start audio on btif_a2dp_on_started
76
77 /* ACK back when media task is fully started */
78 break;
79
80 case UIPC_CLOSE_EVT:
81 /* Post stop event and wait for audio path to stop */
82 btif_av_stream_stop(RawAddress::kEmpty);
83 break;
84
85 default:
86 bluetooth::log::error("### A2DP-DATA EVENT {} NOT HANDLED ###", event);
87 break;
88 }
89 }
90
91 // If A2DP_HOST_DATA_GROUP exists we expect audio server and BT both are
92 // in this group therefore have access to A2DP socket. Otherwise audio
93 // server should be in the same group that BT stack runs with to access
94 // A2DP socket.
a2dp_data_path_open()95 static void a2dp_data_path_open() {
96 UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb, A2DP_HOST_DATA_PATH);
97 struct group* grp = getgrnam(A2DP_HOST_DATA_GROUP);
98 chmod(A2DP_HOST_DATA_PATH, 0770);
99 if (grp) {
100 int res = chown(A2DP_HOST_DATA_PATH, -1, grp->gr_gid);
101 if (res == -1) {
102 bluetooth::log::error("failed: {}", strerror(errno));
103 }
104 }
105 }
106
107 tA2DP_CTRL_CMD a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
108 uint64_t total_bytes_read_;
109 timespec data_position_;
110 uint16_t remote_delay_report_;
111
112 } // namespace
113
114 namespace bluetooth {
115 namespace audio {
116 namespace a2dp {
117
118 // Invoked by audio server to set audio config (PCM for now)
SetAudioConfig(AudioConfig config)119 bool SetAudioConfig(AudioConfig config) {
120 btav_a2dp_codec_config_t codec_config;
121 codec_config.sample_rate = config.sample_rate;
122 codec_config.bits_per_sample = config.bits_per_sample;
123 codec_config.channel_mode = config.channel_mode;
124 btif_a2dp_source_feeding_update_req(codec_config);
125 return true;
126 }
127
128 // Invoked by audio server when it has audio data to stream.
StartRequest()129 bool StartRequest() {
130 // Reset total read bytes and timestamp to avoid confusing audio
131 // server at delay calculation.
132 total_bytes_read_ = 0;
133 data_position_ = {0, 0};
134
135 // Check if a previous request is not finished
136 if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_START) {
137 log::info("A2DP_CTRL_CMD_START in progress");
138 return false;
139 } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) {
140 log::warn("busy in pending_cmd={}", a2dp_pending_cmd_);
141 return false;
142 }
143
144 // Don't send START request to stack while we are in a call
145 if (!bluetooth::headset::IsCallIdle()) {
146 log::error("call state is busy");
147 return false;
148 }
149
150 if (btif_av_stream_started_ready(A2dpType::kSource)) {
151 // Already started, ACK back immediately.
152 a2dp_data_path_open();
153 return true;
154 }
155 if (btif_av_stream_ready(A2dpType::kSource)) {
156 a2dp_data_path_open();
157 /*
158 * Post start event and wait for audio path to open.
159 * If we are the source, the ACK will be sent after the start
160 * procedure is completed.
161 */
162 a2dp_pending_cmd_ = A2DP_CTRL_CMD_START;
163 btif_av_stream_start(A2dpType::kSource);
164 if (btif_av_get_peer_sep(A2dpType::kSource) != AVDT_TSEP_SRC) {
165 log::info("accepted");
166 return true; // NOTE: The request is placed, but could still fail.
167 }
168 a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
169 return true;
170 }
171 log::error("AV stream is not ready to start");
172 return false;
173 }
174
175 // Invoked by audio server when audio streaming is done.
StopRequest()176 bool StopRequest() {
177 if (btif_av_get_peer_sep(A2dpType::kSource) == AVDT_TSEP_SNK &&
178 !btif_av_stream_started_ready(A2dpType::kSource)) {
179 btif_av_clear_remote_suspend_flag(A2dpType::kSource);
180 return true;
181 }
182 log::info("handling");
183 a2dp_pending_cmd_ = A2DP_CTRL_CMD_STOP;
184 btif_av_stream_stop(RawAddress::kEmpty);
185 return true;
186 }
187
SuspendRequest()188 bool SuspendRequest() {
189 if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) {
190 log::warn("busy in pending_cmd={}", a2dp_pending_cmd_);
191 return false;
192 }
193 if (!btif_av_stream_started_ready(A2dpType::kSource)) {
194 log::warn("AV stream is not started");
195 return false;
196 }
197 log::info("handling");
198 a2dp_pending_cmd_ = A2DP_CTRL_CMD_SUSPEND;
199 btif_av_stream_suspend();
200 return true;
201 }
202
203 // Invoked by audio server to check audio presentation position periodically.
GetPresentationPosition()204 PresentationPosition GetPresentationPosition() {
205 PresentationPosition presentation_position{
206 .remote_delay_report_ns = remote_delay_report_ * 100000u,
207 .total_bytes_read = total_bytes_read_,
208 .data_position = data_position_,
209 };
210 return presentation_position;
211 }
212
213 // delay reports from AVDTP is based on 1/10 ms (100us)
set_remote_delay(uint16_t delay_report)214 void set_remote_delay(uint16_t delay_report) { remote_delay_report_ = delay_report; }
215
216 // Inform audio server about offloading codec; not used for now
update_codec_offloading_capabilities(const std::vector<btav_a2dp_codec_config_t> &,bool)217 bool update_codec_offloading_capabilities(
218 const std::vector<btav_a2dp_codec_config_t>& /*framework_preference*/,
219 bool /*supports_a2dp_hw_offload_v2*/) {
220 return false;
221 }
222
223 // Checking if new bluetooth_audio is enabled
is_hal_enabled()224 bool is_hal_enabled() { return true; }
225
226 // Check if new bluetooth_audio is running with offloading encoders
is_hal_offloading()227 bool is_hal_offloading() { return false; }
228
229 static StreamCallbacks null_stream_callbacks_;
230 static StreamCallbacks const* stream_callbacks_ = &null_stream_callbacks_;
231
232 // Initialize BluetoothAudio HAL: openProvider
init(bluetooth::common::MessageLoopThread *,StreamCallbacks const * strean_callbacks,bool)233 bool init(bluetooth::common::MessageLoopThread* /*message_loop*/,
234 StreamCallbacks const* strean_callbacks, bool /*offload_enabled*/) {
235 if (a2dp_uipc != nullptr) {
236 log::warn("Re-init-ing UIPC that is already running");
237 cleanup();
238 }
239 a2dp_uipc = UIPC_Init();
240 total_bytes_read_ = 0;
241 data_position_ = {};
242 remote_delay_report_ = 0;
243 stream_callbacks_ = strean_callbacks;
244
245 return true;
246 }
247
248 // Clean up BluetoothAudio HAL
cleanup()249 void cleanup() {
250 end_session();
251 stream_callbacks_ = &null_stream_callbacks_;
252
253 if (a2dp_uipc != nullptr) {
254 UIPC_Close(*a2dp_uipc, UIPC_CH_ID_ALL);
255 a2dp_uipc = nullptr;
256 }
257 }
258
259 // Set up the codec into BluetoothAudio HAL
setup_codec(A2dpCodecConfig *,uint16_t,int)260 bool setup_codec(A2dpCodecConfig* /*a2dp_config*/, uint16_t /*peer_mtu*/,
261 int /*preferred_encoding_interval_us*/) {
262 // TODO: setup codec
263 return true;
264 }
265
start_session()266 void start_session() {
267 // TODO: Notify server; or do we handle it during connected?
268 }
269
end_session()270 void end_session() {
271 // TODO: Notify server; or do we handle it during disconnected?
272
273 // Reset remote delay. New value will be set when new session starts.
274 remote_delay_report_ = 0;
275
276 a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
277 }
278
set_audio_low_latency_mode_allowed(bool)279 void set_audio_low_latency_mode_allowed(bool /*allowed*/) {}
280
ack_stream_started(Status)281 void ack_stream_started(Status /*ack*/) {
282 a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
283 // TODO: Notify server
284 }
285
ack_stream_suspended(Status)286 void ack_stream_suspended(Status /*ack*/) {
287 a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
288 // TODO: Notify server
289 }
290
291 // Read from the FMQ of BluetoothAudio HAL
read(uint8_t * p_buf,uint32_t len)292 size_t read(uint8_t* p_buf, uint32_t len) {
293 uint32_t bytes_read = 0;
294 if (a2dp_uipc == nullptr) {
295 return 0;
296 }
297 bytes_read = UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, p_buf, len);
298 total_bytes_read_ += bytes_read;
299 // MONOTONIC_RAW isn't affected by NTP, audio stack rely on this
300 // to get precise delay calculation.
301 clock_gettime(CLOCK_MONOTONIC_RAW, &data_position_);
302 return bytes_read;
303 }
304
305 // Check if OPUS codec is supported
is_opus_supported()306 bool is_opus_supported() { return true; }
307
308 namespace provider {
309
310 // Lookup the codec info in the list of supported offloaded sink codecs.
sink_codec_index(const uint8_t *)311 std::optional<btav_a2dp_codec_index_t> sink_codec_index(const uint8_t* /*p_codec_info*/) {
312 return std::nullopt;
313 }
314
315 // Lookup the codec info in the list of supported offloaded source codecs.
source_codec_index(const uint8_t *)316 std::optional<btav_a2dp_codec_index_t> source_codec_index(const uint8_t* /*p_codec_info*/) {
317 return std::nullopt;
318 }
319
320 // Return the name of the codec which is assigned to the input index.
321 // The codec index must be in the ranges
322 // BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN..BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX or
323 // BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN..BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX.
324 // Returns nullopt if the codec_index is not assigned or codec extensibility
325 // is not supported or enabled.
codec_index_str(btav_a2dp_codec_index_t)326 std::optional<const char*> codec_index_str(btav_a2dp_codec_index_t /*codec_index*/) {
327 return std::nullopt;
328 }
329
330 // Return true if the codec is supported for the session type
331 // A2DP_HARDWARE_ENCODING_DATAPATH or A2DP_HARDWARE_DECODING_DATAPATH.
supports_codec(btav_a2dp_codec_index_t)332 bool supports_codec(btav_a2dp_codec_index_t /*codec_index*/) { return false; }
333
334 // Return the A2DP capabilities for the selected codec.
codec_info(btav_a2dp_codec_index_t,bluetooth::a2dp::CodecId *,uint8_t *,btav_a2dp_codec_config_t *)335 bool codec_info(btav_a2dp_codec_index_t /*codec_index*/, bluetooth::a2dp::CodecId* /*codec_id*/,
336 uint8_t* /*codec_info*/, btav_a2dp_codec_config_t* /*codec_config*/) {
337 return false;
338 }
339
340 // Query the codec selection fromt the audio HAL.
341 // The HAL is expected to pick the best audio configuration based on the
342 // discovered remote SEPs.
get_a2dp_configuration(RawAddress,std::vector<a2dp_remote_capabilities> const &,btav_a2dp_codec_config_t const &)343 std::optional<a2dp_configuration> get_a2dp_configuration(
344 RawAddress /*peer_address*/, std::vector<a2dp_remote_capabilities> const& /*remote_seps*/,
345 btav_a2dp_codec_config_t const& /*user_preferences*/) {
346 return std::nullopt;
347 }
348
349 // Query the codec parameters from the audio HAL.
350 // The HAL performs a two part validation:
351 // - check if the configuration is valid
352 // - check if the configuration is supported by the audio provider
353 // In case any of these checks fails, the corresponding A2DP
354 // status is returned. If the configuration is valid and supported,
355 // A2DP_OK is returned.
parse_a2dp_configuration(btav_a2dp_codec_index_t,const uint8_t *,btav_a2dp_codec_config_t *,std::vector<uint8_t> *)356 tA2DP_STATUS parse_a2dp_configuration(btav_a2dp_codec_index_t /*codec_index*/,
357 const uint8_t* /*codec_info*/,
358 btav_a2dp_codec_config_t* /*codec_parameters*/,
359 std::vector<uint8_t>* /*vendor_specific_parameters*/) {
360 return A2DP_FAIL;
361 }
362
363 } // namespace provider
364
365 } // namespace a2dp
366 } // namespace audio
367 } // namespace bluetooth
368