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