123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /*
- * Copyright 2019 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.
- */
- #define LOG_TAG "BTAudioClientHearingAid"
- #include "hearing_aid_software_encoding.h"
- #include "client_interface.h"
- #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
- #include "osi/include/log.h"
- #include "osi/include/properties.h"
- namespace {
- using ::android::hardware::bluetooth::audio::V2_0::CodecType;
- using ::bluetooth::audio::AudioConfiguration;
- using ::bluetooth::audio::BitsPerSample;
- using ::bluetooth::audio::BluetoothAudioCtrlAck;
- using ::bluetooth::audio::ChannelMode;
- using ::bluetooth::audio::PcmParameters;
- using ::bluetooth::audio::SampleRate;
- using ::bluetooth::audio::SessionType;
- using ::bluetooth::audio::hearing_aid::StreamCallbacks;
- // Transport implementation for Hearing Aids
- class HearingAidTransport
- : public bluetooth::audio::IBluetoothTransportInstance {
- public:
- HearingAidTransport(StreamCallbacks stream_cb)
- : IBluetoothTransportInstance(
- SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, {}),
- stream_cb_(std::move(stream_cb)),
- remote_delay_report_ms_(0),
- total_bytes_read_(0),
- data_position_({}){};
- BluetoothAudioCtrlAck StartRequest() override {
- LOG(INFO) << __func__;
- if (stream_cb_.on_resume_(true)) {
- return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
- }
- return BluetoothAudioCtrlAck::FAILURE;
- }
- BluetoothAudioCtrlAck SuspendRequest() override {
- LOG(INFO) << __func__;
- if (stream_cb_.on_suspend_()) {
- uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
- ::bluetooth::audio::hearing_aid::read(p_buf, sizeof(p_buf));
- return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
- } else {
- return BluetoothAudioCtrlAck::FAILURE;
- }
- }
- void StopRequest() override {
- LOG(INFO) << __func__;
- if (stream_cb_.on_suspend_()) {
- // flush
- uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
- ::bluetooth::audio::hearing_aid::read(p_buf, sizeof(p_buf));
- }
- }
- bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
- uint64_t* total_bytes_read,
- timespec* data_position) override {
- VLOG(2) << __func__ << ": data=" << total_bytes_read_
- << " byte(s), timestamp=" << data_position_.tv_sec << "."
- << data_position_.tv_nsec
- << "s, delay report=" << remote_delay_report_ms_ << " msec.";
- if (remote_delay_report_ns != nullptr) {
- *remote_delay_report_ns = remote_delay_report_ms_ * 1000000u;
- }
- if (total_bytes_read != nullptr) *total_bytes_read = total_bytes_read_;
- if (data_position != nullptr) *data_position = data_position_;
- return true;
- }
- void MetadataChanged(const source_metadata_t& source_metadata) override {
- auto track_count = source_metadata.track_count;
- auto tracks = source_metadata.tracks;
- LOG(INFO) << __func__ << ": " << track_count << " track(s) received";
- while (track_count) {
- VLOG(1) << __func__ << ": usage=" << tracks->usage
- << ", content_type=" << tracks->content_type
- << ", gain=" << tracks->gain;
- --track_count;
- ++tracks;
- }
- }
- void ResetPresentationPosition() override {
- VLOG(2) << __func__ << ": called.";
- remote_delay_report_ms_ = 0;
- total_bytes_read_ = 0;
- data_position_ = {};
- }
- void LogBytesRead(size_t bytes_read) override {
- if (bytes_read) {
- total_bytes_read_ += bytes_read;
- clock_gettime(CLOCK_MONOTONIC, &data_position_);
- }
- }
- void SetRemoteDelay(uint16_t delay_report_ms) {
- LOG(INFO) << __func__ << ": delay_report=" << delay_report_ms << " msec";
- remote_delay_report_ms_ = delay_report_ms;
- }
- private:
- StreamCallbacks stream_cb_;
- uint16_t remote_delay_report_ms_;
- uint64_t total_bytes_read_;
- timespec data_position_;
- };
- bool HearingAidGetSelectedHalPcmConfig(PcmParameters* hal_pcm_config) {
- if (hal_pcm_config == nullptr) return false;
- // TODO: we only support one config for now!
- hal_pcm_config->sampleRate = SampleRate::RATE_16000;
- hal_pcm_config->bitsPerSample = BitsPerSample::BITS_16;
- hal_pcm_config->channelMode = ChannelMode::STEREO;
- return true;
- }
- // Sink instance of Hearing Aids to provide call-in APIs for Bluetooth Audio Hal
- HearingAidTransport* hearing_aid_sink = nullptr;
- // Common interface to call-out into Bluetooth Audio Hal
- bluetooth::audio::BluetoothAudioClientInterface*
- hearing_aid_hal_clientinterface = nullptr;
- bool btaudio_hearing_aid_disabled = false;
- bool is_configured = false;
- // Save the value if the remote reports its delay before hearing_aid_sink is
- // initialized
- uint16_t remote_delay_ms = 0;
- bool is_hal_2_0_force_disabled() {
- if (!is_configured) {
- btaudio_hearing_aid_disabled = osi_property_get_bool(BLUETOOTH_AUDIO_HAL_PROP_DISABLED, false);
- is_configured = true;
- }
- return btaudio_hearing_aid_disabled;
- }
- } // namespace
- namespace bluetooth {
- namespace audio {
- namespace hearing_aid {
- bool is_hal_2_0_enabled() { return hearing_aid_hal_clientinterface != nullptr; }
- bool init(StreamCallbacks stream_cb,
- bluetooth::common::MessageLoopThread* message_loop) {
- LOG(INFO) << __func__;
- if (is_hal_2_0_force_disabled()) {
- LOG(ERROR) << __func__ << ": BluetoothAudio HAL is disabled";
- return false;
- }
- hearing_aid_sink = new HearingAidTransport(std::move(stream_cb));
- hearing_aid_hal_clientinterface =
- new bluetooth::audio::BluetoothAudioClientInterface(hearing_aid_sink,
- message_loop);
- if (!hearing_aid_hal_clientinterface->IsValid()) {
- LOG(WARNING) << __func__ << ": BluetoothAudio HAL for Hearing Aid is invalid?!";
- delete hearing_aid_hal_clientinterface;
- hearing_aid_hal_clientinterface = nullptr;
- delete hearing_aid_sink;
- hearing_aid_sink = nullptr;
- return false;
- }
- if (remote_delay_ms != 0) {
- LOG(INFO) << __func__ << ": restore DELAY " << remote_delay_ms << " ms";
- hearing_aid_sink->SetRemoteDelay(remote_delay_ms);
- remote_delay_ms = 0;
- }
- return true;
- }
- void cleanup() {
- LOG(INFO) << __func__;
- if (!is_hal_2_0_enabled()) return;
- end_session();
- delete hearing_aid_hal_clientinterface;
- hearing_aid_hal_clientinterface = nullptr;
- delete hearing_aid_sink;
- hearing_aid_sink = nullptr;
- remote_delay_ms = 0;
- }
- void start_session() {
- LOG(INFO) << __func__;
- if (!is_hal_2_0_enabled()) return;
- AudioConfiguration audio_config;
- PcmParameters pcm_config{};
- if (!HearingAidGetSelectedHalPcmConfig(&pcm_config)) {
- LOG(ERROR) << __func__ << ": cannot get PCM config";
- return;
- }
- audio_config.pcmConfig(pcm_config);
- if (!hearing_aid_hal_clientinterface->UpdateAudioConfig(audio_config)) {
- LOG(ERROR) << __func__ << ": cannot update audio config to HAL";
- return;
- }
- hearing_aid_hal_clientinterface->StartSession();
- }
- void end_session() {
- LOG(INFO) << __func__;
- if (!is_hal_2_0_enabled()) return;
- hearing_aid_hal_clientinterface->EndSession();
- }
- size_t read(uint8_t* p_buf, uint32_t len) {
- if (!is_hal_2_0_enabled()) return 0;
- return hearing_aid_hal_clientinterface->ReadAudioData(p_buf, len);
- }
- // Update Hearing Aids delay report to BluetoothAudio HAL
- void set_remote_delay(uint16_t delay_report_ms) {
- if (!is_hal_2_0_enabled()) {
- LOG(INFO) << __func__ << ": not ready for DelayReport " << delay_report_ms
- << " ms";
- remote_delay_ms = delay_report_ms;
- return;
- }
- LOG(INFO) << __func__ << ": delay_report_ms=" << delay_report_ms << " ms";
- hearing_aid_sink->SetRemoteDelay(delay_report_ms);
- }
- } // namespace hearing_aid
- } // namespace audio
- } // namespace bluetooth
|