From be754da679acd96d1389f5a37ad13b111e72b410 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Fri, 19 Jan 2018 12:23:57 -0800 Subject: [PATCH] HearingAidAudioSource implementation Test: none Bug: 69623109 Change-Id: Iaadd337ed5a8152db54b7515d55e0358f413f937 --- bta/Android.bp | 5 + bta/hearing_aid/hearing_aid_audio_source.cc | 262 ++++++++++++++++++++++++++++ udrv/include/uipc.h | 2 + 3 files changed, 269 insertions(+) create mode 100644 bta/hearing_aid/hearing_aid_audio_source.cc diff --git a/bta/Android.bp b/bta/Android.bp index 0aac12440..575918332 100644 --- a/bta/Android.bp +++ b/bta/Android.bp @@ -67,6 +67,7 @@ cc_library_static { "gatt/bta_gatts_main.cc", "gatt/bta_gatts_utils.cc", "hearing_aid/hearing_aid.cc", + "hearing_aid/hearing_aid_audio_source.cc", "hf_client/bta_hf_client_act.cc", "hf_client/bta_hf_client_api.cc", "hf_client/bta_hf_client_at.cc", @@ -108,6 +109,10 @@ cc_library_static { "sys/bta_sys_main.cc", "sys/utl.cc", ], + + whole_static_libs: [ + "libaudio-hearing-aid-hw-utils", + ], } // bta unit tests for target diff --git a/bta/hearing_aid/hearing_aid_audio_source.cc b/bta/hearing_aid/hearing_aid_audio_source.cc new file mode 100644 index 000000000..276957bbe --- /dev/null +++ b/bta/hearing_aid/hearing_aid_audio_source.cc @@ -0,0 +1,262 @@ +/****************************************************************************** + * + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h" +#include "bta_hearing_aid_api.h" +#include "osi/include/alarm.h" +#include "uipc.h" + +#include +#include +#include + +using base::FilePath; +extern const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event); + +namespace { +int bit_rate = 16; +int sample_rate = 16000; +int data_interval_ms = 20 /* msec */; +int num_channels = 2; +alarm_t* audio_timer = nullptr; + +HearingAidAudioReceiver* localAudioReceiver; +std::unique_ptr uipc_hearing_aid; + +void send_audio_data(void*) { + int bytes_per_tick = + (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000; + + uint16_t event; + uint8_t p_buf[bytes_per_tick]; + + uint32_t bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, + &event, p_buf, bytes_per_tick); + + VLOG(2) << "bytes_read: " << bytes_read; + + std::vector data(p_buf, p_buf + bytes_read); + + localAudioReceiver->OnAudioDataReady(data); +} + +void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) { + uint8_t ack = status; + DVLOG(2) << "Hearing Aid audio ctrl ack: " << status; + UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack)); +} + +void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) { + DVLOG(2) << "Hearing Aid audio data event: " << event; + switch (event) { + case UIPC_OPEN_EVT: + /* + * Read directly from media task from here on (keep callback for + * connection events. + */ + UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, + UIPC_REG_REMOVE_ACTIVE_READSET, NULL); + UIPC_Ioctl(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO, + reinterpret_cast(0)); + + audio_timer = alarm_new_periodic("hearing_aid_data_timer"); + alarm_set_on_mloop(audio_timer, data_interval_ms, send_audio_data, + nullptr); + break; + case UIPC_CLOSE_EVT: + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + if (audio_timer) { + alarm_cancel(audio_timer); + } + break; + default: + LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event; + } +} + +void hearing_aid_recv_ctrl_data() { + tHEARING_AID_CTRL_CMD cmd = HEARING_AID_CTRL_CMD_NONE; + int n; + + uint8_t read_cmd = 0; /* The read command size is one octet */ + n = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, NULL, &read_cmd, 1); + cmd = static_cast(read_cmd); + + /* detach on ctrl channel means audioflinger process was terminated */ + if (n == 0) { + LOG(WARNING) << __func__ << "CTRL CH DETACHED"; + UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL); + return; + } + + VLOG(2) << __func__ << " " << audio_ha_hw_dump_ctrl_event(cmd); + // a2dp_cmd_pending = cmd; + + switch (cmd) { + case HEARING_AID_CTRL_CMD_CHECK_READY: + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + break; + + case HEARING_AID_CTRL_CMD_START: + localAudioReceiver->OnAudioResume(); + // timer is restarted in UIPC_Open + UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb); + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + break; + + case HEARING_AID_CTRL_CMD_STOP: + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + break; + + case HEARING_AID_CTRL_CMD_SUSPEND: + if (audio_timer) alarm_cancel(audio_timer); + localAudioReceiver->OnAudioSuspend(); + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + break; + + case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: { + btav_a2dp_codec_config_t codec_config; + btav_a2dp_codec_config_t codec_capability; + if (sample_rate == 16000) { + codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000; + codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_16000; + } else if (sample_rate == 24000) { + codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000; + codec_capability.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_24000; + } else { + LOG(FATAL) << "unsupported sample rate: " << sample_rate; + } + + codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; + codec_capability.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; + + codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; + codec_capability.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; + + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + // Send the current codec config + UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.sample_rate), + sizeof(btav_a2dp_codec_sample_rate_t)); + UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.bits_per_sample), + sizeof(btav_a2dp_codec_bits_per_sample_t)); + UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.channel_mode), + sizeof(btav_a2dp_codec_channel_mode_t)); + // Send the current codec capability + UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_capability.sample_rate), + sizeof(btav_a2dp_codec_sample_rate_t)); + UIPC_Send( + *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_capability.bits_per_sample), + sizeof(btav_a2dp_codec_bits_per_sample_t)); + UIPC_Send( + *uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_capability.channel_mode), + sizeof(btav_a2dp_codec_channel_mode_t)); + break; + } + + case HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: { + // TODO: we only support one config for now! + btav_a2dp_codec_config_t codec_config; + codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; + codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; + codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; + + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS); + // Send the current codec config + if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.sample_rate), + sizeof(btav_a2dp_codec_sample_rate_t)) != + sizeof(btav_a2dp_codec_sample_rate_t)) { + LOG(ERROR) << __func__ << "Error reading sample rate from audio HAL"; + break; + } + if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.bits_per_sample), + sizeof(btav_a2dp_codec_bits_per_sample_t)) != + sizeof(btav_a2dp_codec_bits_per_sample_t)) { + LOG(ERROR) << __func__ + << "Error reading bits per sample from audio HAL"; + + break; + } + if (UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, + reinterpret_cast(&codec_config.channel_mode), + sizeof(btav_a2dp_codec_channel_mode_t)) != + sizeof(btav_a2dp_codec_channel_mode_t)) { + LOG(ERROR) << __func__ << "Error reading channel mode from audio HAL"; + + break; + } + LOG(INFO) << __func__ << " HEARING_AID_CTRL_SET_OUTPUT_AUDIO_CONFIG: " + << "sample_rate=" << codec_config.sample_rate + << "bits_per_sample=" << codec_config.bits_per_sample + << "channel_mode=" << codec_config.channel_mode; + break; + } + + default: + LOG(ERROR) << __func__ << "UNSUPPORTED CMD: " << cmd; + hearing_aid_send_ack(HEARING_AID_CTRL_ACK_FAILURE); + break; + } + VLOG(2) << __func__ << " a2dp-ctrl-cmd : " << audio_ha_hw_dump_ctrl_event(cmd) + << " DONE"; +} + +void hearing_aid_ctrl_cb(tUIPC_CH_ID, tUIPC_EVENT event) { + VLOG(2) << "Hearing Aid audio ctrl event: " << event; + switch (event) { + case UIPC_OPEN_EVT: + break; + case UIPC_CLOSE_EVT: + UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb); + break; + case UIPC_RX_DATA_READY_EVT: + hearing_aid_recv_ctrl_data(); + break; + default: + LOG(ERROR) << "Hearing Aid audio ctrl unrecognized event: " << event; + } +} +} // namespace + +void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration, + HearingAidAudioReceiver* audioReceiver) { + localAudioReceiver = audioReceiver; + VLOG(2) << "Hearing Aid UIPC Open"; +} + +void HearingAidAudioSource::Stop() { + if (audio_timer) { + alarm_cancel(audio_timer); + } +} + +void HearingAidAudioSource::Initialize() { + uipc_hearing_aid = UIPC_Init(); + UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb); +} + +void HearingAidAudioSource::CleanUp() { + UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL); +} diff --git a/udrv/include/uipc.h b/udrv/include/uipc.h index b5540b2e0..bd1c8bf67 100644 --- a/udrv/include/uipc.h +++ b/udrv/include/uipc.h @@ -18,6 +18,8 @@ #ifndef UIPC_H #define UIPC_H +#include + #define UIPC_CH_ID_AV_CTRL 0 #define UIPC_CH_ID_AV_AUDIO 1 #define UIPC_CH_NUM 2 -- 2.11.0