• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "bluetooth-asha"
20 
21 #include <base/files/file_util.h>
22 #include <bluetooth/log.h>
23 #include <stdio.h>
24 
25 #include <chrono>
26 #include <cstddef>
27 #include <cstdint>
28 #include <memory>
29 #include <ostream>
30 #include <sstream>
31 #include <vector>
32 
33 #include "audio_hal_interface/hearing_aid_software_encoding.h"
34 #include "bta/include/bta_hearing_aid_api.h"
35 #include "common/message_loop_thread.h"
36 #include "common/repeating_timer.h"
37 #include "common/time_util.h"
38 #include "hardware/bluetooth.h"
39 #include "hardware/bt_av.h"
40 #include "osi/include/wakelock.h"
41 #include "stack/include/main_thread.h"
42 
43 using namespace bluetooth;
44 
45 namespace {
46 
47 int bit_rate = -1;
48 int sample_rate = -1;
49 int data_interval_ms = -1;
50 int num_channels = 2;
51 bluetooth::common::RepeatingTimer audio_timer;
52 HearingAidAudioReceiver* localAudioReceiver = nullptr;
53 
54 struct AudioHalStats {
55   size_t media_read_total_underflow_bytes;
56   size_t media_read_total_underflow_count;
57   uint64_t media_read_last_underflow_us;
58 
AudioHalStats__anonda370f840111::AudioHalStats59   AudioHalStats() { Reset(); }
60 
Reset__anonda370f840111::AudioHalStats61   void Reset() {
62     media_read_total_underflow_bytes = 0;
63     media_read_total_underflow_count = 0;
64     media_read_last_underflow_us = 0;
65   }
66 };
67 
68 AudioHalStats stats;
69 
70 bool hearing_aid_on_resume_req(bool start_media_task);
71 bool hearing_aid_on_suspend_req();
72 
send_audio_data()73 void send_audio_data() {
74   uint32_t bytes_per_tick = (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000;
75 
76   uint8_t p_buf[bytes_per_tick];
77 
78   uint32_t bytes_read = 0;
79   if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
80     bytes_read = bluetooth::audio::hearing_aid::read(p_buf, bytes_per_tick);
81   }
82 
83   log::debug("bytes_read: {}", bytes_read);
84   if (bytes_read < bytes_per_tick) {
85     stats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
86     stats.media_read_total_underflow_count++;
87     stats.media_read_last_underflow_us = bluetooth::common::time_get_os_boottime_us();
88   }
89 
90   std::vector<uint8_t> data(p_buf, p_buf + bytes_read);
91 
92   if (localAudioReceiver != nullptr) {
93     localAudioReceiver->OnAudioDataReady(data);
94   }
95 }
96 
start_audio_ticks()97 void start_audio_ticks() {
98   if (data_interval_ms != HA_INTERVAL_10_MS && data_interval_ms != HA_INTERVAL_20_MS) {
99     log::fatal("Unsupported data interval: {}", data_interval_ms);
100   }
101 
102   wakelock_acquire();
103   audio_timer.SchedulePeriodic(get_main_thread()->GetWeakPtr(),
104                                base::BindRepeating(&send_audio_data),
105                                std::chrono::milliseconds(data_interval_ms));
106   log::info("running with data interval: {}", data_interval_ms);
107 }
108 
stop_audio_ticks()109 void stop_audio_ticks() {
110   log::info("stopped");
111   audio_timer.CancelAndWait();
112   wakelock_release();
113 }
114 
hearing_aid_on_resume_req(bool start_media_task)115 bool hearing_aid_on_resume_req(bool start_media_task) {
116   if (localAudioReceiver == nullptr) {
117     log::error("HEARING_AID_CTRL_CMD_START: audio receiver not started");
118     return false;
119   }
120   bt_status_t status;
121   if (start_media_task) {
122     status = do_in_main_thread(base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
123                                               base::Unretained(localAudioReceiver),
124                                               start_audio_ticks));
125   } else {
126     auto start_dummy_ticks = []() { log::info("start_audio_ticks: waiting for data path opened"); };
127     status = do_in_main_thread(base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
128                                               base::Unretained(localAudioReceiver),
129                                               start_dummy_ticks));
130   }
131   if (status != BT_STATUS_SUCCESS) {
132     log::error("HEARING_AID_CTRL_CMD_START: do_in_main_thread err={}", status);
133     return false;
134   }
135   return true;
136 }
137 
hearing_aid_on_suspend_req()138 bool hearing_aid_on_suspend_req() {
139   if (localAudioReceiver == nullptr) {
140     log::error("HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started");
141     return false;
142   }
143   bt_status_t status =
144           do_in_main_thread(base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
145                                            base::Unretained(localAudioReceiver), stop_audio_ticks));
146   if (status != BT_STATUS_SUCCESS) {
147     log::error("HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err={}", status);
148     return false;
149   }
150   return true;
151 }
152 }  // namespace
153 
Start(const CodecConfiguration & codecConfiguration,HearingAidAudioReceiver * audioReceiver,uint16_t remote_delay_ms)154 void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
155                                   HearingAidAudioReceiver* audioReceiver,
156                                   uint16_t remote_delay_ms) {
157   log::info("Hearing Aid Source Open");
158 
159   bit_rate = codecConfiguration.bit_rate;
160   sample_rate = codecConfiguration.sample_rate;
161   data_interval_ms = codecConfiguration.data_interval_ms;
162 
163   stats.Reset();
164 
165   if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
166     bluetooth::audio::hearing_aid::start_session();
167     bluetooth::audio::hearing_aid::set_remote_delay(remote_delay_ms);
168   }
169   localAudioReceiver = audioReceiver;
170 }
171 
Stop()172 void HearingAidAudioSource::Stop() {
173   log::info("Hearing Aid Source Close");
174 
175   localAudioReceiver = nullptr;
176   if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
177     bluetooth::audio::hearing_aid::end_session();
178   }
179 
180   stop_audio_ticks();
181 }
182 
Initialize()183 void HearingAidAudioSource::Initialize() {
184   auto stream_cb = bluetooth::audio::hearing_aid::StreamCallbacks{
185           .on_resume_ = hearing_aid_on_resume_req,
186           .on_suspend_ = hearing_aid_on_suspend_req,
187   };
188   if (!bluetooth::audio::hearing_aid::init(stream_cb, get_main_thread())) {
189     log::error("Hearing AID HAL failed to initialize");
190   }
191 }
192 
CleanUp()193 void HearingAidAudioSource::CleanUp() {
194   if (bluetooth::audio::hearing_aid::is_hal_enabled()) {
195     bluetooth::audio::hearing_aid::cleanup();
196   }
197 }
198 
DebugDump(int fd)199 void HearingAidAudioSource::DebugDump(int fd) {
200   uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
201   std::stringstream stream;
202   stream << "  Hearing Aid Audio HAL:"
203          << "\n    Counts (underflow)                                      : "
204          << stats.media_read_total_underflow_count
205          << "\n    Bytes (underflow)                                       : "
206          << stats.media_read_total_underflow_bytes
207          << "\n    Last update time ago in ms (underflow)                  : "
208          << (stats.media_read_last_underflow_us > 0
209                      ? (now_us - stats.media_read_last_underflow_us) / 1000
210                      : 0)
211          << std::endl;
212   dprintf(fd, "%s", stream.str().c_str());
213 }
214