1 /******************************************************************************
2 *
3 * Copyright 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <base/files/file_util.h>
20 #include <base/logging.h>
21
22 #include <cstdint>
23 #include <memory>
24 #include <sstream>
25 #include <vector>
26
27 #include "audio_hal_interface/hearing_aid_software_encoding.h"
28 #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
29 #include "bta/include/bta_hearing_aid_api.h"
30 #include "common/repeating_timer.h"
31 #include "common/time_util.h"
32 #include "osi/include/log.h"
33 #include "osi/include/wakelock.h"
34 #include "stack/include/btu.h" // get_main_thread
35 #include "udrv/include/uipc.h"
36
37 using base::FilePath;
38
39 namespace {
40 #define CASE_RETURN_STR(const) \
41 case const: \
42 return #const;
43
audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event)44 const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event) {
45 switch (event) {
46 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_NONE)
47 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_CHECK_READY)
48 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_START)
49 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_STOP)
50 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_SUSPEND)
51 CASE_RETURN_STR(HEARING_AID_CTRL_GET_INPUT_AUDIO_CONFIG)
52 CASE_RETURN_STR(HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG)
53 CASE_RETURN_STR(HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG)
54 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_OFFLOAD_START)
55 default:
56 break;
57 }
58
59 return "UNKNOWN HEARING_AID_CTRL_CMD";
60 }
61
62 int bit_rate = -1;
63 int sample_rate = -1;
64 int data_interval_ms = -1;
65 int num_channels = 2;
66 bluetooth::common::RepeatingTimer audio_timer;
67 HearingAidAudioReceiver* localAudioReceiver = nullptr;
68 std::unique_ptr<tUIPC_STATE> uipc_hearing_aid = nullptr;
69
70 struct AudioHalStats {
71 size_t media_read_total_underflow_bytes;
72 size_t media_read_total_underflow_count;
73 uint64_t media_read_last_underflow_us;
74
AudioHalStats__anonb2467cb30111::AudioHalStats75 AudioHalStats() { Reset(); }
76
Reset__anonb2467cb30111::AudioHalStats77 void Reset() {
78 media_read_total_underflow_bytes = 0;
79 media_read_total_underflow_count = 0;
80 media_read_last_underflow_us = 0;
81 }
82 };
83
84 AudioHalStats stats;
85
86 bool hearing_aid_on_resume_req(bool start_media_task);
87 bool hearing_aid_on_suspend_req();
88
send_audio_data()89 void send_audio_data() {
90 uint32_t bytes_per_tick =
91 (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000;
92
93 uint8_t p_buf[bytes_per_tick];
94
95 uint32_t bytes_read;
96 if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
97 bytes_read = bluetooth::audio::hearing_aid::read(p_buf, bytes_per_tick);
98 } else {
99 bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, p_buf,
100 bytes_per_tick);
101 }
102
103 LOG_DEBUG("bytes_read: %u", bytes_read);
104 if (bytes_read < bytes_per_tick) {
105 stats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
106 stats.media_read_total_underflow_count++;
107 stats.media_read_last_underflow_us =
108 bluetooth::common::time_get_os_boottime_us();
109 }
110
111 std::vector<uint8_t> data(p_buf, p_buf + bytes_read);
112
113 if (localAudioReceiver != nullptr) {
114 localAudioReceiver->OnAudioDataReady(data);
115 }
116 }
117
hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status)118 void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) {
119 uint8_t ack = status;
120 LOG_DEBUG("Hearing Aid audio ctrl ack: %u", status);
121 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
122 }
123
start_audio_ticks()124 void start_audio_ticks() {
125 if (data_interval_ms != HA_INTERVAL_10_MS &&
126 data_interval_ms != HA_INTERVAL_20_MS) {
127 LOG_ALWAYS_FATAL("Unsupported data interval: %d", data_interval_ms);
128 }
129
130 wakelock_acquire();
131 audio_timer.SchedulePeriodic(
132 get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data),
133 #if BASE_VER < 931007
134 base::TimeDelta::FromMilliseconds(data_interval_ms));
135 #else
136 base::Milliseconds(data_interval_ms));
137 #endif
138 LOG_INFO("running with data interval: %d", data_interval_ms);
139 }
140
stop_audio_ticks()141 void stop_audio_ticks() {
142 LOG_INFO("stopped");
143 audio_timer.CancelAndWait();
144 wakelock_release();
145 }
146
hearing_aid_data_cb(tUIPC_CH_ID,tUIPC_EVENT event)147 void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
148 LOG_DEBUG("Hearing Aid audio data event: %u", event);
149 switch (event) {
150 case UIPC_OPEN_EVT:
151 LOG_INFO("UIPC_OPEN_EVT");
152 /*
153 * Read directly from media task from here on (keep callback for
154 * connection events.
155 */
156 UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO,
157 UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
158 UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
159 reinterpret_cast<void*>(0));
160
161 do_in_main_thread(FROM_HERE, base::BindOnce(start_audio_ticks));
162 break;
163 case UIPC_CLOSE_EVT:
164 LOG_INFO("UIPC_CLOSE_EVT");
165 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
166 do_in_main_thread(FROM_HERE, base::BindOnce(stop_audio_ticks));
167 break;
168 default:
169 LOG_ERROR("Hearing Aid audio data event not recognized: %u", event);
170 }
171 }
172
hearing_aid_recv_ctrl_data()173 void hearing_aid_recv_ctrl_data() {
174 tHEARING_AID_CTRL_CMD cmd = HEARING_AID_CTRL_CMD_NONE;
175 int n;
176
177 uint8_t read_cmd = 0; /* The read command size is one octet */
178 n = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, &read_cmd, 1);
179 cmd = static_cast<tHEARING_AID_CTRL_CMD>(read_cmd);
180
181 /* detach on ctrl channel means audioflinger process was terminated */
182 if (n == 0) {
183 LOG_WARN("CTRL CH DETACHED");
184 UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL);
185 return;
186 }
187
188 LOG_INFO("%s", audio_ha_hw_dump_ctrl_event(cmd));
189 // a2dp_cmd_pending = cmd;
190
191 tHEARING_AID_CTRL_ACK ctrl_ack_status;
192
193 switch (cmd) {
194 case HEARING_AID_CTRL_CMD_CHECK_READY:
195 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
196 break;
197
198 case HEARING_AID_CTRL_CMD_START:
199 ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
200 // timer is restarted in UIPC_Open
201 if (!hearing_aid_on_resume_req(false)) {
202 ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
203 } else {
204 UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
205 HEARING_AID_DATA_PATH);
206 }
207 hearing_aid_send_ack(ctrl_ack_status);
208 break;
209
210 case HEARING_AID_CTRL_CMD_STOP:
211 if (!hearing_aid_on_suspend_req()) {
212 LOG_INFO(
213 "HEARING_AID_CTRL_CMD_STOP: hearing_aid_on_suspend_req() errs, but "
214 "ignored.");
215 }
216 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
217 break;
218
219 case HEARING_AID_CTRL_CMD_SUSPEND:
220 ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
221 if (!hearing_aid_on_suspend_req()) {
222 ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
223 }
224 hearing_aid_send_ack(ctrl_ack_status);
225 break;
226
227 case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {
228 btav_a2dp_codec_config_t codec_config;
229 btav_a2dp_codec_config_t codec_capability;
230 if (sample_rate == 16000) {
231 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
232 codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
233 } else if (sample_rate == 24000) {
234 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
235 codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
236 } else {
237 LOG_ALWAYS_FATAL("unsupported sample rate: %d", sample_rate);
238 }
239
240 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
241 codec_capability.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
242
243 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
244 codec_capability.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
245
246 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
247 // Send the current codec config
248 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
249 reinterpret_cast<const uint8_t*>(&codec_config.sample_rate),
250 sizeof(btav_a2dp_codec_sample_rate_t));
251 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
252 reinterpret_cast<const uint8_t*>(&codec_config.bits_per_sample),
253 sizeof(btav_a2dp_codec_bits_per_sample_t));
254 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
255 reinterpret_cast<const uint8_t*>(&codec_config.channel_mode),
256 sizeof(btav_a2dp_codec_channel_mode_t));
257 // Send the current codec capability
258 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
259 reinterpret_cast<const uint8_t*>(&codec_capability.sample_rate),
260 sizeof(btav_a2dp_codec_sample_rate_t));
261 UIPC_Send(
262 *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
263 reinterpret_cast<const uint8_t*>(&codec_capability.bits_per_sample),
264 sizeof(btav_a2dp_codec_bits_per_sample_t));
265 UIPC_Send(
266 *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
267 reinterpret_cast<const uint8_t*>(&codec_capability.channel_mode),
268 sizeof(btav_a2dp_codec_channel_mode_t));
269 break;
270 }
271
272 case HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: {
273 // TODO: we only support one config for now!
274 btav_a2dp_codec_config_t codec_config;
275 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
276 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
277 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
278
279 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
280 // Send the current codec config
281 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL,
282 reinterpret_cast<uint8_t*>(&codec_config.sample_rate),
283 sizeof(btav_a2dp_codec_sample_rate_t)) !=
284 sizeof(btav_a2dp_codec_sample_rate_t)) {
285 LOG_ERROR("Error reading sample rate from audio HAL");
286 break;
287 }
288 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL,
289 reinterpret_cast<uint8_t*>(&codec_config.bits_per_sample),
290 sizeof(btav_a2dp_codec_bits_per_sample_t)) !=
291 sizeof(btav_a2dp_codec_bits_per_sample_t)) {
292 LOG_ERROR("Error reading bits per sample from audio HAL");
293
294 break;
295 }
296 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL,
297 reinterpret_cast<uint8_t*>(&codec_config.channel_mode),
298 sizeof(btav_a2dp_codec_channel_mode_t)) !=
299 sizeof(btav_a2dp_codec_channel_mode_t)) {
300 LOG_ERROR("Error reading channel mode from audio HAL");
301
302 break;
303 }
304 LOG_INFO(
305 "HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: sample_rate=%u, "
306 "bits_per_sample=%u,channel_mode=%u",
307 codec_config.sample_rate, codec_config.bits_per_sample,
308 codec_config.channel_mode);
309 break;
310 }
311
312 default:
313 LOG_ERROR("UNSUPPORTED CMD: %u", cmd);
314 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_FAILURE);
315 break;
316 }
317 LOG_INFO("a2dp-ctrl-cmd : %s DONE", audio_ha_hw_dump_ctrl_event(cmd));
318 }
319
hearing_aid_ctrl_cb(tUIPC_CH_ID,tUIPC_EVENT event)320 void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
321 LOG_DEBUG("Hearing Aid audio ctrl event: %u", event);
322 switch (event) {
323 case UIPC_OPEN_EVT:
324 break;
325 case UIPC_CLOSE_EVT:
326 /* restart ctrl server unless we are shutting down */
327 if (HearingAid::IsHearingAidRunning()) {
328 UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
329 HEARING_AID_CTRL_PATH);
330 }
331 break;
332 case UIPC_RX_DATA_READY_EVT:
333 hearing_aid_recv_ctrl_data();
334 break;
335 default:
336 LOG_ERROR("Hearing Aid audio ctrl unrecognized event: %u", event);
337 }
338 }
339
hearing_aid_on_resume_req(bool start_media_task)340 bool hearing_aid_on_resume_req(bool start_media_task) {
341 if (localAudioReceiver == nullptr) {
342 LOG_ERROR("HEARING_AID_CTRL_CMD_START: audio receiver not started");
343 return false;
344 }
345 bt_status_t status;
346 if (start_media_task) {
347 status = do_in_main_thread(
348 FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
349 base::Unretained(localAudioReceiver),
350 start_audio_ticks));
351 } else {
352 auto start_dummy_ticks = []() {
353 LOG_INFO("start_audio_ticks: waiting for data path opened");
354 };
355 status = do_in_main_thread(
356 FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
357 base::Unretained(localAudioReceiver),
358 start_dummy_ticks));
359 }
360 if (status != BT_STATUS_SUCCESS) {
361 LOG_ERROR("HEARING_AID_CTRL_CMD_START: do_in_main_thread err=%u", status);
362 return false;
363 }
364 return true;
365 }
366
hearing_aid_on_suspend_req()367 bool hearing_aid_on_suspend_req() {
368 if (localAudioReceiver == nullptr) {
369 LOG_ERROR("HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started");
370 return false;
371 }
372 bt_status_t status = do_in_main_thread(
373 FROM_HERE,
374 base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
375 base::Unretained(localAudioReceiver), stop_audio_ticks));
376 if (status != BT_STATUS_SUCCESS) {
377 LOG_ERROR("HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err=%u", status);
378 return false;
379 }
380 return true;
381 }
382 } // namespace
383
Start(const CodecConfiguration & codecConfiguration,HearingAidAudioReceiver * audioReceiver,uint16_t remote_delay_ms)384 void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
385 HearingAidAudioReceiver* audioReceiver,
386 uint16_t remote_delay_ms) {
387 LOG_INFO("Hearing Aid Source Open");
388
389 bit_rate = codecConfiguration.bit_rate;
390 sample_rate = codecConfiguration.sample_rate;
391 data_interval_ms = codecConfiguration.data_interval_ms;
392
393 stats.Reset();
394
395 if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
396 bluetooth::audio::hearing_aid::start_session();
397 bluetooth::audio::hearing_aid::set_remote_delay(remote_delay_ms);
398 }
399 localAudioReceiver = audioReceiver;
400 }
401
Stop()402 void HearingAidAudioSource::Stop() {
403 LOG_INFO("Hearing Aid Source Close");
404
405 localAudioReceiver = nullptr;
406 if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
407 bluetooth::audio::hearing_aid::end_session();
408 }
409
410 stop_audio_ticks();
411 }
412
Initialize()413 void HearingAidAudioSource::Initialize() {
414 auto stream_cb = bluetooth::audio::hearing_aid::StreamCallbacks{
415 .on_resume_ = hearing_aid_on_resume_req,
416 .on_suspend_ = hearing_aid_on_suspend_req,
417 };
418 if (!bluetooth::audio::hearing_aid::init(stream_cb, get_main_thread())) {
419 LOG_WARN("Using legacy HAL");
420 uipc_hearing_aid = UIPC_Init();
421 UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb, HEARING_AID_CTRL_PATH);
422 }
423 }
424
CleanUp()425 void HearingAidAudioSource::CleanUp() {
426 if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
427 bluetooth::audio::hearing_aid::cleanup();
428 } else {
429 UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL);
430 uipc_hearing_aid = nullptr;
431 }
432 }
433
DebugDump(int fd)434 void HearingAidAudioSource::DebugDump(int fd) {
435 uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
436 std::stringstream stream;
437 stream << " Hearing Aid Audio HAL:"
438 << "\n Counts (underflow) : "
439 << stats.media_read_total_underflow_count
440 << "\n Bytes (underflow) : "
441 << stats.media_read_total_underflow_bytes
442 << "\n Last update time ago in ms (underflow) : "
443 << (stats.media_read_last_underflow_us > 0
444 ? (unsigned long long)(now_us -
445 stats.media_read_last_underflow_us) /
446 1000
447 : 0)
448 << std::endl;
449 dprintf(fd, "%s", stream.str().c_str());
450 }
451