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 #pragma once 20 21 #include <base/callback_forward.h> 22 #include <hardware/bt_hearing_aid.h> 23 #include <deque> 24 #include <vector> 25 26 constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1; 27 28 constexpr uint16_t HA_INTERVAL_10_MS = 10; 29 constexpr uint16_t HA_INTERVAL_20_MS = 20; 30 31 // Masks for checking capability support 32 constexpr uint8_t CAPABILITY_SIDE = 0x01; 33 constexpr uint8_t CAPABILITY_BINAURAL = 0x02; 34 constexpr uint8_t CAPABILITY_RESERVED = 0xFC; 35 36 /** Implementations of HearingAid will also implement this interface */ 37 class HearingAidAudioReceiver { 38 public: 39 virtual ~HearingAidAudioReceiver() = default; 40 virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0; 41 42 // API to stop our feeding timer, and notify hearing aid devices that the 43 // streaming would stop, too. 44 // 45 // @param stop_audio_ticks a callable function calls out to stop the media 46 // timer for reading data. 47 virtual void OnAudioSuspend( 48 const std::function<void()>& stop_audio_ticks) = 0; 49 50 // To notify hearing aid devices to be ready for streaming, and start the 51 // media timer to feed the audio data. 52 // 53 // @param start_audio_ticks a callable function calls out to start a periodic 54 // timer for feeding data from the audio HAL. 55 virtual void OnAudioResume( 56 const std::function<void()>& start_audio_ticks) = 0; 57 }; 58 59 // Number of rssi reads to attempt when requested 60 constexpr int READ_RSSI_NUM_TRIES = 10; 61 constexpr int PERIOD_TO_READ_RSSI_IN_INTERVALS = 5; 62 // Depth of RSSI History in DumpSys 63 constexpr int MAX_RSSI_HISTORY = 15; 64 65 struct rssi_log { 66 struct timespec timestamp; 67 std::vector<int8_t> rssi; 68 }; 69 70 struct AudioStats { 71 size_t packet_flush_count; 72 size_t packet_send_count; 73 size_t frame_flush_count; 74 size_t frame_send_count; 75 std::deque<rssi_log> rssi_history; 76 AudioStatsAudioStats77 AudioStats() { Reset(); } 78 ResetAudioStats79 void Reset() { 80 packet_flush_count = 0; 81 packet_send_count = 0; 82 frame_flush_count = 0; 83 frame_send_count = 0; 84 } 85 }; 86 87 /** Possible states for the Connection Update status */ 88 typedef enum { 89 NONE, // Not Connected 90 AWAITING, // Waiting for start the Connection Update operation 91 STARTED, // Connection Update has started 92 COMPLETED // Connection Update is completed successfully 93 } connection_update_status_t; 94 95 struct HearingDevice { 96 RawAddress address; 97 /* This is true only during first connection to profile, until we store the 98 * device */ 99 bool first_connection; 100 bool service_changed_rcvd; 101 102 /* we are making active attempt to connect to this device, 'direct connect'. 103 * This is true only during initial phase of first connection. */ 104 bool connecting_actively; 105 106 /* For two hearing aids, you must update their parameters one after another, 107 * not simulteanously, to ensure start of connection events for both devices 108 * are far from each other. This status tracks whether this device is waiting 109 * for update of parameters, that should happen after "LE Connection Update 110 * Complete" event 111 */ 112 connection_update_status_t connection_update_status; 113 uint16_t requested_connection_interval; 114 115 /* if true, we are connected, L2CAP socket is open, we can stream audio. 116 However, the actual audio stream also depends on whether the 117 Audio Service has resumed. 118 */ 119 bool accepting_audio; 120 121 uint16_t conn_id; 122 uint16_t gap_handle; 123 uint16_t audio_control_point_handle; 124 uint16_t audio_status_handle; 125 uint16_t audio_status_ccc_handle; 126 uint16_t service_changed_ccc_handle; 127 uint16_t volume_handle; 128 uint16_t read_psm_handle; 129 130 uint8_t capabilities; 131 uint64_t hi_sync_id; 132 uint16_t render_delay; 133 uint16_t preparation_delay; 134 uint16_t codecs; 135 136 AudioStats audio_stats; 137 /* Keep tracks of whether the "Start Cmd" has been send to this device. When 138 the "Stop Cmd" is send or when this device disconnects, then this flag is 139 cleared. Please note that the "Start Cmd" is not send during device 140 connection in the case when the audio is suspended. */ 141 bool playback_started; 142 /* This tracks whether the last command to Hearing Aids device is 143 * ACKnowledged. */ 144 bool command_acked; 145 146 /* When read_rssi_count is > 0, then read the rssi. The interval between rssi 147 reads is tracked by num_intervals_since_last_rssi_read. */ 148 int read_rssi_count; 149 int num_intervals_since_last_rssi_read; 150 HearingDeviceHearingDevice151 HearingDevice(const RawAddress& address, uint8_t capabilities, 152 uint16_t codecs, uint16_t audio_control_point_handle, 153 uint16_t audio_status_handle, uint16_t audio_status_ccc_handle, 154 uint16_t service_changed_ccc_handle, uint16_t volume_handle, 155 uint16_t read_psm_handle, uint64_t hiSyncId, 156 uint16_t render_delay, uint16_t preparation_delay) 157 : address(address), 158 first_connection(false), 159 service_changed_rcvd(false), 160 connecting_actively(false), 161 connection_update_status(NONE), 162 accepting_audio(false), 163 conn_id(0), 164 gap_handle(0), 165 audio_control_point_handle(audio_control_point_handle), 166 audio_status_handle(audio_status_handle), 167 audio_status_ccc_handle(audio_status_ccc_handle), 168 service_changed_ccc_handle(service_changed_ccc_handle), 169 volume_handle(volume_handle), 170 read_psm_handle(read_psm_handle), 171 capabilities(capabilities), 172 hi_sync_id(hiSyncId), 173 render_delay(render_delay), 174 preparation_delay(preparation_delay), 175 codecs(codecs), 176 playback_started(false), 177 command_acked(false), 178 read_rssi_count(0) {} 179 HearingDeviceHearingDevice180 HearingDevice(const RawAddress& address, bool first_connection) 181 : address(address), 182 first_connection(first_connection), 183 service_changed_rcvd(false), 184 connecting_actively(first_connection), 185 connection_update_status(NONE), 186 accepting_audio(false), 187 conn_id(0), 188 gap_handle(0), 189 audio_status_handle(0), 190 audio_status_ccc_handle(0), 191 service_changed_ccc_handle(0), 192 read_psm_handle(0), 193 capabilities(0), 194 hi_sync_id(0), 195 render_delay(0), 196 preparation_delay(0), 197 codecs(0), 198 playback_started(false), 199 command_acked(false), 200 read_rssi_count(0) {} 201 HearingDeviceHearingDevice202 HearingDevice() : HearingDevice(RawAddress::kEmpty, false) {} 203 204 /* return true if this device represents left Hearing Aid. Returned value is 205 * valid only after capabilities are discovered */ isLeftHearingDevice206 bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); } 207 }; 208 209 class HearingAid { 210 public: 211 virtual ~HearingAid() = default; 212 213 static void Initialize(bluetooth::hearing_aid::HearingAidCallbacks* callbacks, 214 base::Closure initCb); 215 static void CleanUp(); 216 static bool IsHearingAidRunning(); 217 static HearingAid* Get(); 218 static void DebugDump(int fd); 219 220 static void AddFromStorage(const HearingDevice& dev_info, 221 uint16_t is_white_listed); 222 223 static int GetDeviceCount(); 224 225 virtual void Connect(const RawAddress& address) = 0; 226 virtual void Disconnect(const RawAddress& address) = 0; 227 virtual void AddToWhiteList(const RawAddress& address) = 0; 228 virtual void SetVolume(int8_t volume) = 0; 229 }; 230 231 /* Represents configuration of audio codec, as exchanged between hearing aid and 232 * phone. 233 * It can also be passed to the audio source to configure its parameters. 234 */ 235 struct CodecConfiguration { 236 /** sampling rate that the codec expects to receive from audio framework */ 237 uint32_t sample_rate; 238 239 /** bitrate that codec expects to receive from audio framework in bits per 240 * channel */ 241 uint32_t bit_rate; 242 243 /** Data interval determines how often we send samples to the remote. This 244 * should match how often we grab data from audio source, optionally we can 245 * grab data every 2 or 3 intervals, but this would increase latency. 246 * 247 * Value is provided in ms, must be divisable by 1.25 to make sure the 248 * connection interval is integer. 249 */ 250 uint16_t data_interval_ms; 251 }; 252 253 /** Represents source of audio for hearing aids */ 254 class HearingAidAudioSource { 255 public: 256 static void Start(const CodecConfiguration& codecConfiguration, 257 HearingAidAudioReceiver* audioReceiver, 258 uint16_t remote_delay_ms); 259 static void Stop(); 260 static void Initialize(); 261 static void CleanUp(); 262 static void DebugDump(int fd); 263 }; 264