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