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 <cstdint>
21 #include <memory>
22 #include <sstream>
23 #include <vector>
24
25 #include "audio_hal_interface/hearing_aid_software_encoding.h"
26 #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
27 #include "bta/include/bta_hearing_aid_api.h"
28 #include "common/repeating_timer.h"
29 #include "common/time_util.h"
30 #include "osi/include/wakelock.h"
31 #include "stack/include/btu.h" // get_main_thread
32 #include "udrv/include/uipc.h"
33
34 using base::FilePath;
35
36 namespace {
37 #define CASE_RETURN_STR(const) \
38 case const: \
39 return #const;
40
audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event)41 const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event) {
42 switch (event) {
43 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_NONE)
44 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_CHECK_READY)
45 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_START)
46 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_STOP)
47 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_SUSPEND)
48 CASE_RETURN_STR(HEARING_AID_CTRL_GET_INPUT_AUDIO_CONFIG)
49 CASE_RETURN_STR(HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG)
50 CASE_RETURN_STR(HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG)
51 CASE_RETURN_STR(HEARING_AID_CTRL_CMD_OFFLOAD_START)
52 default:
53 break;
54 }
55
56 return "UNKNOWN HEARING_AID_CTRL_CMD";
57 }
58
59 int bit_rate = -1;
60 int sample_rate = -1;
61 int data_interval_ms = -1;
62 int num_channels = 2;
63 bluetooth::common::RepeatingTimer audio_timer;
64 HearingAidAudioReceiver* localAudioReceiver = nullptr;
65 std::unique_ptr<tUIPC_STATE> uipc_hearing_aid = nullptr;
66
67 struct AudioHalStats {
68 size_t media_read_total_underflow_bytes;
69 size_t media_read_total_underflow_count;
70 uint64_t media_read_last_underflow_us;
71
AudioHalStats__anon5f7db97f0111::AudioHalStats72 AudioHalStats() { Reset(); }
73
Reset__anon5f7db97f0111::AudioHalStats74 void Reset() {
75 media_read_total_underflow_bytes = 0;
76 media_read_total_underflow_count = 0;
77 media_read_last_underflow_us = 0;
78 }
79 };
80
81 AudioHalStats stats;
82
83 bool hearing_aid_on_resume_req(bool start_media_task);
84 bool hearing_aid_on_suspend_req();
85
send_audio_data()86 void send_audio_data() {
87 uint32_t bytes_per_tick =
88 (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000;
89
90 uint16_t event;
91 uint8_t p_buf[bytes_per_tick];
92
93 uint32_t bytes_read;
94 if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
95 bytes_read = bluetooth::audio::hearing_aid::read(p_buf, bytes_per_tick);
96 } else {
97 bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, &event,
98 p_buf, bytes_per_tick);
99 }
100
101 VLOG(2) << "bytes_read: " << bytes_read;
102 if (bytes_read < bytes_per_tick) {
103 stats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
104 stats.media_read_total_underflow_count++;
105 stats.media_read_last_underflow_us =
106 bluetooth::common::time_get_os_boottime_us();
107 }
108
109 std::vector<uint8_t> data(p_buf, p_buf + bytes_read);
110
111 if (localAudioReceiver != nullptr) {
112 localAudioReceiver->OnAudioDataReady(data);
113 }
114 }
115
hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status)116 void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) {
117 uint8_t ack = status;
118 DVLOG(2) << "Hearing Aid audio ctrl ack: " << status;
119 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
120 }
121
start_audio_ticks()122 void start_audio_ticks() {
123 if (data_interval_ms != HA_INTERVAL_10_MS &&
124 data_interval_ms != HA_INTERVAL_20_MS) {
125 LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
126 }
127
128 wakelock_acquire();
129 audio_timer.SchedulePeriodic(
130 get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data),
131 base::TimeDelta::FromMilliseconds(data_interval_ms));
132 LOG(INFO) << __func__ << ": running with data interval: " << data_interval_ms;
133 }
134
stop_audio_ticks()135 void stop_audio_ticks() {
136 LOG(INFO) << __func__ << ": stopped";
137 audio_timer.CancelAndWait();
138 wakelock_release();
139 }
140
hearing_aid_data_cb(tUIPC_CH_ID,tUIPC_EVENT event)141 void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
142 DVLOG(2) << "Hearing Aid audio data event: " << event;
143 switch (event) {
144 case UIPC_OPEN_EVT:
145 LOG(INFO) << __func__ << ": UIPC_OPEN_EVT";
146 /*
147 * Read directly from media task from here on (keep callback for
148 * connection events.
149 */
150 UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO,
151 UIPC_REG_REMOVE_ACTIVE_READSET, NULL);
152 UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
153 reinterpret_cast<void*>(0));
154
155 do_in_main_thread(FROM_HERE, base::BindOnce(start_audio_ticks));
156 break;
157 case UIPC_CLOSE_EVT:
158 LOG(INFO) << __func__ << ": UIPC_CLOSE_EVT";
159 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
160 do_in_main_thread(FROM_HERE, base::BindOnce(stop_audio_ticks));
161 break;
162 default:
163 LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event;
164 }
165 }
166
hearing_aid_recv_ctrl_data()167 void hearing_aid_recv_ctrl_data() {
168 tHEARING_AID_CTRL_CMD cmd = HEARING_AID_CTRL_CMD_NONE;
169 int n;
170
171 uint8_t read_cmd = 0; /* The read command size is one octet */
172 n = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, NULL, &read_cmd, 1);
173 cmd = static_cast<tHEARING_AID_CTRL_CMD>(read_cmd);
174
175 /* detach on ctrl channel means audioflinger process was terminated */
176 if (n == 0) {
177 LOG(WARNING) << __func__ << "CTRL CH DETACHED";
178 UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL);
179 return;
180 }
181
182 LOG(INFO) << __func__ << " " << audio_ha_hw_dump_ctrl_event(cmd);
183 // a2dp_cmd_pending = cmd;
184
185 tHEARING_AID_CTRL_ACK ctrl_ack_status;
186
187 switch (cmd) {
188 case HEARING_AID_CTRL_CMD_CHECK_READY:
189 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
190 break;
191
192 case HEARING_AID_CTRL_CMD_START:
193 ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
194 // timer is restarted in UIPC_Open
195 if (!hearing_aid_on_resume_req(false)) {
196 ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
197 } else {
198 UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
199 HEARING_AID_DATA_PATH);
200 }
201 hearing_aid_send_ack(ctrl_ack_status);
202 break;
203
204 case HEARING_AID_CTRL_CMD_STOP:
205 if (!hearing_aid_on_suspend_req()) {
206 LOG(INFO) << __func__ << ":HEARING_AID_CTRL_CMD_STOP: hearing_aid_on_suspend_req() errs, but ignored.";
207 }
208 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
209 break;
210
211 case HEARING_AID_CTRL_CMD_SUSPEND:
212 ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
213 if (!hearing_aid_on_suspend_req()) {
214 ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
215 }
216 hearing_aid_send_ack(ctrl_ack_status);
217 break;
218
219 case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {
220 btav_a2dp_codec_config_t codec_config;
221 btav_a2dp_codec_config_t codec_capability;
222 if (sample_rate == 16000) {
223 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
224 codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
225 } else if (sample_rate == 24000) {
226 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
227 codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
228 } else {
229 LOG(FATAL) << "unsupported sample rate: " << sample_rate;
230 }
231
232 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
233 codec_capability.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
234
235 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
236 codec_capability.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
237
238 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
239 // Send the current codec config
240 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
241 reinterpret_cast<const uint8_t*>(&codec_config.sample_rate),
242 sizeof(btav_a2dp_codec_sample_rate_t));
243 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
244 reinterpret_cast<const uint8_t*>(&codec_config.bits_per_sample),
245 sizeof(btav_a2dp_codec_bits_per_sample_t));
246 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
247 reinterpret_cast<const uint8_t*>(&codec_config.channel_mode),
248 sizeof(btav_a2dp_codec_channel_mode_t));
249 // Send the current codec capability
250 UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
251 reinterpret_cast<const uint8_t*>(&codec_capability.sample_rate),
252 sizeof(btav_a2dp_codec_sample_rate_t));
253 UIPC_Send(
254 *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
255 reinterpret_cast<const uint8_t*>(&codec_capability.bits_per_sample),
256 sizeof(btav_a2dp_codec_bits_per_sample_t));
257 UIPC_Send(
258 *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
259 reinterpret_cast<const uint8_t*>(&codec_capability.channel_mode),
260 sizeof(btav_a2dp_codec_channel_mode_t));
261 break;
262 }
263
264 case HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: {
265 // TODO: we only support one config for now!
266 btav_a2dp_codec_config_t codec_config;
267 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
268 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
269 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
270
271 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
272 // Send the current codec config
273 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
274 reinterpret_cast<uint8_t*>(&codec_config.sample_rate),
275 sizeof(btav_a2dp_codec_sample_rate_t)) !=
276 sizeof(btav_a2dp_codec_sample_rate_t)) {
277 LOG(ERROR) << __func__ << "Error reading sample rate from audio HAL";
278 break;
279 }
280 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
281 reinterpret_cast<uint8_t*>(&codec_config.bits_per_sample),
282 sizeof(btav_a2dp_codec_bits_per_sample_t)) !=
283 sizeof(btav_a2dp_codec_bits_per_sample_t)) {
284 LOG(ERROR) << __func__
285 << "Error reading bits per sample from audio HAL";
286
287 break;
288 }
289 if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0,
290 reinterpret_cast<uint8_t*>(&codec_config.channel_mode),
291 sizeof(btav_a2dp_codec_channel_mode_t)) !=
292 sizeof(btav_a2dp_codec_channel_mode_t)) {
293 LOG(ERROR) << __func__ << "Error reading channel mode from audio HAL";
294
295 break;
296 }
297 LOG(INFO) << __func__ << " HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: "
298 << "sample_rate=" << codec_config.sample_rate
299 << "bits_per_sample=" << codec_config.bits_per_sample
300 << "channel_mode=" << codec_config.channel_mode;
301 break;
302 }
303
304 default:
305 LOG(ERROR) << __func__ << "UNSUPPORTED CMD: " << cmd;
306 hearing_aid_send_ack(HEARING_AID_CTRL_ACK_FAILURE);
307 break;
308 }
309 LOG(INFO) << __func__
310 << " a2dp-ctrl-cmd : " << audio_ha_hw_dump_ctrl_event(cmd)
311 << " DONE";
312 }
313
hearing_aid_ctrl_cb(tUIPC_CH_ID,tUIPC_EVENT event)314 void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
315 VLOG(2) << "Hearing Aid audio ctrl event: " << event;
316 switch (event) {
317 case UIPC_OPEN_EVT:
318 break;
319 case UIPC_CLOSE_EVT:
320 /* restart ctrl server unless we are shutting down */
321 if (HearingAid::IsHearingAidRunning()) {
322 UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
323 HEARING_AID_CTRL_PATH);
324 }
325 break;
326 case UIPC_RX_DATA_READY_EVT:
327 hearing_aid_recv_ctrl_data();
328 break;
329 default:
330 LOG(ERROR) << "Hearing Aid audio ctrl unrecognized event: " << event;
331 }
332 }
333
hearing_aid_on_resume_req(bool start_media_task)334 bool hearing_aid_on_resume_req(bool start_media_task) {
335 if (localAudioReceiver == nullptr) {
336 LOG(ERROR) << __func__
337 << ": HEARING_AID_CTRL_CMD_START: audio receiver not started";
338 return false;
339 }
340 bt_status_t status;
341 if (start_media_task) {
342 status = do_in_main_thread(
343 FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
344 base::Unretained(localAudioReceiver),
345 start_audio_ticks));
346 } else {
347 auto start_dummy_ticks = []() {
348 LOG(INFO) << "start_audio_ticks: waiting for data path opened";
349 };
350 status = do_in_main_thread(
351 FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
352 base::Unretained(localAudioReceiver),
353 start_dummy_ticks));
354 }
355 if (status != BT_STATUS_SUCCESS) {
356 LOG(ERROR) << __func__
357 << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err="
358 << status;
359 return false;
360 }
361 return true;
362 }
363
hearing_aid_on_suspend_req()364 bool hearing_aid_on_suspend_req() {
365 if (localAudioReceiver == nullptr) {
366 LOG(ERROR) << __func__
367 << ": HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started";
368 return false;
369 }
370 bt_status_t status = do_in_main_thread(
371 FROM_HERE,
372 base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
373 base::Unretained(localAudioReceiver), stop_audio_ticks));
374 if (status != BT_STATUS_SUCCESS) {
375 LOG(ERROR) << __func__
376 << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err="
377 << 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) << __func__ << ": 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_2_0_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) << __func__ << ": Hearing Aid Source Close";
404
405 localAudioReceiver = nullptr;
406 if (bluetooth::audio::hearing_aid::is_hal_2_0_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(WARNING) << __func__ << ": 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_2_0_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