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