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 "bta_hearing_aid_api.h"
20
21 #define LOG_TAG "bluetooth"
22
23 #include <base/functional/bind.h>
24 #include <base/functional/callback.h>
25 #include <base/logging.h>
26 #include <base/strings/string_number_conversions.h> // HexEncode
27
28 #include <chrono>
29 #include <cstdint>
30 #include <mutex>
31 #include <vector>
32
33 #include "bta/include/bta_gatt_api.h"
34 #include "bta/include/bta_gatt_queue.h"
35 #include "bta/include/bta_hearing_aid_api.h"
36 #include "btm_iso_api.h"
37 #include "common/init_flags.h"
38 #include "device/include/controller.h"
39 #include "embdrv/g722/g722_enc_dec.h"
40 #include "osi/include/compat.h"
41 #include "osi/include/log.h"
42 #include "osi/include/properties.h"
43 #include "stack/btm/btm_sec.h"
44 #include "stack/include/acl_api.h" // BTM_ReadRSSI
45 #include "stack/include/acl_api_types.h" // tBTM_RSSI_RESULT
46 #include "stack/include/bt_hdr.h"
47 #include "stack/include/bt_octets.h"
48 #include "stack/include/l2c_api.h" // L2CAP_MIN_OFFSET
49 #include "types/bluetooth/uuid.h"
50 #include "types/bt_transport.h"
51 #include "types/raw_address.h"
52
53 using base::Closure;
54 using bluetooth::Uuid;
55 using bluetooth::hci::IsoManager;
56 using bluetooth::hearing_aid::ConnectionState;
57
58 // The MIN_CE_LEN parameter for Connection Parameters based on the current
59 // Connection Interval
60 constexpr uint16_t MIN_CE_LEN_10MS_CI = 0x0006;
61 constexpr uint16_t MIN_CE_LEN_20MS_CI = 0x000C;
62 constexpr uint16_t MAX_CE_LEN_20MS_CI = 0x000C;
63 constexpr uint16_t CE_LEN_20MS_CI_ISO_RUNNING = 0x0000;
64 constexpr uint16_t CONNECTION_INTERVAL_10MS_PARAM = 0x0008;
65 constexpr uint16_t CONNECTION_INTERVAL_20MS_PARAM = 0x0010;
66
67 void btif_storage_add_hearing_aid(const HearingDevice& dev_info);
68 bool btif_storage_get_hearing_aid_prop(
69 const RawAddress& address, uint8_t* capabilities, uint64_t* hi_sync_id,
70 uint16_t* render_delay, uint16_t* preparation_delay, uint16_t* codecs);
71
72 constexpr uint8_t CODEC_G722_16KHZ = 0x01;
73 constexpr uint8_t CODEC_G722_24KHZ = 0x02;
74
75 // audio control point opcodes
76 constexpr uint8_t CONTROL_POINT_OP_START = 0x01;
77 constexpr uint8_t CONTROL_POINT_OP_STOP = 0x02;
78 constexpr uint8_t CONTROL_POINT_OP_STATE_CHANGE = 0x03;
79
80 constexpr uint8_t STATE_CHANGE_OTHER_SIDE_DISCONNECTED = 0x00;
81 constexpr uint8_t STATE_CHANGE_OTHER_SIDE_CONNECTED = 0x01;
82 constexpr uint8_t STATE_CHANGE_CONN_UPDATE = 0x02;
83
84 // used to mark current_volume as not yet known, or possibly old
85 constexpr int8_t VOLUME_UNKNOWN = 127;
86 constexpr int8_t VOLUME_MIN = -127;
87
88 // audio type
89 constexpr uint8_t AUDIOTYPE_UNKNOWN = 0x00;
90
91 // Status of the other side Hearing Aids device
92 constexpr uint8_t OTHER_SIDE_NOT_STREAMING = 0x00;
93 constexpr uint8_t OTHER_SIDE_IS_STREAMING = 0x01;
94
95 // This ADD_RENDER_DELAY_INTERVALS is the number of connection intervals when
96 // the audio data packet is send by Audio Engine to when the Hearing Aids device
97 // received it from the air. We assumed that there is 2 data buffer queued from
98 // audio subsystem to bluetooth chip. Then the estimated OTA delay is two
99 // connnection intervals.
100 constexpr uint16_t ADD_RENDER_DELAY_INTERVALS = 4;
101
102 namespace {
103
104 // clang-format off
105 Uuid HEARING_AID_UUID = Uuid::FromString("FDF0");
106 Uuid READ_ONLY_PROPERTIES_UUID = Uuid::FromString("6333651e-c481-4a3e-9169-7c902aad37bb");
107 Uuid AUDIO_CONTROL_POINT_UUID = Uuid::FromString("f0d4de7e-4a88-476c-9d9f-1937b0996cc0");
108 Uuid AUDIO_STATUS_UUID = Uuid::FromString("38663f1a-e711-4cac-b641-326b56404837");
109 Uuid VOLUME_UUID = Uuid::FromString("00e4ca9e-ab14-41e4-8823-f9e70c7e91df");
110 Uuid LE_PSM_UUID = Uuid::FromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
111 // clang-format on
112
113 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
114 void encryption_callback(const RawAddress*, tBT_TRANSPORT, void*, tBTM_STATUS);
115 void read_rssi_cb(void* p_void);
116
malloc_l2cap_buf(uint16_t len)117 inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
118 BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET +
119 len /* LE-only, no need for FCS here */);
120 msg->offset = L2CAP_MIN_OFFSET;
121 msg->len = len;
122 return msg;
123 }
124
get_l2cap_sdu_start_ptr(BT_HDR * msg)125 inline uint8_t* get_l2cap_sdu_start_ptr(BT_HDR* msg) {
126 return (uint8_t*)(msg) + BT_HDR_SIZE + L2CAP_MIN_OFFSET;
127 }
128
129 class HearingAidImpl;
130 HearingAidImpl* instance;
131 std::mutex instance_mutex;
132 HearingAidAudioReceiver* audioReceiver;
133
134 class HearingDevices {
135 public:
Add(HearingDevice device)136 void Add(HearingDevice device) {
137 if (FindByAddress(device.address) != nullptr) return;
138
139 devices.push_back(device);
140 }
141
Remove(const RawAddress & address)142 void Remove(const RawAddress& address) {
143 for (auto it = devices.begin(); it != devices.end();) {
144 if (it->address != address) {
145 ++it;
146 continue;
147 }
148
149 it = devices.erase(it);
150 return;
151 }
152 }
153
FindByAddress(const RawAddress & address)154 HearingDevice* FindByAddress(const RawAddress& address) {
155 auto iter = std::find_if(devices.begin(), devices.end(),
156 [&address](const HearingDevice& device) {
157 return device.address == address;
158 });
159
160 return (iter == devices.end()) ? nullptr : &(*iter);
161 }
162
FindByConnId(uint16_t conn_id)163 HearingDevice* FindByConnId(uint16_t conn_id) {
164 auto iter = std::find_if(devices.begin(), devices.end(),
165 [&conn_id](const HearingDevice& device) {
166 return device.conn_id == conn_id;
167 });
168
169 return (iter == devices.end()) ? nullptr : &(*iter);
170 }
171
FindByGapHandle(uint16_t gap_handle)172 HearingDevice* FindByGapHandle(uint16_t gap_handle) {
173 auto iter = std::find_if(devices.begin(), devices.end(),
174 [&gap_handle](const HearingDevice& device) {
175 return device.gap_handle == gap_handle;
176 });
177
178 return (iter == devices.end()) ? nullptr : &(*iter);
179 }
180
IsAnyConnectionUpdateStarted()181 bool IsAnyConnectionUpdateStarted() {
182 for (const auto& d : devices) {
183 if (d.connection_update_status == STARTED) return true;
184 }
185
186 return false;
187 }
188
StartRssiLog()189 void StartRssiLog() {
190 int read_rssi_start_interval_count = 0;
191
192 for (auto& d : devices) {
193 LOG_DEBUG("device=%s, read_rssi_count=%d",
194 ADDRESS_TO_LOGGABLE_CSTR(d.address), d.read_rssi_count);
195
196 // Reset the count
197 if (d.read_rssi_count <= 0) {
198 d.read_rssi_count = READ_RSSI_NUM_TRIES;
199 d.num_intervals_since_last_rssi_read = read_rssi_start_interval_count;
200
201 // Spaced apart the Read RSSI commands to the BT controller.
202 read_rssi_start_interval_count += PERIOD_TO_READ_RSSI_IN_INTERVALS / 2;
203 read_rssi_start_interval_count %= PERIOD_TO_READ_RSSI_IN_INTERVALS;
204
205 std::deque<rssi_log>& rssi_logs = d.audio_stats.rssi_history;
206 if (rssi_logs.size() >= MAX_RSSI_HISTORY) {
207 rssi_logs.pop_front();
208 }
209 rssi_logs.emplace_back();
210 }
211 }
212 }
213
size()214 size_t size() { return (devices.size()); }
215
216 std::vector<HearingDevice> devices;
217 };
218
write_rpt_ctl_cfg_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)219 static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
220 uint16_t handle, uint16_t len,
221 const uint8_t* value, void* data) {
222 if (status != GATT_SUCCESS) {
223 LOG_ERROR("handle= %hu, conn_id=%hu, status= %s, length=%u", handle,
224 conn_id, loghex(static_cast<uint8_t>(status)).c_str(), len);
225 }
226 }
227
228 g722_encode_state_t* encoder_state_left = nullptr;
229 g722_encode_state_t* encoder_state_right = nullptr;
230
encoder_state_init()231 inline void encoder_state_init() {
232 if (encoder_state_left != nullptr) {
233 LOG_WARN("encoder already initialized");
234 return;
235 }
236 encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
237 encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
238 }
239
encoder_state_release()240 inline void encoder_state_release() {
241 if (encoder_state_left != nullptr) {
242 g722_encode_release(encoder_state_left);
243 encoder_state_left = nullptr;
244 g722_encode_release(encoder_state_right);
245 encoder_state_right = nullptr;
246 }
247 }
248
249 class HearingAidImpl : public HearingAid {
250 private:
251 // Keep track of whether the Audio Service has resumed audio playback
252 bool audio_running;
253 bool is_iso_running = false;
254 // For Testing: overwrite the MIN_CE_LEN and MAX_CE_LEN during connection
255 // parameter updates
256 int16_t overwrite_min_ce_len = -1;
257 int16_t overwrite_max_ce_len = -1;
258 const std::string PERSIST_MIN_CE_LEN_NAME =
259 "persist.bluetooth.hearing_aid_min_ce_len";
260 const std::string PERSIST_MAX_CE_LEN_NAME =
261 "persist.bluetooth.hearing_aid_max_ce_len";
262 // Record whether the connection parameter needs to update to a better one
263 bool needs_parameter_update = false;
264 std::chrono::time_point<std::chrono::steady_clock> last_drop_time_point =
265 std::chrono::steady_clock::now();
266 // at most 1 packet DROP per DROP_FREQUENCY_THRESHOLD seconds
267 const int DROP_FREQUENCY_THRESHOLD =
268 bluetooth::common::init_flags::get_asha_packet_drop_frequency_threshold();
269
270 public:
271 ~HearingAidImpl() override = default;
272
HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks * callbacks,Closure initCb)273 HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
274 Closure initCb)
275 : audio_running(false),
276 overwrite_min_ce_len(-1),
277 overwrite_max_ce_len(-1),
278 gatt_if(0),
279 seq_counter(0),
280 current_volume(VOLUME_UNKNOWN),
281 callbacks(callbacks),
282 codec_in_use(0) {
283 default_data_interval_ms = (uint16_t)osi_property_get_int32(
284 "persist.bluetooth.hearingaid.interval", (int32_t)HA_INTERVAL_20_MS);
285 if ((default_data_interval_ms != HA_INTERVAL_10_MS) &&
286 (default_data_interval_ms != HA_INTERVAL_20_MS)) {
287 LOG_ERROR("invalid interval= %ums. Overwrriting back to default",
288 default_data_interval_ms);
289 default_data_interval_ms = HA_INTERVAL_20_MS;
290 }
291 LOG_DEBUG("default_data_interval_ms=%u", default_data_interval_ms);
292
293 overwrite_min_ce_len =
294 (int16_t)osi_property_get_int32(PERSIST_MIN_CE_LEN_NAME.c_str(), -1);
295 if (overwrite_min_ce_len != -1) {
296 LOG_INFO("Overwrites MIN_CE_LEN=%d", overwrite_min_ce_len);
297 }
298 overwrite_max_ce_len =
299 (int16_t)osi_property_get_int32(PERSIST_MAX_CE_LEN_NAME.c_str(), -1);
300 if (overwrite_max_ce_len != -1) {
301 LOG_INFO("Overwrites MAX_CE_LEN=%d", overwrite_max_ce_len);
302 }
303
304 BTA_GATTC_AppRegister(
305 hearingaid_gattc_callback,
306 base::Bind(
307 [](Closure initCb, uint8_t client_id, uint8_t status) {
308 if (status != GATT_SUCCESS) {
309 LOG_ERROR(
310 "Can't start Hearing Aid profile - no gatt clients left!");
311 return;
312 }
313 instance->gatt_if = client_id;
314 initCb.Run();
315 },
316 initCb),
317 false);
318
319 IsoManager::GetInstance()->Start();
320 IsoManager::GetInstance()->RegisterOnIsoTrafficActiveCallback(
321 [](bool is_active) {
322 if (!instance) {
323 return;
324 }
325 instance->IsoTrafficEventCb(is_active);
326 });
327 }
328
IsoTrafficEventCb(bool is_active)329 void IsoTrafficEventCb(bool is_active) {
330 if (is_active) {
331 is_iso_running = true;
332 needs_parameter_update = true;
333 } else {
334 is_iso_running = false;
335 }
336 LOG_INFO("is_iso_running: %d, needs_parameter_update: %d", is_iso_running,
337 needs_parameter_update);
338 if (needs_parameter_update) {
339 for (auto& device : hearingDevices.devices) {
340 if (device.conn_id != 0) {
341 device.connection_update_status = STARTED;
342 device.requested_connection_interval =
343 UpdateBleConnParams(device.address);
344 }
345 }
346 }
347 }
348
UpdateBleConnParams(const RawAddress & address)349 uint16_t UpdateBleConnParams(const RawAddress& address) {
350 /* List of parameters that depends on the chosen Connection Interval */
351 uint16_t min_ce_len = MIN_CE_LEN_20MS_CI;
352 uint16_t max_ce_len = MAX_CE_LEN_20MS_CI;
353 uint16_t connection_interval;
354
355 switch (default_data_interval_ms) {
356 case HA_INTERVAL_10_MS:
357 min_ce_len = MIN_CE_LEN_10MS_CI;
358 connection_interval = CONNECTION_INTERVAL_10MS_PARAM;
359 break;
360 case HA_INTERVAL_20_MS:
361 LOG_INFO("is_iso_running %d", is_iso_running);
362
363 // Because when ISO is connected, controller might not be able to
364 // update connection event length successfully.
365 // So if ISO is running, we use a small ce length to connect first,
366 // then update to a better value later on
367 if (is_iso_running) {
368 min_ce_len = CE_LEN_20MS_CI_ISO_RUNNING;
369 max_ce_len = CE_LEN_20MS_CI_ISO_RUNNING;
370 needs_parameter_update = true;
371 } else {
372 min_ce_len = MIN_CE_LEN_20MS_CI;
373 max_ce_len = MAX_CE_LEN_20MS_CI;
374 needs_parameter_update = false;
375 }
376 connection_interval = CONNECTION_INTERVAL_20MS_PARAM;
377 break;
378 default:
379 LOG_ERROR("invalid default_data_interval_ms=%u",
380 default_data_interval_ms);
381 min_ce_len = MIN_CE_LEN_10MS_CI;
382 connection_interval = CONNECTION_INTERVAL_10MS_PARAM;
383 }
384
385 if (overwrite_min_ce_len != -1) {
386 LOG_WARN("min_ce_len=%u for device %s is overwritten to %d", min_ce_len,
387 ADDRESS_TO_LOGGABLE_CSTR(address), overwrite_min_ce_len);
388 min_ce_len = overwrite_min_ce_len;
389 }
390 if (overwrite_max_ce_len != -1) {
391 LOG_WARN("max_ce_len=%u for device %s is overwritten to %d", max_ce_len,
392 ADDRESS_TO_LOGGABLE_CSTR(address), overwrite_max_ce_len);
393 max_ce_len = overwrite_max_ce_len;
394 }
395
396 LOG_INFO(
397 "L2CA_UpdateBleConnParams for device %s min_ce_len:%u "
398 "max_ce_len:%u",
399 ADDRESS_TO_LOGGABLE_CSTR(address), min_ce_len, max_ce_len);
400 L2CA_UpdateBleConnParams(address, connection_interval, connection_interval,
401 0x000A, 0x0064 /*1s*/, min_ce_len, max_ce_len);
402 return connection_interval;
403 }
404
IsBelowDropFrequency(std::chrono::time_point<std::chrono::steady_clock> tp)405 bool IsBelowDropFrequency(
406 std::chrono::time_point<std::chrono::steady_clock> tp) {
407 auto duration = tp - last_drop_time_point;
408 bool droppable =
409 std::chrono::duration_cast<std::chrono::seconds>(duration).count() >=
410 DROP_FREQUENCY_THRESHOLD;
411 LOG_INFO("IsBelowDropFrequency %s", droppable ? "true" : "false");
412 return droppable;
413 }
414
Connect(const RawAddress & address)415 void Connect(const RawAddress& address) {
416 LOG_DEBUG("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
417 hearingDevices.Add(HearingDevice(address, true));
418 BTA_GATTC_Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, false);
419 }
420
AddToAcceptlist(const RawAddress & address)421 void AddToAcceptlist(const RawAddress& address) {
422 LOG_DEBUG("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
423 hearingDevices.Add(HearingDevice(address, true));
424 BTA_GATTC_Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
425 }
426
AddFromStorage(const HearingDevice & dev_info,uint16_t is_acceptlisted)427 void AddFromStorage(const HearingDevice& dev_info, uint16_t is_acceptlisted) {
428 LOG_DEBUG("%s, hiSyncId=%s, isAcceptlisted=%u",
429 ADDRESS_TO_LOGGABLE_CSTR(dev_info.address),
430 loghex(dev_info.hi_sync_id).c_str(), is_acceptlisted);
431 if (is_acceptlisted) {
432 hearingDevices.Add(dev_info);
433
434 // TODO: we should increase the scanning window for few seconds, to get
435 // faster initial connection, same after hearing aid disconnects, i.e.
436 // BTM_BleSetConnScanParams(2048, 1024);
437
438 /* add device into BG connection to accept remote initiated connection */
439 BTA_GATTC_Open(gatt_if, dev_info.address, BTM_BLE_BKG_CONNECT_ALLOW_LIST,
440 false);
441 }
442
443 callbacks->OnDeviceAvailable(dev_info.capabilities, dev_info.hi_sync_id,
444 dev_info.address);
445 }
446
GetDeviceCount()447 int GetDeviceCount() { return (hearingDevices.size()); }
448
OnGattConnected(tGATT_STATUS status,uint16_t conn_id,tGATT_IF client_if,RawAddress address,tBT_TRANSPORT transport,uint16_t mtu)449 void OnGattConnected(tGATT_STATUS status, uint16_t conn_id,
450 tGATT_IF client_if, RawAddress address,
451 tBT_TRANSPORT transport, uint16_t mtu) {
452 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
453 if (!hearingDevice) {
454 /* When Hearing Aid is quickly disabled and enabled in settings, this case
455 * might happen */
456 LOG_WARN("Closing connection to non hearing-aid device, address=%s",
457 ADDRESS_TO_LOGGABLE_CSTR(address));
458 BTA_GATTC_Close(conn_id);
459 return;
460 }
461
462 LOG_INFO("address=%s, conn_id=%u", ADDRESS_TO_LOGGABLE_CSTR(address),
463 conn_id);
464
465 if (status != GATT_SUCCESS) {
466 if (!hearingDevice->connecting_actively) {
467 // acceptlist connection failed, that's ok.
468 return;
469 }
470
471 LOG_INFO("Failed to connect to Hearing Aid device");
472 hearingDevices.Remove(address);
473 callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
474 return;
475 }
476
477 hearingDevice->conn_id = conn_id;
478
479 /* We must update connection parameters one at a time, otherwise anchor
480 * point (start of connection event) for two devices can be too close to
481 * each other. Here, by setting min_ce_len=max_ce_len=X, we force controller
482 * to move anchor point of both connections away from each other, to make
483 * sure we'll be able to fit all the data we want in one connection event.
484 */
485 bool any_update_pending = hearingDevices.IsAnyConnectionUpdateStarted();
486 // mark the device as pending connection update. If we don't start the
487 // update now, it'll be started once current device finishes.
488 if (!any_update_pending) {
489 hearingDevice->connection_update_status = STARTED;
490 hearingDevice->requested_connection_interval =
491 UpdateBleConnParams(address);
492 } else {
493 hearingDevice->connection_update_status = AWAITING;
494 }
495
496 if (controller_get_interface()->supports_ble_2m_phy()) {
497 LOG_INFO("%s set preferred 2M PHY", ADDRESS_TO_LOGGABLE_CSTR(address));
498 BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
499 }
500
501 // Set data length
502 // TODO(jpawlowski: for 16khz only 87 is required, optimize
503 BTM_SetBleDataLength(address, 167);
504
505 if (BTM_SecIsSecurityPending(address)) {
506 /* if security collision happened, wait for encryption done
507 * (BTA_GATTC_ENC_CMPL_CB_EVT) */
508 return;
509 }
510
511 /* verify bond */
512 if (BTM_IsEncrypted(address, BT_TRANSPORT_LE)) {
513 /* if link has been encrypted */
514 OnEncryptionComplete(address, true);
515 return;
516 }
517
518 if (BTM_IsLinkKeyKnown(address, BT_TRANSPORT_LE)) {
519 /* if bonded and link not encrypted */
520 BTM_SetEncryption(address, BT_TRANSPORT_LE, encryption_callback, nullptr,
521 BTM_BLE_SEC_ENCRYPT);
522 return;
523 }
524
525 /* otherwise let it go through */
526 OnEncryptionComplete(address, true);
527 }
528
OnConnectionUpdateComplete(uint16_t conn_id,tBTA_GATTC * p_data)529 void OnConnectionUpdateComplete(uint16_t conn_id, tBTA_GATTC* p_data) {
530 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
531 if (!hearingDevice) {
532 LOG_DEBUG("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
533 return;
534 }
535
536 if (p_data) {
537 if (p_data->conn_update.status == 0) {
538 bool same_conn_interval =
539 (hearingDevice->requested_connection_interval ==
540 p_data->conn_update.interval);
541
542 switch (hearingDevice->connection_update_status) {
543 case COMPLETED:
544 if (!same_conn_interval) {
545 LOG_WARN(
546 "Unexpected change. Redo. connection interval=%u, "
547 "expected=%u, conn_id=%u, connection_update_status=%u",
548 p_data->conn_update.interval,
549 hearingDevice->requested_connection_interval, conn_id,
550 hearingDevice->connection_update_status);
551 // Redo this connection interval change.
552 hearingDevice->connection_update_status = AWAITING;
553 }
554 break;
555 case STARTED:
556 if (same_conn_interval) {
557 LOG_INFO("Connection update completed. conn_id=%u, device=%s",
558 conn_id,
559 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
560 hearingDevice->connection_update_status = COMPLETED;
561 } else {
562 LOG_WARN(
563 "Ignored. Different connection interval=%u, expected=%u, "
564 "conn_id=%u, connection_update_status=%u",
565 p_data->conn_update.interval,
566 hearingDevice->requested_connection_interval, conn_id,
567 hearingDevice->connection_update_status);
568 // Wait for the right Connection Update Completion.
569 return;
570 }
571 break;
572 case AWAITING:
573 case NONE:
574 break;
575 }
576
577 // Inform this side and other side device (if any) of Connection
578 // Updates.
579 std::vector<uint8_t> conn_update(
580 {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_CONN_UPDATE,
581 (uint8_t)p_data->conn_update.interval});
582 send_state_change_to_other_side(hearingDevice, conn_update);
583 send_state_change(hearingDevice, conn_update);
584 } else {
585 LOG_INFO(
586 "error status=%s, conn_id=%u,device=%s, "
587 "connection_update_status=%u",
588 loghex(static_cast<uint8_t>(p_data->conn_update.status)).c_str(),
589 conn_id, ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address),
590 hearingDevice->connection_update_status);
591 if (hearingDevice->connection_update_status == STARTED) {
592 // Redo this connection interval change.
593 LOG_ERROR("Redo Connection Interval change");
594 hearingDevice->connection_update_status = AWAITING;
595 }
596 }
597 } else {
598 hearingDevice->connection_update_status = NONE;
599 }
600
601 if (!hearingDevice->accepting_audio &&
602 hearingDevice->connection_update_status == COMPLETED &&
603 hearingDevice->gap_opened) {
604 OnDeviceReady(hearingDevice->address);
605 }
606
607 for (auto& device : hearingDevices.devices) {
608 if (device.conn_id && (device.connection_update_status == AWAITING)) {
609 device.connection_update_status = STARTED;
610 device.requested_connection_interval =
611 UpdateBleConnParams(device.address);
612 return;
613 }
614 }
615 }
616
617 // Completion Callback for the RSSI read operation.
OnReadRssiComplete(const RawAddress & address,int8_t rssi_value)618 void OnReadRssiComplete(const RawAddress& address, int8_t rssi_value) {
619 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
620 if (!hearingDevice) {
621 LOG_INFO("Skipping unknown device %s",
622 ADDRESS_TO_LOGGABLE_CSTR(address));
623 return;
624 }
625
626 LOG_DEBUG("device=%s, rss=%d", ADDRESS_TO_LOGGABLE_CSTR(address),
627 (int)rssi_value);
628
629 if (hearingDevice->read_rssi_count <= 0) {
630 LOG_ERROR(" device=%s, invalid read_rssi_count=%d",
631 ADDRESS_TO_LOGGABLE_CSTR(address),
632 hearingDevice->read_rssi_count);
633 return;
634 }
635
636 rssi_log& last_log_set = hearingDevice->audio_stats.rssi_history.back();
637
638 if (hearingDevice->read_rssi_count == READ_RSSI_NUM_TRIES) {
639 // Store the timestamp only for the first one after packet flush
640 clock_gettime(CLOCK_REALTIME, &last_log_set.timestamp);
641 LOG_INFO("store time, device=%s, rssi=%d",
642 ADDRESS_TO_LOGGABLE_CSTR(address), (int)rssi_value);
643 }
644
645 last_log_set.rssi.emplace_back(rssi_value);
646 hearingDevice->read_rssi_count--;
647 }
648
OnEncryptionComplete(const RawAddress & address,bool success)649 void OnEncryptionComplete(const RawAddress& address, bool success) {
650 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
651 if (!hearingDevice) {
652 LOG_DEBUG("Skipping unknown device %s",
653 ADDRESS_TO_LOGGABLE_CSTR(address));
654 return;
655 }
656
657 if (!success) {
658 LOG_ERROR("encryption failed");
659 BTA_GATTC_Close(hearingDevice->conn_id);
660 if (hearingDevice->first_connection) {
661 callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
662 }
663 return;
664 }
665
666 LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
667
668 if (hearingDevice->audio_control_point_handle &&
669 hearingDevice->audio_status_handle &&
670 hearingDevice->audio_status_ccc_handle &&
671 hearingDevice->volume_handle && hearingDevice->read_psm_handle) {
672 // Use cached data, jump to read PSM
673 ReadPSM(hearingDevice);
674 } else {
675 LOG_INFO("%s: do BTA_GATTC_ServiceSearchRequest",
676 ADDRESS_TO_LOGGABLE_CSTR(address));
677 hearingDevice->first_connection = true;
678 BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
679 }
680 }
681
682 // Just take care phy update successful case to avoid loop excuting.
OnPhyUpdateEvent(uint16_t conn_id,uint8_t tx_phys,uint8_t rx_phys,tGATT_STATUS status)683 void OnPhyUpdateEvent(uint16_t conn_id, uint8_t tx_phys, uint8_t rx_phys,
684 tGATT_STATUS status) {
685 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
686 if (!hearingDevice) {
687 LOG_DEBUG("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
688 return;
689 }
690 if (status != GATT_SUCCESS) {
691 LOG_WARN("%s phy update fail with status: %hu",
692 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address), status);
693 return;
694 }
695 if (tx_phys == PHY_LE_2M && rx_phys == PHY_LE_2M) {
696 LOG_INFO("%s phy update to 2M successful",
697 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
698 hearingDevice->phy_update_retry_remain = PHY_UPDATE_RETRY_LIMIT;
699 return;
700 }
701
702 if (hearingDevice->phy_update_retry_remain > 0) {
703 LOG_INFO(
704 "%s phy update successful but not target phy, try again. tx_phys: "
705 "%u,rx_phys: %u",
706 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address), tx_phys, rx_phys);
707 BTM_BleSetPhy(hearingDevice->address, PHY_LE_2M, PHY_LE_2M, 0);
708 hearingDevice->phy_update_retry_remain--;
709 } else {
710 LOG_INFO("no more phy update after %d retry", PHY_UPDATE_RETRY_LIMIT);
711 }
712 }
713
OnServiceChangeEvent(const RawAddress & address)714 void OnServiceChangeEvent(const RawAddress& address) {
715 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
716 if (!hearingDevice) {
717 LOG_DEBUG("Skipping unknown device %s",
718 ADDRESS_TO_LOGGABLE_CSTR(address));
719 return;
720 }
721 LOG_INFO("address=%s", ADDRESS_TO_LOGGABLE_CSTR(address));
722 hearingDevice->first_connection = true;
723 hearingDevice->service_changed_rcvd = true;
724 BtaGattQueue::Clean(hearingDevice->conn_id);
725 if (hearingDevice->gap_handle != GAP_INVALID_HANDLE) {
726 GAP_ConnClose(hearingDevice->gap_handle);
727 hearingDevice->gap_handle = GAP_INVALID_HANDLE;
728 }
729 }
730
OnServiceDiscDoneEvent(const RawAddress & address)731 void OnServiceDiscDoneEvent(const RawAddress& address) {
732 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
733 if (!hearingDevice) {
734 LOG_DEBUG("Skipping unknown device %s",
735 ADDRESS_TO_LOGGABLE_CSTR(address));
736 return;
737 }
738 LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
739 if (hearingDevice->service_changed_rcvd ||
740 !(hearingDevice->audio_control_point_handle &&
741 hearingDevice->audio_status_handle &&
742 hearingDevice->audio_status_ccc_handle &&
743 hearingDevice->volume_handle && hearingDevice->read_psm_handle)) {
744 LOG_INFO("%s: do BTA_GATTC_ServiceSearchRequest",
745 ADDRESS_TO_LOGGABLE_CSTR(address));
746 BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
747 }
748 }
749
OnServiceSearchComplete(uint16_t conn_id,tGATT_STATUS status)750 void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) {
751 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
752 if (!hearingDevice) {
753 LOG_DEBUG("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
754 return;
755 }
756
757 // Known device, nothing to do.
758 if (!hearingDevice->first_connection) return;
759
760 if (status != GATT_SUCCESS) {
761 /* close connection and report service discovery complete with error */
762 LOG_ERROR("Service discovery failed");
763 if (hearingDevice->first_connection) {
764 callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
765 hearingDevice->address);
766 }
767 return;
768 }
769
770 const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
771
772 const gatt::Service* service = nullptr;
773 for (const gatt::Service& tmp : *services) {
774 if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) {
775 LOG_INFO("Found UUID_SERVCLASS_GATT_SERVER, handle=%s",
776 loghex(tmp.handle).c_str());
777 const gatt::Service* service_changed_service = &tmp;
778 find_server_changed_ccc_handle(conn_id, service_changed_service);
779 } else if (tmp.uuid == HEARING_AID_UUID) {
780 LOG_INFO("Found Hearing Aid service, handle=%s",
781 loghex(tmp.handle).c_str());
782 service = &tmp;
783 }
784 }
785
786 if (!service) {
787 LOG_ERROR("No Hearing Aid service found");
788 callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
789 hearingDevice->address);
790 return;
791 }
792
793 for (const gatt::Characteristic& charac : service->characteristics) {
794 if (charac.uuid == READ_ONLY_PROPERTIES_UUID) {
795 if (!btif_storage_get_hearing_aid_prop(
796 hearingDevice->address, &hearingDevice->capabilities,
797 &hearingDevice->hi_sync_id, &hearingDevice->render_delay,
798 &hearingDevice->preparation_delay, &hearingDevice->codecs)) {
799 LOG_DEBUG("Reading read only properties %s",
800 loghex(charac.value_handle).c_str());
801 BtaGattQueue::ReadCharacteristic(
802 conn_id, charac.value_handle,
803 HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr);
804 }
805 } else if (charac.uuid == AUDIO_CONTROL_POINT_UUID) {
806 hearingDevice->audio_control_point_handle = charac.value_handle;
807 // store audio control point!
808 } else if (charac.uuid == AUDIO_STATUS_UUID) {
809 hearingDevice->audio_status_handle = charac.value_handle;
810
811 hearingDevice->audio_status_ccc_handle =
812 find_ccc_handle(conn_id, charac.value_handle);
813 if (!hearingDevice->audio_status_ccc_handle) {
814 LOG_ERROR("cannot find Audio Status CCC descriptor");
815 continue;
816 }
817
818 LOG_INFO("audio_status_handle=%s, ccc=%s",
819 loghex(charac.value_handle).c_str(),
820 loghex(hearingDevice->audio_status_ccc_handle).c_str());
821 } else if (charac.uuid == VOLUME_UUID) {
822 hearingDevice->volume_handle = charac.value_handle;
823 } else if (charac.uuid == LE_PSM_UUID) {
824 hearingDevice->read_psm_handle = charac.value_handle;
825 } else {
826 LOG_WARN("Unknown characteristic found:%s",
827 charac.uuid.ToString().c_str());
828 }
829 }
830
831 if (hearingDevice->service_changed_rcvd) {
832 hearingDevice->service_changed_rcvd = false;
833 }
834
835 ReadPSM(hearingDevice);
836 }
837
ReadPSM(HearingDevice * hearingDevice)838 void ReadPSM(HearingDevice* hearingDevice) {
839 if (hearingDevice->read_psm_handle) {
840 LOG_INFO("Reading PSM %s, device=%s",
841 loghex(hearingDevice->read_psm_handle).c_str(),
842 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
843 BtaGattQueue::ReadCharacteristic(
844 hearingDevice->conn_id, hearingDevice->read_psm_handle,
845 HearingAidImpl::OnPsmReadStatic, nullptr);
846 }
847 }
848
OnNotificationEvent(uint16_t conn_id,uint16_t handle,uint16_t len,uint8_t * value)849 void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len,
850 uint8_t* value) {
851 HearingDevice* device = hearingDevices.FindByConnId(conn_id);
852 if (!device) {
853 LOG_INFO("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
854 return;
855 }
856
857 if (device->audio_status_handle != handle) {
858 LOG_INFO("Mismatched handle, %s!=%s",
859 loghex(device->audio_status_handle).c_str(),
860 loghex(handle).c_str());
861 return;
862 }
863
864 if (len < 1) {
865 LOG_ERROR("Data Length too small, len=%u, expecting at least 1", len);
866 return;
867 }
868
869 if (value[0] != 0) {
870 LOG_INFO("Invalid returned status. data=%s", loghex(value[0]).c_str());
871 return;
872 }
873
874 LOG_INFO("audio status success notification. command_acked=%u",
875 device->command_acked);
876 device->command_acked = true;
877 }
878
OnReadOnlyPropertiesRead(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)879 void OnReadOnlyPropertiesRead(uint16_t conn_id, tGATT_STATUS status,
880 uint16_t handle, uint16_t len, uint8_t* value,
881 void* data) {
882 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
883 if (!hearingDevice) {
884 LOG_DEBUG("unknown conn_id=%s", loghex(conn_id).c_str());
885 return;
886 }
887
888 LOG_DEBUG("%s", base::HexEncode(value, len).c_str());
889
890 uint8_t* p = value;
891
892 uint8_t version;
893 STREAM_TO_UINT8(version, p);
894
895 if (version != 0x01) {
896 LOG_WARN("Unknown version: %s", loghex(version).c_str());
897 return;
898 }
899
900 // version 0x01 of read only properties:
901 if (len < 17) {
902 LOG_WARN("Read only properties too short: %s", loghex(len).c_str());
903 return;
904 }
905 uint8_t capabilities;
906 STREAM_TO_UINT8(capabilities, p);
907 hearingDevice->capabilities = capabilities;
908 bool side = capabilities & CAPABILITY_SIDE;
909 bool standalone = capabilities & CAPABILITY_BINAURAL;
910 LOG_DEBUG("capabilities: %s, %s", (side ? "right" : "left"),
911 (standalone ? "binaural" : "monaural"));
912
913 if (capabilities & CAPABILITY_RESERVED) {
914 LOG_WARN("reserved capabilities are set");
915 }
916
917 STREAM_TO_UINT64(hearingDevice->hi_sync_id, p);
918 LOG_DEBUG("hiSyncId: %s", loghex(hearingDevice->hi_sync_id).c_str());
919 uint8_t feature_map;
920 STREAM_TO_UINT8(feature_map, p);
921
922 STREAM_TO_UINT16(hearingDevice->render_delay, p);
923 LOG_DEBUG("render delay: %s", loghex(hearingDevice->render_delay).c_str());
924
925 STREAM_TO_UINT16(hearingDevice->preparation_delay, p);
926 LOG_DEBUG("preparation delay: %s",
927 loghex(hearingDevice->preparation_delay).c_str());
928
929 uint16_t codecs;
930 STREAM_TO_UINT16(codecs, p);
931 hearingDevice->codecs = codecs;
932 LOG_DEBUG("supported codecs: %s", loghex(codecs).c_str());
933 if (codecs & (1 << CODEC_G722_16KHZ)) LOG_INFO("%s\tG722@16kHz", __func__);
934 if (codecs & (1 << CODEC_G722_24KHZ)) LOG_INFO("%s\tG722@24kHz", __func__);
935
936 if (!(codecs & (1 << CODEC_G722_16KHZ))) {
937 LOG_WARN("Mandatory codec, G722@16kHz not supported");
938 }
939 }
940
CalcCompressedAudioPacketSize(uint16_t codec_type,int connection_interval)941 uint16_t CalcCompressedAudioPacketSize(uint16_t codec_type,
942 int connection_interval) {
943 int sample_rate;
944
945 const int sample_bit_rate = 16; /* 16 bits per sample */
946 const int compression_ratio = 4; /* G.722 has a 4:1 compression ratio */
947 if (codec_type == CODEC_G722_24KHZ) {
948 sample_rate = 24000;
949 } else {
950 sample_rate = 16000;
951 }
952
953 // compressed_data_packet_size is the size in bytes of the compressed audio
954 // data buffer that is generated for each connection interval.
955 uint32_t compressed_data_packet_size =
956 (sample_rate * connection_interval * (sample_bit_rate / 8) /
957 compression_ratio) /
958 1000;
959 return ((uint16_t)compressed_data_packet_size);
960 }
961
ChooseCodec(const HearingDevice & hearingDevice)962 void ChooseCodec(const HearingDevice& hearingDevice) {
963 if (codec_in_use) return;
964
965 // use the best codec available for this pair of devices.
966 uint16_t codecs = hearingDevice.codecs;
967 if (hearingDevice.hi_sync_id != 0) {
968 for (const auto& device : hearingDevices.devices) {
969 if (device.hi_sync_id != hearingDevice.hi_sync_id) continue;
970
971 codecs &= device.codecs;
972 }
973 }
974
975 if ((codecs & (1 << CODEC_G722_24KHZ)) &&
976 controller_get_interface()->supports_ble_2m_phy() &&
977 default_data_interval_ms == HA_INTERVAL_10_MS) {
978 codec_in_use = CODEC_G722_24KHZ;
979 } else if (codecs & (1 << CODEC_G722_16KHZ)) {
980 codec_in_use = CODEC_G722_16KHZ;
981 }
982 }
983
OnAudioStatus(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)984 void OnAudioStatus(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
985 uint16_t len, uint8_t* value, void* data) {
986 LOG_INFO("%s", base::HexEncode(value, len).c_str());
987 }
988
OnPsmRead(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)989 void OnPsmRead(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
990 uint16_t len, uint8_t* value, void* data) {
991 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
992 if (!hearingDevice) {
993 LOG_DEBUG("Skipping unknown read event, conn_id=%s",
994 loghex(conn_id).c_str());
995 return;
996 }
997
998 if (status != GATT_SUCCESS) {
999 LOG_ERROR("Error reading PSM for device %s",
1000 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
1001 return;
1002 }
1003
1004 if (len > 2) {
1005 LOG_ERROR("Bad PSM Lengh");
1006 return;
1007 }
1008
1009 uint16_t psm = *((uint16_t*)value);
1010 LOG_DEBUG("read psm:%s", loghex(psm).c_str());
1011
1012 if (hearingDevice->gap_handle == GAP_INVALID_HANDLE &&
1013 BTM_IsEncrypted(hearingDevice->address, BT_TRANSPORT_LE)) {
1014 ConnectSocket(hearingDevice, psm);
1015 }
1016 }
1017
ConnectSocket(HearingDevice * hearingDevice,uint16_t psm)1018 void ConnectSocket(HearingDevice* hearingDevice, uint16_t psm) {
1019 tL2CAP_CFG_INFO cfg_info = tL2CAP_CFG_INFO{.mtu = 512};
1020
1021 SendEnableServiceChangedInd(hearingDevice);
1022
1023 uint8_t service_id = hearingDevice->isLeft()
1024 ? BTM_SEC_SERVICE_HEARING_AID_LEFT
1025 : BTM_SEC_SERVICE_HEARING_AID_RIGHT;
1026 uint16_t gap_handle = GAP_ConnOpen(
1027 "", service_id, false, &hearingDevice->address, psm, 514 /* MPS */,
1028 &cfg_info, nullptr, BTM_SEC_NONE /* TODO: request security ? */,
1029 HearingAidImpl::GapCallbackStatic, BT_TRANSPORT_LE);
1030 if (gap_handle == GAP_INVALID_HANDLE) {
1031 LOG_ERROR("UNABLE TO GET gap_handle");
1032 return;
1033 }
1034
1035 hearingDevice->gap_handle = gap_handle;
1036 LOG_INFO("Successfully sent GAP connect request");
1037 }
1038
OnReadOnlyPropertiesReadStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)1039 static void OnReadOnlyPropertiesReadStatic(uint16_t conn_id,
1040 tGATT_STATUS status,
1041 uint16_t handle, uint16_t len,
1042 uint8_t* value, void* data) {
1043 if (instance)
1044 instance->OnReadOnlyPropertiesRead(conn_id, status, handle, len, value,
1045 data);
1046 }
OnAudioStatusStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)1047 static void OnAudioStatusStatic(uint16_t conn_id, tGATT_STATUS status,
1048 uint16_t handle, uint16_t len, uint8_t* value,
1049 void* data) {
1050 if (instance)
1051 instance->OnAudioStatus(conn_id, status, handle, len, value, data);
1052 }
1053
OnPsmReadStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)1054 static void OnPsmReadStatic(uint16_t conn_id, tGATT_STATUS status,
1055 uint16_t handle, uint16_t len, uint8_t* value,
1056 void* data) {
1057 if (instance)
1058 instance->OnPsmRead(conn_id, status, handle, len, value, data);
1059 }
1060
1061 /* CoC Socket, BLE connection parameter are ready */
OnDeviceReady(const RawAddress & address)1062 void OnDeviceReady(const RawAddress& address) {
1063 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
1064 if (!hearingDevice) {
1065 LOG_INFO("Device not connected to profile %s",
1066 ADDRESS_TO_LOGGABLE_CSTR(address));
1067 return;
1068 }
1069
1070 if (hearingDevice->first_connection) {
1071 btif_storage_add_hearing_aid(*hearingDevice);
1072
1073 hearingDevice->first_connection = false;
1074 }
1075
1076 LOG_INFO("audio_status_handle=%s, audio_status_ccc_handle=%s",
1077 loghex(hearingDevice->audio_status_handle).c_str(),
1078 loghex(hearingDevice->audio_status_ccc_handle).c_str());
1079
1080 /* Register and enable the Audio Status Notification */
1081 tGATT_STATUS register_status;
1082 register_status = BTA_GATTC_RegisterForNotifications(
1083 gatt_if, address, hearingDevice->audio_status_handle);
1084 if (register_status != GATT_SUCCESS) {
1085 LOG_ERROR("BTA_GATTC_RegisterForNotifications failed, status=%s",
1086 loghex(static_cast<uint8_t>(register_status)).c_str());
1087 return;
1088 }
1089 std::vector<uint8_t> value(2);
1090 uint8_t* ptr = value.data();
1091 UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
1092 BtaGattQueue::WriteDescriptor(
1093 hearingDevice->conn_id, hearingDevice->audio_status_ccc_handle,
1094 std::move(value), GATT_WRITE, write_rpt_ctl_cfg_cb, nullptr);
1095
1096 ChooseCodec(*hearingDevice);
1097
1098 SendStart(hearingDevice);
1099
1100 if (audio_running) {
1101 // Inform the other side (if any) of this connection
1102 std::vector<uint8_t> inform_conn_state(
1103 {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_CONNECTED});
1104 send_state_change_to_other_side(hearingDevice, inform_conn_state);
1105 }
1106
1107 hearingDevice->connecting_actively = false;
1108 hearingDevice->accepting_audio = true;
1109 LOG_INFO("address=%s, hi_sync_id=%s, codec_in_use=%s, audio_running=%i",
1110 ADDRESS_TO_LOGGABLE_CSTR(address),
1111 loghex(hearingDevice->hi_sync_id).c_str(),
1112 loghex(codec_in_use).c_str(), audio_running);
1113
1114 StartSendingAudio(*hearingDevice);
1115
1116 callbacks->OnDeviceAvailable(hearingDevice->capabilities,
1117 hearingDevice->hi_sync_id, address);
1118 callbacks->OnConnectionState(ConnectionState::CONNECTED, address);
1119 }
1120
StartSendingAudio(const HearingDevice & hearingDevice)1121 void StartSendingAudio(const HearingDevice& hearingDevice) {
1122 LOG_DEBUG("device=%s", ADDRESS_TO_LOGGABLE_CSTR(hearingDevice.address));
1123
1124 if (encoder_state_left == nullptr) {
1125 encoder_state_init();
1126 seq_counter = 0;
1127
1128 CodecConfiguration codec;
1129 if (codec_in_use == CODEC_G722_24KHZ) {
1130 codec.sample_rate = 24000;
1131 } else {
1132 codec.sample_rate = 16000;
1133 }
1134 codec.bit_rate = 16;
1135 codec.data_interval_ms = default_data_interval_ms;
1136
1137 uint16_t delay_report_ms = 0;
1138 if (hearingDevice.render_delay != 0) {
1139 delay_report_ms =
1140 hearingDevice.render_delay +
1141 (ADD_RENDER_DELAY_INTERVALS * default_data_interval_ms);
1142 }
1143
1144 HearingAidAudioSource::Start(codec, audioReceiver, delay_report_ms);
1145 }
1146 }
1147
OnAudioSuspend(const std::function<void ()> & stop_audio_ticks)1148 void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) {
1149 CHECK(stop_audio_ticks) << "stop_audio_ticks is empty";
1150
1151 if (!audio_running) {
1152 LOG_WARN("Unexpected audio suspend");
1153 } else {
1154 LOG_INFO("audio_running=%i", audio_running);
1155 }
1156 audio_running = false;
1157 stop_audio_ticks();
1158
1159 std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP});
1160 for (auto& device : hearingDevices.devices) {
1161 if (!device.accepting_audio) continue;
1162
1163 if (!device.playback_started) {
1164 LOG_WARN("Playback not started, skip send Stop cmd, device=%s",
1165 ADDRESS_TO_LOGGABLE_CSTR(device.address));
1166 } else {
1167 LOG_INFO("send Stop cmd, device=%s",
1168 ADDRESS_TO_LOGGABLE_CSTR(device.address));
1169 device.playback_started = false;
1170 device.command_acked = false;
1171 BtaGattQueue::WriteCharacteristic(device.conn_id,
1172 device.audio_control_point_handle,
1173 stop, GATT_WRITE, nullptr, nullptr);
1174 }
1175 }
1176 }
1177
OnAudioResume(const std::function<void ()> & start_audio_ticks)1178 void OnAudioResume(const std::function<void()>& start_audio_ticks) {
1179 CHECK(start_audio_ticks) << "start_audio_ticks is empty";
1180
1181 if (audio_running) {
1182 LOG_ERROR("Unexpected Audio Resume");
1183 } else {
1184 LOG_INFO("audio_running=%i", audio_running);
1185 }
1186
1187 for (auto& device : hearingDevices.devices) {
1188 if (!device.accepting_audio) continue;
1189 audio_running = true;
1190 SendStart(&device);
1191 }
1192
1193 if (!audio_running) {
1194 LOG_INFO("No device (0/%d) ready to start", GetDeviceCount());
1195 return;
1196 }
1197
1198 // TODO: shall we also reset the encoder ?
1199 encoder_state_release();
1200 encoder_state_init();
1201 seq_counter = 0;
1202
1203 start_audio_ticks();
1204 }
1205
GetOtherSideStreamStatus(HearingDevice * this_side_device)1206 uint8_t GetOtherSideStreamStatus(HearingDevice* this_side_device) {
1207 for (auto& device : hearingDevices.devices) {
1208 if ((device.address == this_side_device->address) ||
1209 (device.hi_sync_id != this_side_device->hi_sync_id)) {
1210 continue;
1211 }
1212 if (audio_running && (device.conn_id != 0)) {
1213 return (OTHER_SIDE_IS_STREAMING);
1214 } else {
1215 return (OTHER_SIDE_NOT_STREAMING);
1216 }
1217 }
1218 return (OTHER_SIDE_NOT_STREAMING);
1219 }
1220
SendEnableServiceChangedInd(HearingDevice * device)1221 void SendEnableServiceChangedInd(HearingDevice* device) {
1222 LOG_DEBUG("Enable service changed ind.%s",
1223 ADDRESS_TO_LOGGABLE_CSTR(device->address));
1224 std::vector<uint8_t> value(2);
1225 uint8_t* ptr = value.data();
1226 UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_INDICTION);
1227 BtaGattQueue::WriteDescriptor(
1228 device->conn_id, device->service_changed_ccc_handle, std::move(value),
1229 GATT_WRITE, nullptr, nullptr);
1230 }
1231
SendStart(HearingDevice * device)1232 void SendStart(HearingDevice* device) {
1233 std::vector<uint8_t> start({CONTROL_POINT_OP_START, codec_in_use,
1234 AUDIOTYPE_UNKNOWN, (uint8_t)current_volume,
1235 OTHER_SIDE_NOT_STREAMING});
1236
1237 if (!audio_running) {
1238 if (!device->playback_started) {
1239 LOG_INFO("Skip Send Start since audio is not running, device=%s",
1240 ADDRESS_TO_LOGGABLE_CSTR(device->address));
1241 } else {
1242 LOG_ERROR("Audio not running but Playback has started, device=%s",
1243 ADDRESS_TO_LOGGABLE_CSTR(device->address));
1244 }
1245 return;
1246 }
1247
1248 if (current_volume == VOLUME_UNKNOWN) start[3] = (uint8_t)VOLUME_MIN;
1249
1250 if (device->playback_started) {
1251 LOG_ERROR("Playback already started, skip send Start cmd, device=%s",
1252 ADDRESS_TO_LOGGABLE_CSTR(device->address));
1253 } else {
1254 start[4] = GetOtherSideStreamStatus(device);
1255 LOG_INFO(
1256 "send Start cmd, volume=%s, audio type=%s, device=%s, other side "
1257 "streaming=%s",
1258 loghex(start[3]).c_str(), loghex(start[2]).c_str(),
1259 ADDRESS_TO_LOGGABLE_CSTR(device->address),
1260 loghex(start[4]).c_str());
1261 device->command_acked = false;
1262 BtaGattQueue::WriteCharacteristic(
1263 device->conn_id, device->audio_control_point_handle, start,
1264 GATT_WRITE, HearingAidImpl::StartAudioCtrlCallbackStatic, nullptr);
1265 }
1266 }
1267
StartAudioCtrlCallbackStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)1268 static void StartAudioCtrlCallbackStatic(uint16_t conn_id,
1269 tGATT_STATUS status, uint16_t handle,
1270 uint16_t len, const uint8_t* value,
1271 void* data) {
1272 if (status != GATT_SUCCESS) {
1273 LOG_ERROR("handle=%u, conn_id=%u, status=%s", handle, conn_id,
1274 loghex(static_cast<uint8_t>(status)).c_str());
1275 return;
1276 }
1277 if (!instance) {
1278 LOG_ERROR("instance is null");
1279 return;
1280 }
1281 instance->StartAudioCtrlCallback(conn_id);
1282 }
1283
StartAudioCtrlCallback(uint16_t conn_id)1284 void StartAudioCtrlCallback(uint16_t conn_id) {
1285 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
1286 if (!hearingDevice) {
1287 LOG_ERROR("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
1288 return;
1289 }
1290 LOG_INFO("device: %s", ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
1291 hearingDevice->playback_started = true;
1292 }
1293
1294 /* Compare the two sides LE CoC credit and return true to drop two sides
1295 * packet on these situations.
1296 * 1) The credit is close
1297 * 2) Other side is disconnected
1298 * 3) Get one side current credit value failure.
1299 *
1300 * Otherwise, just flush audio packet one side.
1301 */
NeedToDropPacket(HearingDevice * target_side,HearingDevice * other_side)1302 bool NeedToDropPacket(HearingDevice* target_side, HearingDevice* other_side) {
1303 // Just drop packet if the other side does not exist.
1304 if (!other_side) {
1305 LOG_DEBUG("other side not connected to profile");
1306 return true;
1307 }
1308
1309 uint16_t diff_credit = 0;
1310
1311 uint16_t target_current_credit = L2CA_GetPeerLECocCredit(
1312 target_side->address, GAP_ConnGetL2CAPCid(target_side->gap_handle));
1313 if (target_current_credit == L2CAP_LE_CREDIT_MAX) {
1314 LOG_ERROR("Get target side credit value fail.");
1315 return true;
1316 }
1317
1318 uint16_t other_current_credit = L2CA_GetPeerLECocCredit(
1319 other_side->address, GAP_ConnGetL2CAPCid(other_side->gap_handle));
1320 if (other_current_credit == L2CAP_LE_CREDIT_MAX) {
1321 LOG_ERROR("Get other side credit value fail.");
1322 return true;
1323 }
1324
1325 if (target_current_credit > other_current_credit) {
1326 diff_credit = target_current_credit - other_current_credit;
1327 } else {
1328 diff_credit = other_current_credit - target_current_credit;
1329 }
1330 LOG_DEBUG("Target(%s) Credit: %u, Other(%s) Credit: %u, Init Credit: %u",
1331 ADDRESS_TO_LOGGABLE_CSTR(target_side->address),
1332 target_current_credit,
1333 ADDRESS_TO_LOGGABLE_CSTR(other_side->address),
1334 other_current_credit, init_credit);
1335 return diff_credit < (init_credit / 2 - 1);
1336 }
1337
OnAudioDataReady(const std::vector<uint8_t> & data)1338 void OnAudioDataReady(const std::vector<uint8_t>& data) {
1339 /* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
1340 bool need_drop = false;
1341 int num_samples =
1342 data.size() / (2 /*bytes_per_sample*/ * 2 /*number of channels*/);
1343
1344 // The G.722 codec accept only even number of samples for encoding
1345 if (num_samples % 2 != 0)
1346 LOG_ALWAYS_FATAL("num_samples is not even: %d", num_samples);
1347
1348 // TODO: we should cache left/right and current state, instad of recomputing
1349 // it for each packet, 100 times a second.
1350 HearingDevice* left = nullptr;
1351 HearingDevice* right = nullptr;
1352 for (auto& device : hearingDevices.devices) {
1353 if (!device.accepting_audio) continue;
1354
1355 if (device.isLeft())
1356 left = &device;
1357 else
1358 right = &device;
1359 }
1360
1361 if (left == nullptr && right == nullptr) {
1362 LOG_WARN("No more (0/%d) devices ready", GetDeviceCount());
1363 DoDisconnectAudioStop();
1364 return;
1365 }
1366
1367 std::vector<uint16_t> chan_left;
1368 std::vector<uint16_t> chan_right;
1369 if (left == nullptr || right == nullptr) {
1370 for (int i = 0; i < num_samples; i++) {
1371 const uint8_t* sample = data.data() + i * 4;
1372
1373 int16_t left = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
1374
1375 sample += 2;
1376 int16_t right = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
1377
1378 uint16_t mono_data = (int16_t)(((uint32_t)left + (uint32_t)right) >> 1);
1379 chan_left.push_back(mono_data);
1380 chan_right.push_back(mono_data);
1381 }
1382 } else {
1383 for (int i = 0; i < num_samples; i++) {
1384 const uint8_t* sample = data.data() + i * 4;
1385
1386 uint16_t left = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
1387 chan_left.push_back(left);
1388
1389 sample += 2;
1390 uint16_t right = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
1391 chan_right.push_back(right);
1392 }
1393 }
1394
1395 // TODO: monural, binarual check
1396
1397 // divide encoded data into packets, add header, send.
1398
1399 // TODO: make those buffers static and global to prevent constant
1400 // reallocations
1401 // TODO: this should basically fit the encoded data, tune the size later
1402 std::vector<uint8_t> encoded_data_left;
1403 auto time_point = std::chrono::steady_clock::now();
1404 if (left) {
1405 // TODO: instead of a magic number, we need to figure out the correct
1406 // buffer size
1407 encoded_data_left.resize(4000);
1408 int encoded_size =
1409 g722_encode(encoder_state_left, encoded_data_left.data(),
1410 (const int16_t*)chan_left.data(), chan_left.size());
1411 encoded_data_left.resize(encoded_size);
1412
1413 uint16_t cid = GAP_ConnGetL2CAPCid(left->gap_handle);
1414 uint16_t packets_in_chans = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
1415 if (packets_in_chans) {
1416 // Compare the two sides LE CoC credit value to confirm need to drop or
1417 // skip audio packet.
1418 if (NeedToDropPacket(left, right) && IsBelowDropFrequency(time_point)) {
1419 LOG_INFO("%s triggers dropping, %u packets in channel",
1420 ADDRESS_TO_LOGGABLE_CSTR(left->address),
1421 packets_in_chans);
1422 need_drop = true;
1423 left->audio_stats.trigger_drop_count++;
1424 } else {
1425 LOG_INFO("%s skipping %u packets",
1426 ADDRESS_TO_LOGGABLE_CSTR(left->address),
1427 packets_in_chans);
1428 left->audio_stats.packet_flush_count += packets_in_chans;
1429 left->audio_stats.frame_flush_count++;
1430 L2CA_FlushChannel(cid, 0xffff);
1431 }
1432 hearingDevices.StartRssiLog();
1433 }
1434 check_and_do_rssi_read(left);
1435 }
1436
1437 std::vector<uint8_t> encoded_data_right;
1438 if (right) {
1439 // TODO: instead of a magic number, we need to figure out the correct
1440 // buffer size
1441 encoded_data_right.resize(4000);
1442 int encoded_size =
1443 g722_encode(encoder_state_right, encoded_data_right.data(),
1444 (const int16_t*)chan_right.data(), chan_right.size());
1445 encoded_data_right.resize(encoded_size);
1446
1447 uint16_t cid = GAP_ConnGetL2CAPCid(right->gap_handle);
1448 uint16_t packets_in_chans = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
1449 if (packets_in_chans) {
1450 // Compare the two sides LE CoC credit value to confirm need to drop or
1451 // skip audio packet.
1452 if (NeedToDropPacket(right, left) && IsBelowDropFrequency(time_point)) {
1453 LOG_INFO("%s triggers dropping, %u packets in channel",
1454 ADDRESS_TO_LOGGABLE_CSTR(right->address),
1455 packets_in_chans);
1456 need_drop = true;
1457 right->audio_stats.trigger_drop_count++;
1458 } else {
1459 LOG_INFO("%s skipping %u packets",
1460 ADDRESS_TO_LOGGABLE_CSTR(right->address),
1461 packets_in_chans);
1462 right->audio_stats.packet_flush_count += packets_in_chans;
1463 right->audio_stats.frame_flush_count++;
1464 L2CA_FlushChannel(cid, 0xffff);
1465 }
1466 hearingDevices.StartRssiLog();
1467 }
1468 check_and_do_rssi_read(right);
1469 }
1470
1471 size_t encoded_data_size =
1472 std::max(encoded_data_left.size(), encoded_data_right.size());
1473
1474 uint16_t packet_size =
1475 CalcCompressedAudioPacketSize(codec_in_use, default_data_interval_ms);
1476
1477 if (need_drop) {
1478 last_drop_time_point = time_point;
1479 if (left) {
1480 left->audio_stats.packet_drop_count++;
1481 }
1482 if (right) {
1483 right->audio_stats.packet_drop_count++;
1484 }
1485 return;
1486 }
1487
1488 for (size_t i = 0; i < encoded_data_size; i += packet_size) {
1489 if (left) {
1490 left->audio_stats.packet_send_count++;
1491 SendAudio(encoded_data_left.data() + i, packet_size, left);
1492 }
1493 if (right) {
1494 right->audio_stats.packet_send_count++;
1495 SendAudio(encoded_data_right.data() + i, packet_size, right);
1496 }
1497 seq_counter++;
1498 }
1499 if (left) left->audio_stats.frame_send_count++;
1500 if (right) right->audio_stats.frame_send_count++;
1501 }
1502
SendAudio(uint8_t * encoded_data,uint16_t packet_size,HearingDevice * hearingAid)1503 void SendAudio(uint8_t* encoded_data, uint16_t packet_size,
1504 HearingDevice* hearingAid) {
1505 if (!hearingAid->playback_started || !hearingAid->command_acked) {
1506 LOG_DEBUG("Playback stalled, device=%s,cmd send=%i, cmd acked=%i",
1507 ADDRESS_TO_LOGGABLE_CSTR(hearingAid->address),
1508 hearingAid->playback_started, hearingAid->command_acked);
1509 return;
1510 }
1511
1512 BT_HDR* audio_packet = malloc_l2cap_buf(packet_size + 1);
1513 uint8_t* p = get_l2cap_sdu_start_ptr(audio_packet);
1514 *p = seq_counter;
1515 p++;
1516 memcpy(p, encoded_data, packet_size);
1517
1518 LOG_DEBUG("%s : %s", ADDRESS_TO_LOGGABLE_CSTR(hearingAid->address),
1519 base::HexEncode(p, packet_size).c_str());
1520
1521 uint16_t result = GAP_ConnWriteData(hearingAid->gap_handle, audio_packet);
1522
1523 if (result != BT_PASS) {
1524 LOG_ERROR("Error sending data: %s", loghex(result).c_str());
1525 }
1526 }
1527
GapCallback(uint16_t gap_handle,uint16_t event,tGAP_CB_DATA * data)1528 void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* data) {
1529 HearingDevice* hearingDevice = hearingDevices.FindByGapHandle(gap_handle);
1530 if (!hearingDevice) {
1531 LOG_INFO("Skipping unknown device, gap_handle=%u", gap_handle);
1532 return;
1533 }
1534
1535 switch (event) {
1536 case GAP_EVT_CONN_OPENED: {
1537 RawAddress address = *GAP_ConnGetRemoteAddr(gap_handle);
1538 uint16_t tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1539
1540 init_credit =
1541 L2CA_GetPeerLECocCredit(address, GAP_ConnGetL2CAPCid(gap_handle));
1542
1543 LOG_INFO("GAP_EVT_CONN_OPENED %s, tx_mtu=%u, init_credit=%u",
1544 ADDRESS_TO_LOGGABLE_CSTR(address), tx_mtu, init_credit);
1545
1546 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
1547 if (!hearingDevice) {
1548 LOG_INFO("Skipping unknown device %s",
1549 ADDRESS_TO_LOGGABLE_CSTR(address));
1550 return;
1551 }
1552 hearingDevice->gap_opened = true;
1553 if (hearingDevice->connection_update_status == COMPLETED) {
1554 OnDeviceReady(address);
1555 }
1556 break;
1557 }
1558
1559 case GAP_EVT_CONN_CLOSED:
1560 LOG_INFO(
1561 "GAP_EVT_CONN_CLOSED: %s, playback_started=%i, "
1562 "accepting_audio=%i",
1563 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address),
1564 hearingDevice->playback_started, hearingDevice->accepting_audio);
1565 if (!hearingDevice->accepting_audio) {
1566 /* Disconnect connection when data channel is not available */
1567 BTA_GATTC_Close(hearingDevice->conn_id);
1568 } else {
1569 /* Just clean data channel related parameter when data channel is
1570 * available */
1571 hearingDevice->gap_handle = GAP_INVALID_HANDLE;
1572 hearingDevice->accepting_audio = false;
1573 hearingDevice->playback_started = false;
1574 hearingDevice->command_acked = false;
1575 hearingDevice->gap_opened = false;
1576 }
1577 break;
1578 case GAP_EVT_CONN_DATA_AVAIL: {
1579 LOG_DEBUG("GAP_EVT_CONN_DATA_AVAIL");
1580
1581 // only data we receive back from hearing aids are some stats, not
1582 // really important, but useful now for debugging.
1583 uint32_t bytes_to_read = 0;
1584 GAP_GetRxQueueCnt(gap_handle, &bytes_to_read);
1585 std::vector<uint8_t> buffer(bytes_to_read);
1586
1587 uint16_t bytes_read = 0;
1588 // TODO:GAP_ConnReadData should accpet uint32_t for length!
1589 GAP_ConnReadData(gap_handle, buffer.data(), buffer.size(), &bytes_read);
1590
1591 if (bytes_read < 4) {
1592 LOG_WARN("Wrong data length");
1593 return;
1594 }
1595
1596 uint8_t* p = buffer.data();
1597
1598 LOG_DEBUG("stats from the hearing aid:");
1599 for (size_t i = 0; i + 4 <= buffer.size(); i += 4) {
1600 uint16_t event_counter, frame_index;
1601 STREAM_TO_UINT16(event_counter, p);
1602 STREAM_TO_UINT16(frame_index, p);
1603 LOG_DEBUG("event_counter=%u frame_index: %u", event_counter,
1604 frame_index);
1605 }
1606 break;
1607 }
1608
1609 case GAP_EVT_TX_EMPTY:
1610 LOG_DEBUG("GAP_EVT_TX_EMPTY");
1611 break;
1612 case GAP_EVT_CONN_CONGESTED:
1613 LOG_DEBUG("GAP_EVT_CONN_CONGESTED");
1614
1615 // TODO: make it into function
1616 HearingAidAudioSource::Stop();
1617 // TODO: kill the encoder only if all hearing aids are down.
1618 // g722_encode_release(encoder_state);
1619 // encoder_state_left = nulllptr;
1620 // encoder_state_right = nulllptr;
1621 break;
1622 case GAP_EVT_CONN_UNCONGESTED:
1623 LOG_DEBUG("GAP_EVT_CONN_UNCONGESTED");
1624 break;
1625 }
1626 }
1627
GapCallbackStatic(uint16_t gap_handle,uint16_t event,tGAP_CB_DATA * data)1628 static void GapCallbackStatic(uint16_t gap_handle, uint16_t event,
1629 tGAP_CB_DATA* data) {
1630 if (instance) instance->GapCallback(gap_handle, event, data);
1631 }
1632
DumpRssi(int fd,const HearingDevice & device)1633 void DumpRssi(int fd, const HearingDevice& device) {
1634 const struct AudioStats* stats = &device.audio_stats;
1635
1636 if (stats->rssi_history.size() <= 0) {
1637 dprintf(fd, " No RSSI history for %s:\n",
1638 ADDRESS_TO_LOGGABLE_CSTR(device.address));
1639 return;
1640 }
1641 dprintf(fd, " RSSI history for %s:\n",
1642 ADDRESS_TO_LOGGABLE_CSTR(device.address));
1643
1644 dprintf(fd, " Time of RSSI 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9\n");
1645 for (auto& rssi_logs : stats->rssi_history) {
1646 if (rssi_logs.rssi.size() <= 0) {
1647 break;
1648 }
1649
1650 char eventtime[20];
1651 char temptime[20];
1652 struct tm* tstamp = localtime(&rssi_logs.timestamp.tv_sec);
1653 if (!strftime(temptime, sizeof(temptime), "%H:%M:%S", tstamp)) {
1654 LOG_ERROR("strftime fails. tm_sec=%d, tm_min=%d, tm_hour=%d",
1655 tstamp->tm_sec, tstamp->tm_min, tstamp->tm_hour);
1656 strlcpy(temptime, "UNKNOWN TIME", sizeof(temptime));
1657 }
1658 snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime, rssi_logs.timestamp.tv_nsec / 1000000);
1659
1660 dprintf(fd, " %s: ", eventtime);
1661
1662 for (auto rssi_value : rssi_logs.rssi) {
1663 dprintf(fd, " %04d", rssi_value);
1664 }
1665 dprintf(fd, "\n");
1666 }
1667 }
1668
Dump(int fd)1669 void Dump(int fd) {
1670 std::stringstream stream;
1671 for (const auto& device : hearingDevices.devices) {
1672 bool side = device.capabilities & CAPABILITY_SIDE;
1673 bool standalone = device.capabilities & CAPABILITY_BINAURAL;
1674 stream << " " << device.address.ToString() << " "
1675 << (device.accepting_audio ? "" : "not ") << "connected"
1676 << "\n " << (standalone ? "binaural" : "monaural") << " "
1677 << (side ? "right" : "left") << " " << loghex(device.hi_sync_id)
1678 << std::endl;
1679 stream
1680 << " Trigger dropped counts : "
1681 << device.audio_stats.trigger_drop_count
1682 << "\n Packet dropped counts : "
1683 << device.audio_stats.packet_drop_count
1684 << "\n Packet counts (send/flush) : "
1685 << device.audio_stats.packet_send_count << " / "
1686 << device.audio_stats.packet_flush_count
1687 << "\n Frame counts (sent/flush) : "
1688 << device.audio_stats.frame_send_count << " / "
1689 << device.audio_stats.frame_flush_count << std::endl;
1690
1691 DumpRssi(fd, device);
1692 }
1693 dprintf(fd, "%s", stream.str().c_str());
1694 }
1695
Disconnect(const RawAddress & address)1696 void Disconnect(const RawAddress& address) {
1697 HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
1698 if (!hearingDevice) {
1699 LOG_INFO("Device not connected to profile %s",
1700 ADDRESS_TO_LOGGABLE_CSTR(address));
1701 return;
1702 }
1703
1704 LOG_DEBUG("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
1705
1706 bool connected = hearingDevice->accepting_audio;
1707 bool connecting_by_user = hearingDevice->connecting_actively;
1708
1709 LOG_INFO("%s, playback_started=%i, accepting_audio=%i",
1710 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address),
1711 hearingDevice->playback_started, hearingDevice->accepting_audio);
1712
1713 if (hearingDevice->connecting_actively) {
1714 // cancel pending direct connect
1715 BTA_GATTC_CancelOpen(gatt_if, address, true);
1716 }
1717
1718 // Removes all registrations for connection.
1719 BTA_GATTC_CancelOpen(0, address, false);
1720
1721 // Inform the other side (if any) of this disconnection
1722 std::vector<uint8_t> inform_disconn_state(
1723 {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_DISCONNECTED});
1724 send_state_change_to_other_side(hearingDevice, inform_disconn_state);
1725
1726 DoDisconnectCleanUp(hearingDevice);
1727
1728 if (!connected) {
1729 /* In case user wanted to connect, sent DISCONNECTED state */
1730 if (connecting_by_user) {
1731 callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
1732 }
1733 /* Do remove device when the address is useless. */
1734 hearingDevices.Remove(address);
1735 return;
1736 }
1737
1738 callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
1739 /* Do remove device when the address is useless. */
1740 hearingDevices.Remove(address);
1741 for (const auto& device : hearingDevices.devices) {
1742 if (device.accepting_audio) return;
1743 }
1744 LOG_INFO("No more (0/%d) devices ready", GetDeviceCount());
1745 DoDisconnectAudioStop();
1746 }
1747
OnGattDisconnected(uint16_t conn_id,tGATT_IF client_if,RawAddress remote_bda)1748 void OnGattDisconnected(uint16_t conn_id, tGATT_IF client_if,
1749 RawAddress remote_bda) {
1750 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
1751 if (!hearingDevice) {
1752 LOG_DEBUG("Skipping unknown device disconnect, conn_id=%s",
1753 loghex(conn_id).c_str());
1754 return;
1755 }
1756 LOG_DEBUG("conn_id=%s, remote_bda=%s", loghex(conn_id).c_str(),
1757 ADDRESS_TO_LOGGABLE_CSTR(remote_bda));
1758
1759 // Inform the other side (if any) of this disconnection
1760 std::vector<uint8_t> inform_disconn_state(
1761 {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_DISCONNECTED});
1762 send_state_change_to_other_side(hearingDevice, inform_disconn_state);
1763
1764 DoDisconnectCleanUp(hearingDevice);
1765
1766 // This is needed just for the first connection. After stack is restarted,
1767 // code that loads device will add them to acceptlist.
1768 BTA_GATTC_Open(gatt_if, hearingDevice->address,
1769 BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
1770
1771 callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda);
1772
1773 for (const auto& device : hearingDevices.devices) {
1774 if (device.accepting_audio) return;
1775 }
1776 LOG_INFO("No more (0/%d) devices ready", GetDeviceCount());
1777 DoDisconnectAudioStop();
1778 }
1779
DoDisconnectCleanUp(HearingDevice * hearingDevice)1780 void DoDisconnectCleanUp(HearingDevice* hearingDevice) {
1781 if (hearingDevice->connection_update_status != COMPLETED) {
1782 LOG_INFO("connection update not completed. Current=%u, device=%s",
1783 hearingDevice->connection_update_status,
1784 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address));
1785
1786 if (hearingDevice->connection_update_status == STARTED) {
1787 OnConnectionUpdateComplete(hearingDevice->conn_id, NULL);
1788 }
1789 }
1790 hearingDevice->connection_update_status = NONE;
1791 hearingDevice->gap_opened = false;
1792
1793 if (hearingDevice->conn_id) {
1794 BtaGattQueue::Clean(hearingDevice->conn_id);
1795 BTA_GATTC_Close(hearingDevice->conn_id);
1796 hearingDevice->conn_id = 0;
1797 }
1798
1799 if (hearingDevice->gap_handle != GAP_INVALID_HANDLE) {
1800 GAP_ConnClose(hearingDevice->gap_handle);
1801 hearingDevice->gap_handle = GAP_INVALID_HANDLE;
1802 }
1803
1804 hearingDevice->accepting_audio = false;
1805 LOG_INFO("device=%s, playback_started=%i",
1806 ADDRESS_TO_LOGGABLE_CSTR(hearingDevice->address),
1807 hearingDevice->playback_started);
1808 hearingDevice->playback_started = false;
1809 hearingDevice->command_acked = false;
1810 }
1811
DoDisconnectAudioStop()1812 void DoDisconnectAudioStop() {
1813 HearingAidAudioSource::Stop();
1814 audio_running = false;
1815 encoder_state_release();
1816 current_volume = VOLUME_UNKNOWN;
1817 }
1818
SetVolume(int8_t volume)1819 void SetVolume(int8_t volume) {
1820 LOG_DEBUG("%d", volume);
1821 current_volume = volume;
1822 for (HearingDevice& device : hearingDevices.devices) {
1823 if (!device.accepting_audio) continue;
1824
1825 std::vector<uint8_t> volume_value({static_cast<unsigned char>(volume)});
1826 BtaGattQueue::WriteCharacteristic(device.conn_id, device.volume_handle,
1827 volume_value, GATT_WRITE_NO_RSP,
1828 nullptr, nullptr);
1829 }
1830 }
1831
CleanUp()1832 void CleanUp() {
1833 BTA_GATTC_AppDeregister(gatt_if);
1834 for (HearingDevice& device : hearingDevices.devices) {
1835 DoDisconnectCleanUp(&device);
1836 }
1837
1838 hearingDevices.devices.clear();
1839
1840 encoder_state_release();
1841 }
1842
1843 private:
1844 uint8_t gatt_if;
1845 uint8_t seq_counter;
1846 /* current volume gain for the hearing aids*/
1847 int8_t current_volume;
1848 bluetooth::hearing_aid::HearingAidCallbacks* callbacks;
1849
1850 /* currently used codec */
1851 uint8_t codec_in_use;
1852
1853 uint16_t default_data_interval_ms;
1854
1855 uint16_t init_credit;
1856
1857 HearingDevices hearingDevices;
1858
find_server_changed_ccc_handle(uint16_t conn_id,const gatt::Service * service)1859 void find_server_changed_ccc_handle(uint16_t conn_id,
1860 const gatt::Service* service) {
1861 HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
1862 if (!hearingDevice) {
1863 LOG_DEBUG("Skipping unknown device, conn_id=%s", loghex(conn_id).c_str());
1864 return;
1865 }
1866 for (const gatt::Characteristic& charac : service->characteristics) {
1867 if (charac.uuid == Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) {
1868 hearingDevice->service_changed_ccc_handle =
1869 find_ccc_handle(conn_id, charac.value_handle);
1870 if (!hearingDevice->service_changed_ccc_handle) {
1871 LOG_ERROR("cannot find service changed CCC descriptor");
1872 continue;
1873 }
1874 LOG_INFO("service_changed_ccc=%s",
1875 loghex(hearingDevice->service_changed_ccc_handle).c_str());
1876 break;
1877 }
1878 }
1879 }
1880
1881 // Find the handle for the client characteristics configuration of a given
1882 // characteristics
find_ccc_handle(uint16_t conn_id,uint16_t char_handle)1883 uint16_t find_ccc_handle(uint16_t conn_id, uint16_t char_handle) {
1884 const gatt::Characteristic* p_char =
1885 BTA_GATTC_GetCharacteristic(conn_id, char_handle);
1886
1887 if (!p_char) {
1888 LOG_WARN("No such characteristic: %u", char_handle);
1889 return 0;
1890 }
1891
1892 for (const gatt::Descriptor& desc : p_char->descriptors) {
1893 if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG))
1894 return desc.handle;
1895 }
1896
1897 return 0;
1898 }
1899
send_state_change(HearingDevice * device,std::vector<uint8_t> payload)1900 void send_state_change(HearingDevice* device, std::vector<uint8_t> payload) {
1901 if (device->conn_id != 0) {
1902 if (device->service_changed_rcvd) {
1903 LOG_INFO(
1904 "service discover is in progress, skip send State Change cmd.");
1905 return;
1906 }
1907 // Send the data packet
1908 LOG_INFO("Send State Change. device=%s, status=%s",
1909 ADDRESS_TO_LOGGABLE_CSTR(device->address),
1910 loghex(payload[1]).c_str());
1911 BtaGattQueue::WriteCharacteristic(
1912 device->conn_id, device->audio_control_point_handle, payload,
1913 GATT_WRITE_NO_RSP, nullptr, nullptr);
1914 }
1915 }
1916
send_state_change_to_other_side(HearingDevice * this_side_device,std::vector<uint8_t> payload)1917 void send_state_change_to_other_side(HearingDevice* this_side_device,
1918 std::vector<uint8_t> payload) {
1919 for (auto& device : hearingDevices.devices) {
1920 if ((device.address == this_side_device->address) ||
1921 (device.hi_sync_id != this_side_device->hi_sync_id)) {
1922 continue;
1923 }
1924 send_state_change(&device, payload);
1925 }
1926 }
1927
check_and_do_rssi_read(HearingDevice * device)1928 void check_and_do_rssi_read(HearingDevice* device) {
1929 if (device->read_rssi_count > 0) {
1930 device->num_intervals_since_last_rssi_read++;
1931 if (device->num_intervals_since_last_rssi_read >= PERIOD_TO_READ_RSSI_IN_INTERVALS) {
1932 device->num_intervals_since_last_rssi_read = 0;
1933 LOG_DEBUG("device=%s", ADDRESS_TO_LOGGABLE_CSTR(device->address));
1934 BTM_ReadRSSI(device->address, read_rssi_cb);
1935 }
1936 }
1937 }
1938 };
1939
read_rssi_cb(void * p_void)1940 void read_rssi_cb(void* p_void) {
1941 tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
1942
1943 if (!p_result) return;
1944
1945 if ((instance) && (p_result->status == BTM_SUCCESS)) {
1946 instance->OnReadRssiComplete(p_result->rem_bda, p_result->rssi);
1947 }
1948 }
1949
hearingaid_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1950 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1951 LOG_DEBUG("event = %u", event);
1952
1953 if (p_data == nullptr) return;
1954
1955 switch (event) {
1956 case BTA_GATTC_DEREG_EVT:
1957 break;
1958
1959 case BTA_GATTC_OPEN_EVT: {
1960 if (!instance) return;
1961 tBTA_GATTC_OPEN& o = p_data->open;
1962 instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda,
1963 o.transport, o.mtu);
1964 break;
1965 }
1966
1967 case BTA_GATTC_CLOSE_EVT: {
1968 if (!instance) return;
1969 tBTA_GATTC_CLOSE& c = p_data->close;
1970 instance->OnGattDisconnected(c.conn_id, c.client_if, c.remote_bda);
1971 } break;
1972
1973 case BTA_GATTC_SEARCH_CMPL_EVT:
1974 if (!instance) return;
1975 instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id,
1976 p_data->search_cmpl.status);
1977 break;
1978
1979 case BTA_GATTC_NOTIF_EVT:
1980 if (!instance) return;
1981 if (!p_data->notify.is_notify || p_data->notify.len > GATT_MAX_ATTR_LEN) {
1982 LOG_ERROR("rejected BTA_GATTC_NOTIF_EVT. is_notify=%i, len=%u",
1983 p_data->notify.is_notify, p_data->notify.len);
1984 break;
1985 }
1986 instance->OnNotificationEvent(p_data->notify.conn_id,
1987 p_data->notify.handle, p_data->notify.len,
1988 p_data->notify.value);
1989 break;
1990
1991 case BTA_GATTC_ENC_CMPL_CB_EVT:
1992 if (!instance) return;
1993 instance->OnEncryptionComplete(
1994 p_data->enc_cmpl.remote_bda,
1995 BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE));
1996 break;
1997
1998 case BTA_GATTC_CONN_UPDATE_EVT:
1999 if (!instance) return;
2000 instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id, p_data);
2001 break;
2002
2003 case BTA_GATTC_SRVC_CHG_EVT:
2004 if (!instance) return;
2005 instance->OnServiceChangeEvent(p_data->remote_bda);
2006 break;
2007
2008 case BTA_GATTC_SRVC_DISC_DONE_EVT:
2009 if (!instance) return;
2010 instance->OnServiceDiscDoneEvent(p_data->service_changed.remote_bda);
2011 break;
2012 case BTA_GATTC_PHY_UPDATE_EVT: {
2013 if (!instance) return;
2014 tBTA_GATTC_PHY_UPDATE& p = p_data->phy_update;
2015 instance->OnPhyUpdateEvent(p.conn_id, p.tx_phy, p.rx_phy, p.status);
2016 break;
2017 }
2018
2019 default:
2020 break;
2021 }
2022 }
2023
encryption_callback(const RawAddress * address,tBT_TRANSPORT,void *,tBTM_STATUS status)2024 void encryption_callback(const RawAddress* address, tBT_TRANSPORT, void*,
2025 tBTM_STATUS status) {
2026 if (instance) {
2027 instance->OnEncryptionComplete(*address,
2028 status == BTM_SUCCESS ? true : false);
2029 }
2030 }
2031
2032 class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
2033 public:
OnAudioDataReady(const std::vector<uint8_t> & data)2034 void OnAudioDataReady(const std::vector<uint8_t>& data) override {
2035 if (instance) instance->OnAudioDataReady(data);
2036 }
OnAudioSuspend(const std::function<void ()> & stop_audio_ticks)2037 void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) override {
2038 if (instance) instance->OnAudioSuspend(stop_audio_ticks);
2039 }
OnAudioResume(const std::function<void ()> & start_audio_ticks)2040 void OnAudioResume(const std::function<void()>& start_audio_ticks) override {
2041 if (instance) instance->OnAudioResume(start_audio_ticks);
2042 }
2043 };
2044
2045 HearingAidAudioReceiverImpl audioReceiverImpl;
2046
2047 } // namespace
2048
Initialize(bluetooth::hearing_aid::HearingAidCallbacks * callbacks,Closure initCb)2049 void HearingAid::Initialize(
2050 bluetooth::hearing_aid::HearingAidCallbacks* callbacks, Closure initCb) {
2051 std::scoped_lock<std::mutex> lock(instance_mutex);
2052 if (instance) {
2053 LOG_ERROR("Already initialized!");
2054 return;
2055 }
2056
2057 audioReceiver = &audioReceiverImpl;
2058 instance = new HearingAidImpl(callbacks, initCb);
2059 HearingAidAudioSource::Initialize();
2060 }
2061
IsHearingAidRunning()2062 bool HearingAid::IsHearingAidRunning() { return instance; }
2063
Connect(const RawAddress & address)2064 void HearingAid::Connect(const RawAddress& address) {
2065 if (!instance) {
2066 LOG_ERROR("Hearing Aid instance is not available");
2067 return;
2068 }
2069 instance->Connect(address);
2070 }
2071
Disconnect(const RawAddress & address)2072 void HearingAid::Disconnect(const RawAddress& address) {
2073 if (!instance) {
2074 LOG_ERROR("Hearing Aid instance is not available");
2075 return;
2076 }
2077 instance->Disconnect(address);
2078 }
2079
AddToAcceptlist(const RawAddress & address)2080 void HearingAid::AddToAcceptlist(const RawAddress& address) {
2081 if (!instance) {
2082 LOG_ERROR("Hearing Aid instance is not available");
2083 return;
2084 }
2085 instance->AddToAcceptlist(address);
2086 }
2087
SetVolume(int8_t volume)2088 void HearingAid::SetVolume(int8_t volume) {
2089 if (!instance) {
2090 LOG_ERROR("Hearing Aid instance is not available");
2091 return;
2092 }
2093 instance->SetVolume(volume);
2094 }
2095
AddFromStorage(const HearingDevice & dev_info,uint16_t is_acceptlisted)2096 void HearingAid::AddFromStorage(const HearingDevice& dev_info,
2097 uint16_t is_acceptlisted) {
2098 if (!instance) {
2099 LOG_ERROR("Not initialized yet");
2100 }
2101
2102 instance->AddFromStorage(dev_info, is_acceptlisted);
2103 };
2104
GetDeviceCount()2105 int HearingAid::GetDeviceCount() {
2106 if (!instance) {
2107 LOG_INFO("Not initialized yet");
2108 return 0;
2109 }
2110
2111 return (instance->GetDeviceCount());
2112 }
2113
CleanUp()2114 void HearingAid::CleanUp() {
2115 std::scoped_lock<std::mutex> lock(instance_mutex);
2116 // Must stop audio source to make sure it doesn't call any of callbacks on our
2117 // soon to be null instance
2118 HearingAidAudioSource::Stop();
2119
2120 HearingAidImpl* ptr = instance;
2121 instance = nullptr;
2122 HearingAidAudioSource::CleanUp();
2123
2124 ptr->CleanUp();
2125
2126 delete ptr;
2127 };
2128
DebugDump(int fd)2129 void HearingAid::DebugDump(int fd) {
2130 std::scoped_lock<std::mutex> lock(instance_mutex);
2131 dprintf(fd, "Hearing Aid Manager:\n");
2132 if (instance) instance->Dump(fd);
2133 HearingAidAudioSource::DebugDump(fd);
2134 dprintf(fd, "\n");
2135 }
2136