Home | History | Annotate | Download | only in hearing_aid
      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 
     29 #include <base/bind.h>
     30 #include <base/logging.h>
     31 #include <base/strings/string_number_conversions.h>
     32 #include <hardware/bt_hearing_aid.h>
     33 #include <vector>
     34 
     35 using base::Closure;
     36 using bluetooth::Uuid;
     37 using bluetooth::hearing_aid::ConnectionState;
     38 
     39 void btif_storage_add_hearing_aid(const RawAddress& address, uint16_t psm,
     40                                   uint8_t capabilities, uint16_t codecs,
     41                                   uint16_t audio_control_point_handle,
     42                                   uint16_t volume_handle, uint64_t hiSyncId,
     43                                   uint16_t render_delay,
     44                                   uint16_t preparation_delay);
     45 
     46 constexpr uint8_t CODEC_G722_16KHZ = 0x01;
     47 constexpr uint8_t CODEC_G722_24KHZ = 0x02;
     48 
     49 // Masks for checking capability support
     50 constexpr uint8_t CAPABILITY_SIDE = 0x01;
     51 constexpr uint8_t CAPABILITY_BINAURAL = 0x02;
     52 constexpr uint8_t CAPABILITY_RESERVED = 0xFC;
     53 
     54 // audio control point opcodes
     55 constexpr uint8_t CONTROL_POINT_OP_START = 0x01;
     56 constexpr uint8_t CONTROL_POINT_OP_STOP = 0x02;
     57 
     58 // used to mark current_volume as not yet known, or possibly old
     59 constexpr int8_t VOLUME_UNKNOWN = 127;
     60 constexpr int8_t VOLUME_MIN = -127;
     61 
     62 namespace {
     63 
     64 // clang-format off
     65 Uuid HEARING_AID_UUID          = Uuid::FromString("FDF0");
     66 Uuid READ_ONLY_PROPERTIES_UUID = Uuid::FromString("6333651e-c481-4a3e-9169-7c902aad37bb");
     67 Uuid AUDIO_CONTROL_POINT_UUID  = Uuid::FromString("f0d4de7e-4a88-476c-9d9f-1937b0996cc0");
     68 Uuid AUDIO_STATUS_UUID         = Uuid::FromString("38663f1a-e711-4cac-b641-326b56404837");
     69 Uuid VOLUME_UUID               = Uuid::FromString("00e4ca9e-ab14-41e4-8823-f9e70c7e91df");
     70 Uuid LE_PSM_UUID               = Uuid::FromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
     71 // clang-format on
     72 
     73 constexpr uint16_t MIN_CE_LEN_1M = 0x0006;
     74 
     75 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
     76 void encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*,
     77                          tBTM_STATUS);
     78 
     79 inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
     80   BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET +
     81                                     len /* LE-only, no need for FCS here */);
     82   msg->offset = L2CAP_MIN_OFFSET;
     83   msg->len = len;
     84   return msg;
     85 }
     86 
     87 inline uint8_t* get_l2cap_sdu_start_ptr(BT_HDR* msg) {
     88   return (uint8_t*)(msg) + BT_HDR_SIZE + L2CAP_MIN_OFFSET;
     89 }
     90 
     91 struct AudioStats {
     92   size_t packet_flush_count;
     93   size_t packet_send_count;
     94   size_t frame_flush_count;
     95   size_t frame_send_count;
     96 
     97   AudioStats() { Reset(); }
     98 
     99   void Reset() {
    100     packet_flush_count = 0;
    101     packet_send_count = 0;
    102     frame_flush_count = 0;
    103     frame_send_count = 0;
    104   }
    105 };
    106 
    107 class HearingAidImpl;
    108 HearingAidImpl* instance;
    109 HearingAidAudioReceiver* audioReceiver;
    110 
    111 struct HearingDevice {
    112   RawAddress address;
    113   /* This is true only during first connection to profile, until we store the
    114    * device */
    115   bool first_connection;
    116 
    117   /* we are making active attempt to connect to this device, 'direct connect'.
    118    * This is true only during initial phase of first connection. */
    119   bool connecting_actively;
    120 
    121   /* For two hearing aids, you must update their parameters one after another,
    122    * not simulteanously, to ensure start of connection events for both devices
    123    * are far from each other. This flag means that this device is waiting for
    124    * update of parameters, that should happen after "LE Connection Update
    125    * Complete" event
    126    */
    127   bool connection_update_pending;
    128 
    129   /* if true, we are connected, L2CAP socket is open, we can stream audio*/
    130   bool accepting_audio;
    131 
    132   uint16_t conn_id;
    133   uint16_t gap_handle;
    134   uint16_t audio_control_point_handle;
    135   uint16_t volume_handle;
    136   uint16_t psm;
    137 
    138   uint8_t capabilities;
    139   uint64_t hi_sync_id;
    140   uint16_t render_delay;
    141   uint16_t preparation_delay;
    142   uint16_t codecs;
    143 
    144   AudioStats audio_stats;
    145 
    146   HearingDevice(const RawAddress& address, uint16_t psm, uint8_t capabilities,
    147                 uint16_t codecs, uint16_t audio_control_point_handle,
    148                 uint16_t volume_handle, uint64_t hiSyncId,
    149                 uint16_t render_delay, uint16_t preparation_delay)
    150       : address(address),
    151         first_connection(false),
    152         connecting_actively(false),
    153         connection_update_pending(false),
    154         accepting_audio(false),
    155         conn_id(0),
    156         gap_handle(0),
    157         audio_control_point_handle(audio_control_point_handle),
    158         volume_handle(volume_handle),
    159         psm(psm),
    160         capabilities(capabilities),
    161         hi_sync_id(hiSyncId),
    162         render_delay(render_delay),
    163         preparation_delay(preparation_delay),
    164         codecs(codecs) {}
    165 
    166   HearingDevice(const RawAddress& address, bool first_connection)
    167       : address(address),
    168         first_connection(first_connection),
    169         connecting_actively(first_connection),
    170         connection_update_pending(false),
    171         accepting_audio(false),
    172         conn_id(0),
    173         gap_handle(0),
    174         psm(0) {}
    175 
    176   HearingDevice() { HearingDevice(RawAddress::kEmpty, false); }
    177 
    178   /* return true if this device represents left Hearing Aid. Returned value is
    179    * valid only after capabilities are discovered */
    180   bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); }
    181 };
    182 
    183 class HearingDevices {
    184  public:
    185   void Add(HearingDevice device) {
    186     if (FindByAddress(device.address) != nullptr) return;
    187 
    188     devices.push_back(device);
    189   }
    190 
    191   void Remove(const RawAddress& address) {
    192     for (auto it = devices.begin(); it != devices.end();) {
    193       if (it->address != address) {
    194         ++it;
    195         continue;
    196       }
    197 
    198       it = devices.erase(it);
    199       return;
    200     }
    201   }
    202 
    203   HearingDevice* FindByAddress(const RawAddress& address) {
    204     auto iter = std::find_if(devices.begin(), devices.end(),
    205                              [&address](const HearingDevice& device) {
    206                                return device.address == address;
    207                              });
    208 
    209     return (iter == devices.end()) ? nullptr : &(*iter);
    210   }
    211 
    212   HearingDevice* FindByConnId(uint16_t conn_id) {
    213     auto iter = std::find_if(devices.begin(), devices.end(),
    214                              [&conn_id](const HearingDevice& device) {
    215                                return device.conn_id == conn_id;
    216                              });
    217 
    218     return (iter == devices.end()) ? nullptr : &(*iter);
    219   }
    220 
    221   HearingDevice* FindByGapHandle(uint16_t gap_handle) {
    222     auto iter = std::find_if(devices.begin(), devices.end(),
    223                              [&gap_handle](const HearingDevice& device) {
    224                                return device.gap_handle == gap_handle;
    225                              });
    226 
    227     return (iter == devices.end()) ? nullptr : &(*iter);
    228   }
    229 
    230   bool IsAnyConnectionUpdatePending() {
    231     for (const auto& d : devices) {
    232       if (d.connection_update_pending) return true;
    233     }
    234 
    235     return false;
    236   }
    237 
    238   size_t size() { return (devices.size()); }
    239 
    240   std::vector<HearingDevice> devices;
    241 };
    242 
    243 g722_encode_state_t* encoder_state_left = nullptr;
    244 g722_encode_state_t* encoder_state_right = nullptr;
    245 
    246 class HearingAidImpl : public HearingAid {
    247  public:
    248   virtual ~HearingAidImpl() = default;
    249 
    250   HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
    251                  Closure initCb)
    252       : gatt_if(0),
    253         seq_counter(0),
    254         current_volume(VOLUME_UNKNOWN),
    255         callbacks(callbacks) {
    256     DVLOG(2) << __func__;
    257     BTA_GATTC_AppRegister(
    258         hearingaid_gattc_callback,
    259         base::Bind(
    260             [](Closure initCb, uint8_t client_id, uint8_t status) {
    261               if (status != GATT_SUCCESS) {
    262                 LOG(ERROR) << "Can't start Hearing Aid profile - no gatt "
    263                               "clients left!";
    264                 return;
    265               }
    266               instance->gatt_if = client_id;
    267               initCb.Run();
    268             },
    269             initCb));
    270   }
    271 
    272   void Connect(const RawAddress& address) override {
    273     DVLOG(2) << __func__ << " " << address;
    274     hearingDevices.Add(HearingDevice(address, true));
    275     BTA_GATTC_Open(gatt_if, address, true, GATT_TRANSPORT_LE, false);
    276   }
    277 
    278   void AddFromStorage(const RawAddress& address, uint16_t psm,
    279                       uint8_t capabilities, uint16_t codecs,
    280                       uint16_t audio_control_point_handle,
    281                       uint16_t volume_handle, uint64_t hiSyncId,
    282                       uint16_t render_delay, uint16_t preparation_delay,
    283                       uint16_t is_white_listed) {
    284     DVLOG(2) << __func__ << " " << address << ", hiSyncId=" << loghex(hiSyncId)
    285              << ", isWhiteListed=" << is_white_listed;
    286     if (is_white_listed) {
    287       hearingDevices.Add(HearingDevice(
    288           address, psm, capabilities, codecs, audio_control_point_handle,
    289           volume_handle, hiSyncId, render_delay, preparation_delay));
    290 
    291       // TODO: we should increase the scanning window for few seconds, to get
    292       // faster initial connection, same after hearing aid disconnects, i.e.
    293       // BTM_BleSetConnScanParams(2048, 1024);
    294 
    295       /* add device into BG connection to accept remote initiated connection */
    296       BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
    297       BTA_DmBleStartAutoConn();
    298     }
    299 
    300     callbacks->OnDeviceAvailable(capabilities, hiSyncId, address);
    301   }
    302 
    303   int GetDeviceCount() { return (hearingDevices.size()); }
    304 
    305   void OnGattConnected(tGATT_STATUS status, uint16_t conn_id,
    306                        tGATT_IF client_if, RawAddress address,
    307                        tBTA_TRANSPORT transport, uint16_t mtu) {
    308     VLOG(2) << __func__ << " " << address;
    309 
    310     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
    311     if (!hearingDevice) {
    312       DVLOG(2) << "Skipping unknown device, address=" << address;
    313       return;
    314     }
    315 
    316     if (status != GATT_SUCCESS) {
    317       if (!hearingDevice->connecting_actively) {
    318         // whitelist connection failed, that's ok.
    319         return;
    320       }
    321 
    322       LOG(INFO) << "Failed to connect to Hearing Aid device";
    323       hearingDevices.Remove(address);
    324       callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
    325       return;
    326     }
    327 
    328     hearingDevice->connecting_actively = false;
    329     hearingDevice->conn_id = conn_id;
    330 
    331     /* We must update connection parameters one at a time, otherwise anchor
    332      * point (start of connection event) for two devices can be too close to
    333      * each other. Here, by setting min_ce_len=max_ce_len=X, we force controller
    334      * to move anchor point of both connections away from each other, to make
    335      * sure we'll be able to fit all the data we want in one connection event.
    336      */
    337     bool any_update_pending = hearingDevices.IsAnyConnectionUpdatePending();
    338     // mark the device as pending connection update. If we don't start the
    339     // update now, it'll be started once current device finishes.
    340     hearingDevice->connection_update_pending = true;
    341     if (!any_update_pending) {
    342       L2CA_UpdateBleConnParams(address, 0x0008, 0x0008, 0x000A, 0x0064 /*1s*/,
    343                                MIN_CE_LEN_1M, MIN_CE_LEN_1M);
    344     }
    345 
    346     // Set data length
    347     // TODO(jpawlowski: for 16khz only 87 is required, optimize
    348     BTM_SetBleDataLength(address, 147);
    349 
    350     tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
    351     if (p_dev_rec) {
    352       if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
    353           p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
    354         /* if security collision happened, wait for encryption done
    355          * (BTA_GATTC_ENC_CMPL_CB_EVT) */
    356         return;
    357       }
    358     }
    359 
    360     /* verify bond */
    361     uint8_t sec_flag = 0;
    362     BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE);
    363 
    364     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) {
    365       /* if link has been encrypted */
    366       OnEncryptionComplete(address, true);
    367       return;
    368     }
    369 
    370     if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) {
    371       /* if bonded and link not encrypted */
    372       sec_flag = BTM_BLE_SEC_ENCRYPT;
    373       BTM_SetEncryption(address, BTA_TRANSPORT_LE, encryption_callback, nullptr,
    374                         sec_flag);
    375       return;
    376     }
    377 
    378     /* otherwise let it go through */
    379     OnEncryptionComplete(address, true);
    380   }
    381 
    382   void OnConnectionUpdateComplete(uint16_t conn_id) {
    383     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
    384     if (!hearingDevice) {
    385       DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
    386       return;
    387     }
    388 
    389     hearingDevice->connection_update_pending = false;
    390 
    391     for (auto& device : hearingDevices.devices) {
    392       if (device.conn_id && device.connection_update_pending) {
    393         L2CA_UpdateBleConnParams(device.address, 0x0008, 0x0008, 0x000A,
    394                                  0x0064 /*1s*/, MIN_CE_LEN_1M, MIN_CE_LEN_1M);
    395         return;
    396       }
    397     }
    398   }
    399 
    400   void OnEncryptionComplete(const RawAddress& address, bool success) {
    401     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
    402     if (!hearingDevice) {
    403       DVLOG(2) << "Skipping unknown device" << address;
    404       return;
    405     }
    406 
    407     if (!success) {
    408       LOG(ERROR) << "encryption failed";
    409       BTA_GATTC_Close(hearingDevice->conn_id);
    410       if (hearingDevice->first_connection) {
    411         callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
    412       }
    413       return;
    414     }
    415 
    416     DVLOG(2) << __func__ << " " << address;
    417 
    418     if (!hearingDevice->first_connection) {
    419       // Use cached data, jump to connecting socket
    420       ConnectSocket(hearingDevice);
    421       return;
    422     }
    423 
    424     BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
    425   }
    426 
    427   void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) {
    428     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
    429     if (!hearingDevice) {
    430       DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
    431       return;
    432     }
    433 
    434     // Known device, nothing to do.
    435     if (!hearingDevice->first_connection) return;
    436 
    437     if (status != GATT_SUCCESS) {
    438       /* close connection and report service discovery complete with error */
    439       LOG(ERROR) << "Service discovery failed";
    440       if (hearingDevice->first_connection) {
    441         callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
    442                                      hearingDevice->address);
    443       }
    444       return;
    445     }
    446 
    447     const std::vector<tBTA_GATTC_SERVICE>* services =
    448         BTA_GATTC_GetServices(conn_id);
    449 
    450     const tBTA_GATTC_SERVICE* service = nullptr;
    451     for (const tBTA_GATTC_SERVICE& tmp : *services) {
    452       if (tmp.uuid != HEARING_AID_UUID) continue;
    453       LOG(INFO) << "Found Hearing Aid service, handle=" << loghex(tmp.handle);
    454       service = &tmp;
    455       break;
    456     }
    457 
    458     if (!service) {
    459       LOG(ERROR) << "No Hearing Aid service found";
    460       callbacks->OnConnectionState(ConnectionState::DISCONNECTED,
    461                                    hearingDevice->address);
    462       return;
    463     }
    464 
    465     uint16_t psm_handle = 0x0000;
    466     for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
    467       if (charac.uuid == READ_ONLY_PROPERTIES_UUID) {
    468         DVLOG(2) << "Reading read only properties "
    469                  << loghex(charac.value_handle);
    470         BtaGattQueue::ReadCharacteristic(
    471             conn_id, charac.value_handle,
    472             HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr);
    473       } else if (charac.uuid == AUDIO_CONTROL_POINT_UUID) {
    474         hearingDevice->audio_control_point_handle = charac.value_handle;
    475         // store audio control point!
    476       } else if (charac.uuid == AUDIO_STATUS_UUID) {
    477         DVLOG(2) << "Reading Audio status " << loghex(charac.value_handle);
    478         BtaGattQueue::ReadCharacteristic(conn_id, charac.value_handle,
    479                                          HearingAidImpl::OnAudioStatusStatic,
    480                                          nullptr);
    481       } else if (charac.uuid == VOLUME_UUID) {
    482         hearingDevice->volume_handle = charac.value_handle;
    483       } else if (charac.uuid == LE_PSM_UUID) {
    484         psm_handle = charac.value_handle;
    485       } else {
    486         LOG(WARNING) << "Unknown characteristic found:" << charac.uuid;
    487       }
    488     }
    489 
    490     if (psm_handle) {
    491       DVLOG(2) << "Reading PSM " << loghex(psm_handle);
    492       BtaGattQueue::ReadCharacteristic(
    493           conn_id, psm_handle, HearingAidImpl::OnPsmReadStatic, nullptr);
    494     }
    495   }
    496 
    497   void OnReadOnlyPropertiesRead(uint16_t conn_id, tGATT_STATUS status,
    498                                 uint16_t handle, uint16_t len, uint8_t* value,
    499                                 void* data) {
    500     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
    501     if (!hearingDevice) {
    502       DVLOG(2) << __func__ << "unknown conn_id=" << loghex(conn_id);
    503       return;
    504     }
    505 
    506     VLOG(2) << __func__ << " " << base::HexEncode(value, len);
    507 
    508     uint8_t* p = value;
    509 
    510     uint8_t version;
    511     STREAM_TO_UINT8(version, p);
    512 
    513     if (version != 0x01) {
    514       LOG(WARNING) << "Unknown version: " << loghex(version);
    515       return;
    516     }
    517 
    518     // version 0x01 of read only properties:
    519     if (len < 17) {
    520       LOG(WARNING) << "Read only properties too short: " << loghex(len);
    521       return;
    522     }
    523     uint8_t capabilities;
    524     STREAM_TO_UINT8(capabilities, p);
    525     hearingDevice->capabilities = capabilities;
    526     bool side = capabilities & CAPABILITY_SIDE;
    527     bool standalone = capabilities & CAPABILITY_BINAURAL;
    528     VLOG(2) << __func__ << " capabilities: " << (side ? "right" : "left")
    529             << ", " << (standalone ? "binaural" : "monaural");
    530 
    531     if (capabilities & CAPABILITY_RESERVED) {
    532       LOG(WARNING) << __func__ << " reserved capabilities are set";
    533     }
    534 
    535     STREAM_TO_UINT64(hearingDevice->hi_sync_id, p);
    536     VLOG(2) << __func__ << " hiSyncId: " << loghex(hearingDevice->hi_sync_id);
    537     uint8_t feature_map;
    538     STREAM_TO_UINT8(feature_map, p);
    539 
    540     STREAM_TO_UINT16(hearingDevice->render_delay, p);
    541     VLOG(2) << __func__
    542             << " render delay: " << loghex(hearingDevice->render_delay);
    543 
    544     STREAM_TO_UINT16(hearingDevice->preparation_delay, p);
    545     VLOG(2) << __func__ << " preparation delay: "
    546             << loghex(hearingDevice->preparation_delay);
    547 
    548     uint16_t codecs;
    549     STREAM_TO_UINT16(codecs, p);
    550     hearingDevice->codecs = codecs;
    551     VLOG(2) << __func__ << " supported codecs: " << loghex(codecs);
    552     if (codecs & (1 << CODEC_G722_16KHZ)) VLOG(2) << "\tG722@16kHz";
    553     if (codecs & (1 << CODEC_G722_24KHZ)) VLOG(2) << "\tG722@24kHz";
    554 
    555     if (!(codecs & (1 << CODEC_G722_16KHZ))) {
    556       LOG(WARNING) << __func__ << " Mandatory codec, G722@16kHz not supported";
    557     }
    558   }
    559 
    560   void OnAudioStatus(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
    561                      uint16_t len, uint8_t* value, void* data) {
    562     DVLOG(2) << __func__ << " " << base::HexEncode(value, len);
    563   }
    564 
    565   void OnPsmRead(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
    566                  uint16_t len, uint8_t* value, void* data) {
    567     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
    568     if (!hearingDevice) {
    569       DVLOG(2) << "Skipping unknown read event, conn_id=" << loghex(conn_id);
    570       return;
    571     }
    572 
    573     if (status != GATT_SUCCESS) {
    574       LOG(ERROR) << "Error reading PSM for device" << hearingDevice->address;
    575       return;
    576     }
    577 
    578     if (len > 2) {
    579       LOG(ERROR) << "Bad PSM length";
    580       return;
    581     }
    582 
    583     uint16_t psm_val = *((uint16_t*)value);
    584     hearingDevice->psm = psm_val;
    585     VLOG(2) << "read psm:" << loghex(hearingDevice->psm);
    586 
    587     ConnectSocket(hearingDevice);
    588   }
    589 
    590   void ConnectSocket(HearingDevice* hearingDevice) {
    591     tL2CAP_CFG_INFO cfg_info = tL2CAP_CFG_INFO{.mtu = 512};
    592 
    593     uint16_t gap_handle = GAP_ConnOpen(
    594         "", 0, false, &hearingDevice->address, hearingDevice->psm,
    595         514 /* MPS */, &cfg_info, nullptr,
    596         BTM_SEC_NONE /* TODO: request security ? */, L2CAP_FCR_LE_COC_MODE,
    597         HearingAidImpl::GapCallbackStatic, BT_TRANSPORT_LE);
    598     if (gap_handle == GAP_INVALID_HANDLE) {
    599       LOG(ERROR) << "UNABLE TO GET gap_handle";
    600       return;
    601     }
    602 
    603     hearingDevice->gap_handle = gap_handle;
    604     LOG(INFO) << "Successfully sent GAP connect request";
    605   }
    606 
    607   static void OnReadOnlyPropertiesReadStatic(uint16_t conn_id,
    608                                              tGATT_STATUS status,
    609                                              uint16_t handle, uint16_t len,
    610                                              uint8_t* value, void* data) {
    611     if (instance)
    612       instance->OnReadOnlyPropertiesRead(conn_id, status, handle, len, value,
    613                                          data);
    614   }
    615   static void OnAudioStatusStatic(uint16_t conn_id, tGATT_STATUS status,
    616                                   uint16_t handle, uint16_t len, uint8_t* value,
    617                                   void* data) {
    618     if (instance)
    619       instance->OnAudioStatus(conn_id, status, handle, len, value, data);
    620   }
    621 
    622   static void OnPsmReadStatic(uint16_t conn_id, tGATT_STATUS status,
    623                               uint16_t handle, uint16_t len, uint8_t* value,
    624                               void* data) {
    625     if (instance)
    626       instance->OnPsmRead(conn_id, status, handle, len, value, data);
    627   }
    628 
    629   /* CoC Socket is ready */
    630   void OnGapConnection(const RawAddress& address) {
    631     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
    632     if (!hearingDevice) {
    633       LOG(INFO) << "Device not connected to profile" << address;
    634       return;
    635     }
    636 
    637     if (hearingDevice->first_connection) {
    638       /* add device into BG connection to accept remote initiated connection */
    639       BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
    640       BTA_DmBleStartAutoConn();
    641 
    642       btif_storage_add_hearing_aid(
    643           address, hearingDevice->psm, hearingDevice->capabilities,
    644           hearingDevice->codecs, hearingDevice->audio_control_point_handle,
    645           hearingDevice->volume_handle, hearingDevice->hi_sync_id,
    646           hearingDevice->render_delay, hearingDevice->preparation_delay);
    647 
    648       hearingDevice->first_connection = false;
    649     }
    650 
    651     SendStart(*hearingDevice);
    652 
    653     hearingDevice->accepting_audio = true;
    654     LOG(INFO) << __func__ << ": address=" << address
    655               << ", hi_sync_id=" << loghex(hearingDevice->hi_sync_id);
    656     callbacks->OnDeviceAvailable(hearingDevice->capabilities,
    657                                  hearingDevice->hi_sync_id, address);
    658     callbacks->OnConnectionState(ConnectionState::CONNECTED, address);
    659 
    660     StartSendingAudio(*hearingDevice);
    661   }
    662 
    663   void StartSendingAudio(const HearingDevice& hearingDevice) {
    664     VLOG(0) << __func__ << hearingDevice.address;
    665 
    666     if (encoder_state_left == nullptr) {
    667       encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
    668       encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
    669       seq_counter = 0;
    670 
    671       // use the best codec avaliable for this pair of devices.
    672       uint16_t codecs = hearingDevice.codecs;
    673       if (hearingDevice.hi_sync_id != 0) {
    674         for (const auto& device : hearingDevices.devices) {
    675           if (device.hi_sync_id != hearingDevice.hi_sync_id) continue;
    676 
    677           codecs &= device.codecs;
    678         }
    679       }
    680 
    681       if ((codecs & (1 << CODEC_G722_24KHZ)) &&
    682           controller_get_interface()->supports_ble_2m_phy()) {
    683         codec_in_use = CODEC_G722_24KHZ;
    684         codec.sample_rate = 24000;
    685         codec.bit_rate = 16;
    686         codec.data_interval_ms = 10;
    687       } else if (codecs & (1 << CODEC_G722_16KHZ)) {
    688         codec_in_use = CODEC_G722_16KHZ;
    689         codec.sample_rate = 16000;
    690         codec.bit_rate = 16;
    691         codec.data_interval_ms = 10;
    692       }
    693 
    694       // TODO: remove once we implement support for other codecs
    695       codec_in_use = CODEC_G722_16KHZ;
    696       HearingAidAudioSource::Start(codec, audioReceiver);
    697     }
    698   }
    699 
    700   void OnAudioSuspend() {
    701     DVLOG(2) << __func__;
    702 
    703     std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP});
    704     for (const auto& device : hearingDevices.devices) {
    705       if (!device.accepting_audio) continue;
    706 
    707       BtaGattQueue::WriteCharacteristic(device.conn_id,
    708                                         device.audio_control_point_handle, stop,
    709                                         GATT_WRITE, nullptr, nullptr);
    710     }
    711   }
    712 
    713   void OnAudioResume() {
    714     DVLOG(2) << __func__;
    715 
    716     // TODO: shall we also reset the encoder ?
    717     if (encoder_state_left != nullptr) {
    718       g722_encode_release(encoder_state_left);
    719       g722_encode_release(encoder_state_right);
    720       encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
    721       encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
    722     }
    723     seq_counter = 0;
    724 
    725     for (const auto& device : hearingDevices.devices) {
    726       if (!device.accepting_audio) continue;
    727       SendStart(device);
    728     }
    729   }
    730 
    731   void SendStart(const HearingDevice& device) {
    732     std::vector<uint8_t> start({CONTROL_POINT_OP_START, codec_in_use,
    733                                 0x02 /* media */, (uint8_t)current_volume});
    734 
    735     if (current_volume == VOLUME_UNKNOWN) start[3] = (uint8_t)VOLUME_MIN;
    736 
    737     BtaGattQueue::WriteCharacteristic(device.conn_id,
    738                                       device.audio_control_point_handle, start,
    739                                       GATT_WRITE, nullptr, nullptr);
    740 
    741     // TODO(jpawlowski): this will be removed, once test devices get volume
    742     // from start reqest
    743     if (current_volume != VOLUME_UNKNOWN) {
    744       std::vector<uint8_t> volume_value(
    745           {static_cast<unsigned char>(current_volume)});
    746       BtaGattQueue::WriteCharacteristic(device.conn_id, device.volume_handle,
    747                                         volume_value, GATT_WRITE_NO_RSP,
    748                                         nullptr, nullptr);
    749     }
    750   }
    751 
    752   void OnAudioDataReady(const std::vector<uint8_t>& data) {
    753     /* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
    754     DVLOG(2) << __func__;
    755 
    756     int num_samples =
    757         data.size() / (2 /*bytes_per_sample*/ * 2 /*number of channels*/);
    758 
    759     // The G.722 codec accept only even number of samples for encoding
    760     if (num_samples % 2 != 0)
    761       LOG(FATAL) << "num_samples is not even: " << num_samples;
    762 
    763     std::vector<uint16_t> chan_left;
    764     std::vector<uint16_t> chan_right;
    765     // TODO: encode data into G.722 left/right or mono.
    766     for (int i = 0; i < num_samples; i++) {
    767       const uint8_t* sample = data.data() + i * 4;
    768 
    769       uint16_t left = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
    770       chan_left.push_back(left);
    771 
    772       sample += 2;
    773       uint16_t right = (int16_t)((*(sample + 1) << 8) + *sample) >> 1;
    774       chan_right.push_back(right);
    775     }
    776 
    777     // TODO: we should cache left/right and current state, instad of recomputing
    778     // it for each packet, 100 times a second.
    779     HearingDevice* left = nullptr;
    780     HearingDevice* right = nullptr;
    781     for (auto& device : hearingDevices.devices) {
    782       if (!device.accepting_audio) continue;
    783 
    784       if (device.isLeft())
    785         left = &device;
    786       else
    787         right = &device;
    788     }
    789 
    790     if (left == nullptr && right == nullptr) {
    791       HearingAidAudioSource::Stop();
    792       current_volume = VOLUME_UNKNOWN;
    793       return;
    794     }
    795 
    796     // TODO: monural, binarual check
    797 
    798     // divide encoded data into packets, add header, send.
    799 
    800     // TODO: make those buffers static and global to prevent constant
    801     // reallocations
    802     // TODO: this should basically fit the encoded data, tune the size later
    803     std::vector<uint8_t> encoded_data_left;
    804     if (left) {
    805       encoded_data_left.resize(2000);
    806       int encoded_size =
    807           g722_encode(encoder_state_left, encoded_data_left.data(),
    808                       (const int16_t*)chan_left.data(), chan_left.size());
    809       encoded_data_left.resize(encoded_size);
    810 
    811       uint16_t cid = GAP_ConnGetL2CAPCid(left->gap_handle);
    812       uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
    813       if (packets_to_flush) {
    814         VLOG(2) << left->address << " skipping " << packets_to_flush
    815                 << " packets";
    816         left->audio_stats.packet_flush_count += packets_to_flush;
    817         left->audio_stats.frame_flush_count++;
    818       }
    819       // flush all packets stuck in queue
    820       L2CA_FlushChannel(cid, 0xffff);
    821     }
    822 
    823     std::vector<uint8_t> encoded_data_right;
    824     if (right) {
    825       encoded_data_right.resize(2000);
    826       int encoded_size =
    827           g722_encode(encoder_state_right, encoded_data_right.data(),
    828                       (const int16_t*)chan_right.data(), chan_right.size());
    829       encoded_data_right.resize(encoded_size);
    830 
    831       uint16_t cid = GAP_ConnGetL2CAPCid(right->gap_handle);
    832       uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
    833       if (packets_to_flush) {
    834         VLOG(2) << right->address << " skipping " << packets_to_flush
    835                 << " packets";
    836         right->audio_stats.packet_flush_count += packets_to_flush;
    837         right->audio_stats.frame_flush_count++;
    838       }
    839       // flush all packets stuck in queue
    840       L2CA_FlushChannel(cid, 0xffff);
    841     }
    842 
    843     size_t encoded_data_size =
    844         std::max(encoded_data_left.size(), encoded_data_right.size());
    845 
    846     // TODO: make it also dependent on the interval, when we support intervals
    847     // different than 10ms
    848     uint16_t packet_size;
    849 
    850     if (codec_in_use == CODEC_G722_24KHZ) {
    851       packet_size = 120;
    852     } else /* if (codec_in_use == CODEC_G722_16KHZ) */ {
    853       packet_size = 80;
    854     }
    855 
    856     for (size_t i = 0; i < encoded_data_size; i += packet_size) {
    857       if (left) {
    858         left->audio_stats.packet_send_count++;
    859         SendAudio(encoded_data_left.data() + i, packet_size, left);
    860       }
    861       if (right) {
    862         right->audio_stats.packet_send_count++;
    863         SendAudio(encoded_data_right.data() + i, packet_size, right);
    864       }
    865       seq_counter++;
    866     }
    867     if (left) left->audio_stats.frame_send_count++;
    868     if (right) right->audio_stats.frame_send_count++;
    869   }
    870 
    871   void SendAudio(uint8_t* encoded_data, uint16_t packet_size,
    872                  HearingDevice* hearingAid) {
    873     BT_HDR* audio_packet = malloc_l2cap_buf(packet_size + 1);
    874     uint8_t* p = get_l2cap_sdu_start_ptr(audio_packet);
    875     *p = seq_counter;
    876     p++;
    877     memcpy(p, encoded_data, packet_size);
    878 
    879     DVLOG(2) << hearingAid->address << " : " << base::HexEncode(p, packet_size);
    880 
    881     uint16_t result = GAP_ConnWriteData(hearingAid->gap_handle, audio_packet);
    882 
    883     if (result != BT_PASS) {
    884       LOG(ERROR) << " Error sending data: " << loghex(result);
    885     }
    886   }
    887 
    888   void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* data) {
    889     HearingDevice* hearingDevice = hearingDevices.FindByGapHandle(gap_handle);
    890     if (!hearingDevice) {
    891       DVLOG(2) << "Skipping unknown device, gap_handle=" << gap_handle;
    892       return;
    893     }
    894 
    895     switch (event) {
    896       case GAP_EVT_CONN_OPENED: {
    897         RawAddress address = *GAP_ConnGetRemoteAddr(gap_handle);
    898         uint16_t tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
    899 
    900         LOG(INFO) << "GAP_EVT_CONN_OPENED " << address << ", tx_mtu=" << tx_mtu;
    901         OnGapConnection(address);
    902         break;
    903       }
    904 
    905       // TODO: handle properly!
    906       case GAP_EVT_CONN_CLOSED:
    907         DVLOG(2) << "GAP_EVT_CONN_CLOSED";
    908         hearingDevice->accepting_audio = false;
    909         hearingDevice->gap_handle = 0;
    910         break;
    911       case GAP_EVT_CONN_DATA_AVAIL: {
    912         DVLOG(2) << "GAP_EVT_CONN_DATA_AVAIL";
    913 
    914         // only data we receive back from hearing aids are some stats, not
    915         // really important, but useful now for debugging.
    916         uint32_t bytes_to_read = 0;
    917         GAP_GetRxQueueCnt(gap_handle, &bytes_to_read);
    918         std::vector<uint8_t> buffer(bytes_to_read);
    919 
    920         uint16_t bytes_read = 0;
    921         // TODO:GAP_ConnReadData should accpet uint32_t for length!
    922         GAP_ConnReadData(gap_handle, buffer.data(), buffer.size(), &bytes_read);
    923 
    924         if (bytes_read < 4) {
    925           LOG(WARNING) << " Wrong data length";
    926           return;
    927         }
    928 
    929         uint8_t* p = buffer.data();
    930 
    931         DVLOG(1) << "stats from the hearing aid:";
    932         for (size_t i = 0; i + 4 <= buffer.size(); i += 4) {
    933           uint16_t event_counter, frame_index;
    934           STREAM_TO_UINT16(event_counter, p);
    935           STREAM_TO_UINT16(frame_index, p);
    936           DVLOG(1) << "event_counter=" << event_counter
    937                    << " frame_index: " << frame_index;
    938         }
    939         break;
    940       }
    941 
    942       case GAP_EVT_TX_EMPTY:
    943         DVLOG(2) << "GAP_EVT_TX_EMPTY";
    944         break;
    945       case GAP_EVT_CONN_CONGESTED:
    946         DVLOG(2) << "GAP_EVT_CONN_CONGESTED";
    947 
    948         // TODO: make it into function
    949         HearingAidAudioSource::Stop();
    950         // TODO: kill the encoder only if all hearing aids are down.
    951         // g722_encode_release(encoder_state);
    952         // encoder_state_left = nulllptr;
    953         // encoder_state_right = nulllptr;
    954         break;
    955       case GAP_EVT_CONN_UNCONGESTED:
    956         DVLOG(2) << "GAP_EVT_CONN_UNCONGESTED";
    957         break;
    958 
    959       case GAP_EVT_LE_COC_CREDITS: {
    960         auto& tmp = data->coc_credits;
    961         DVLOG(2) << "GAP_EVT_LE_COC_CREDITS, for device: "
    962                  << hearingDevice->address << " added" << tmp.credits_received
    963                  << " credit_count: " << tmp.credit_count;
    964         break;
    965       }
    966     }
    967   }
    968 
    969   static void GapCallbackStatic(uint16_t gap_handle, uint16_t event,
    970                                 tGAP_CB_DATA* data) {
    971     if (instance) instance->GapCallback(gap_handle, event, data);
    972   }
    973 
    974   void Dump(int fd) {
    975     std::stringstream stream;
    976     for (const auto& device : hearingDevices.devices) {
    977       bool side = device.capabilities & CAPABILITY_SIDE;
    978       bool standalone = device.capabilities & CAPABILITY_BINAURAL;
    979       stream << "  " << device.address.ToString() << " "
    980              << (device.accepting_audio ? "" : "not ") << "connected"
    981              << "\n    " << (standalone ? "binaural" : "monaural") << " "
    982              << (side ? "right" : "left") << " " << loghex(device.hi_sync_id)
    983              << std::endl;
    984       stream
    985           << "    Packet counts (enqueued/flushed)                        : "
    986           << device.audio_stats.packet_send_count << " / "
    987           << device.audio_stats.packet_flush_count
    988           << "\n    Frame counts (enqueued/flushed)                         : "
    989           << device.audio_stats.frame_send_count << " / "
    990           << device.audio_stats.frame_flush_count << std::endl;
    991     }
    992     dprintf(fd, "%s", stream.str().c_str());
    993   }
    994 
    995   void Disconnect(const RawAddress& address) override {
    996     DVLOG(2) << __func__;
    997     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
    998     if (!hearingDevice) {
    999       LOG(INFO) << "Device not connected to profile" << address;
   1000       return;
   1001     }
   1002 
   1003     VLOG(2) << __func__ << ": " << address;
   1004 
   1005     bool connected = hearingDevice->accepting_audio;
   1006     hearingDevice->accepting_audio = false;
   1007 
   1008     if (hearingDevice->connecting_actively) {
   1009       // cancel pending direct connect
   1010       BTA_GATTC_CancelOpen(gatt_if, address, true);
   1011     }
   1012 
   1013     if (hearingDevice->conn_id) {
   1014       BTA_GATTC_Close(hearingDevice->conn_id);
   1015     }
   1016 
   1017     if (hearingDevice->gap_handle) {
   1018       GAP_ConnClose(hearingDevice->gap_handle);
   1019       hearingDevice->gap_handle = 0;
   1020     }
   1021 
   1022     // cancel autoconnect
   1023     BTA_GATTC_CancelOpen(gatt_if, address, false);
   1024 
   1025     hearingDevices.Remove(address);
   1026 
   1027     if (connected)
   1028       callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address);
   1029   }
   1030 
   1031   void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id,
   1032                           tGATT_IF client_if, RawAddress remote_bda,
   1033                           tBTA_GATT_REASON reason) {
   1034     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
   1035     if (!hearingDevice) {
   1036       VLOG(2) << "Skipping unknown device disconnect, conn_id=" << conn_id;
   1037       return;
   1038     }
   1039 
   1040     hearingDevice->accepting_audio = false;
   1041     hearingDevice->conn_id = 0;
   1042 
   1043     BtaGattQueue::Clean(conn_id);
   1044 
   1045     callbacks->OnConnectionState(ConnectionState::DISCONNECTED, remote_bda);
   1046   }
   1047 
   1048   void SetVolume(int8_t volume) override {
   1049     VLOG(2) << __func__ << ": " << +volume;
   1050     current_volume = volume;
   1051     for (HearingDevice& device : hearingDevices.devices) {
   1052       if (!device.accepting_audio) continue;
   1053 
   1054       std::vector<uint8_t> volume_value({static_cast<unsigned char>(volume)});
   1055       BtaGattQueue::WriteCharacteristic(device.conn_id, device.volume_handle,
   1056                                         volume_value, GATT_WRITE_NO_RSP,
   1057                                         nullptr, nullptr);
   1058     }
   1059   }
   1060 
   1061   void CleanUp() {
   1062     BTA_GATTC_AppDeregister(gatt_if);
   1063     for (HearingDevice& device : hearingDevices.devices) {
   1064       if (!device.gap_handle) continue;
   1065 
   1066       GAP_ConnClose(device.gap_handle);
   1067       device.gap_handle = 0;
   1068     }
   1069 
   1070     hearingDevices.devices.clear();
   1071     HearingAidAudioSource::Stop();
   1072   }
   1073 
   1074  private:
   1075   uint8_t gatt_if;
   1076   uint8_t seq_counter;
   1077   /* current volume gain for the hearing aids*/
   1078   int8_t current_volume;
   1079   bluetooth::hearing_aid::HearingAidCallbacks* callbacks;
   1080 
   1081   /* currently used codec */
   1082   uint8_t codec_in_use;
   1083   CodecConfiguration codec;
   1084 
   1085   HearingDevices hearingDevices;
   1086 };
   1087 
   1088 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
   1089   VLOG(2) << __func__ << " event = " << +event;
   1090 
   1091   if (p_data == nullptr) return;
   1092 
   1093   switch (event) {
   1094     case BTA_GATTC_DEREG_EVT:
   1095       break;
   1096 
   1097     case BTA_GATTC_OPEN_EVT: {
   1098       if (!instance) return;
   1099       tBTA_GATTC_OPEN& o = p_data->open;
   1100       instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda,
   1101                                 o.transport, o.mtu);
   1102       break;
   1103     }
   1104 
   1105     case BTA_GATTC_CLOSE_EVT: {
   1106       if (!instance) return;
   1107       tBTA_GATTC_CLOSE& c = p_data->close;
   1108       instance->OnGattDisconnected(c.status, c.conn_id, c.client_if,
   1109                                    c.remote_bda, c.reason);
   1110     } break;
   1111 
   1112     case BTA_GATTC_SEARCH_CMPL_EVT:
   1113       if (!instance) return;
   1114       instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id,
   1115                                         p_data->search_cmpl.status);
   1116       break;
   1117 
   1118     case BTA_GATTC_NOTIF_EVT:
   1119       break;
   1120 
   1121     case BTA_GATTC_ENC_CMPL_CB_EVT:
   1122       if (!instance) return;
   1123       instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true);
   1124       break;
   1125 
   1126     case BTA_GATTC_CONN_UPDATE_EVT:
   1127       if (!instance) return;
   1128       instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id);
   1129       break;
   1130 
   1131     default:
   1132       break;
   1133   }
   1134 }
   1135 
   1136 void encryption_callback(const RawAddress* address, tGATT_TRANSPORT, void*,
   1137                          tBTM_STATUS status) {
   1138   if (instance) {
   1139     instance->OnEncryptionComplete(*address,
   1140                                    status == BTM_SUCCESS ? true : false);
   1141   }
   1142 }
   1143 
   1144 class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
   1145  public:
   1146   void OnAudioDataReady(const std::vector<uint8_t>& data) override {
   1147     if (instance) instance->OnAudioDataReady(data);
   1148   }
   1149   void OnAudioSuspend() override {
   1150     if (instance) instance->OnAudioSuspend();
   1151   }
   1152 
   1153   void OnAudioResume() override {
   1154     if (instance) instance->OnAudioResume();
   1155   }
   1156 };
   1157 
   1158 HearingAidAudioReceiverImpl audioReceiverImpl;
   1159 
   1160 }  // namespace
   1161 
   1162 void HearingAid::Initialize(
   1163     bluetooth::hearing_aid::HearingAidCallbacks* callbacks, Closure initCb) {
   1164   if (instance) {
   1165     LOG(ERROR) << "Already initialized!";
   1166   }
   1167 
   1168   audioReceiver = &audioReceiverImpl;
   1169   instance = new HearingAidImpl(callbacks, initCb);
   1170   HearingAidAudioSource::Initialize();
   1171 }
   1172 
   1173 bool HearingAid::IsInitialized() { return instance; }
   1174 
   1175 HearingAid* HearingAid::Get() {
   1176   CHECK(instance);
   1177   return instance;
   1178 };
   1179 
   1180 void HearingAid::AddFromStorage(const RawAddress& address, uint16_t psm,
   1181                                 uint8_t capabilities, uint16_t codecs,
   1182                                 uint16_t audio_control_point_handle,
   1183                                 uint16_t volume_handle, uint64_t hiSyncId,
   1184                                 uint16_t render_delay,
   1185                                 uint16_t preparation_delay,
   1186                                 uint16_t is_white_listed) {
   1187   if (!instance) {
   1188     LOG(ERROR) << "Not initialized yet";
   1189   }
   1190 
   1191   instance->AddFromStorage(address, psm, capabilities, codecs,
   1192                            audio_control_point_handle, volume_handle, hiSyncId,
   1193                            render_delay, preparation_delay, is_white_listed);
   1194 };
   1195 
   1196 int HearingAid::GetDeviceCount() {
   1197   if (!instance) {
   1198     LOG(INFO) << __func__ << ": Not initialized yet";
   1199     return 0;
   1200   }
   1201 
   1202   return (instance->GetDeviceCount());
   1203 }
   1204 
   1205 void HearingAid::CleanUp() {
   1206   // Must stop audio source to make sure it doesn't call any of callbacks on our
   1207   // soon to be  null instance
   1208   HearingAidAudioSource::Stop();
   1209   HearingAidAudioSource::CleanUp();
   1210 
   1211   instance->CleanUp();
   1212   HearingAidImpl* ptr = instance;
   1213   instance = nullptr;
   1214   delete ptr;
   1215 };
   1216 
   1217 void HearingAid::DebugDump(int fd) {
   1218   dprintf(fd, "\nHearing Aid Manager:\n");
   1219   if (instance) instance->Dump(fd);
   1220   HearingAidAudioSource::DebugDump(fd);
   1221 }