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