• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - www.ehima.com
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 #include <base/bind_helpers.h>
19 #include <base/functional/bind.h>
20 #include <base/strings/string_number_conversions.h>
21 #include <bluetooth/log.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include <osi/include/alarm.h>
25 #include <sys/socket.h>
26 
27 #include <variant>
28 
29 #include "bta/le_audio/le_audio_types.h"
30 #include "bta_csis_api.h"
31 #include "bta_gatt_api_mock.h"
32 #include "bta_gatt_queue_mock.h"
33 #include "bta_has_api.h"
34 #include "btif_storage_mock.h"
35 #include "btm_api_mock.h"
36 #include "gatt/database_builder.h"
37 #include "hardware/bt_gatt_types.h"
38 #include "has_types.h"
39 #include "mock_csis_client.h"
40 #include "stack/include/bt_uuid16.h"
41 #include "test/common/mock_functions.h"
42 
gatt_profile_get_eatt_support(const RawAddress & addr)43 bool gatt_profile_get_eatt_support(const RawAddress& addr) { return true; }
44 void osi_property_set_bool(const char* key, bool value);
45 
46 namespace bluetooth {
47 namespace has {
48 namespace internal {
49 namespace {
50 
51 using base::HexEncode;
52 
53 using ::bluetooth::csis::CsisClient;
54 using ::bluetooth::has::ConnectionState;
55 using ::bluetooth::has::ErrorCode;
56 using ::bluetooth::has::HasClientCallbacks;
57 using ::bluetooth::has::PresetInfo;
58 
59 using ::bluetooth::le_audio::has::HasClient;
60 using ::bluetooth::le_audio::has::HasCtpGroupOpCoordinator;
61 using ::bluetooth::le_audio::has::HasCtpOp;
62 using ::bluetooth::le_audio::has::HasDevice;
63 using ::bluetooth::le_audio::has::HasPreset;
64 
65 using ::testing::_;
66 using ::testing::AnyNumber;
67 using ::testing::DoAll;
68 using ::testing::DoDefault;
69 using ::testing::Invoke;
70 using ::testing::Mock;
71 using ::testing::NotNull;
72 using ::testing::Return;
73 using ::testing::SaveArg;
74 using ::testing::Sequence;
75 using ::testing::SetArgPointee;
76 using ::testing::WithArg;
77 
78 // Disables most likely false-positives from base::SplitString()
79 // extern "C" const char* __asan_default_options() {
80 //   return "detect_container_overflow=0";
81 // }
82 
GetTestAddress(int index)83 RawAddress GetTestAddress(int index) {
84   EXPECT_LT(index, UINT8_MAX);
85   RawAddress result = {
86       {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
87   return result;
88 }
89 
GetTestConnId(const RawAddress & address)90 static uint16_t GetTestConnId(const RawAddress& address) {
91   return address.address[RawAddress::kLength - 1];
92 }
93 
94 class MockHasCallbacks : public HasClientCallbacks {
95  public:
96   MockHasCallbacks() = default;
97   MockHasCallbacks(const MockHasCallbacks&) = delete;
98   MockHasCallbacks& operator=(const MockHasCallbacks&) = delete;
99 
100   ~MockHasCallbacks() override = default;
101 
102   MOCK_METHOD((void), OnConnectionState,
103               (ConnectionState state, const RawAddress& address), (override));
104   MOCK_METHOD((void), OnDeviceAvailable,
105               (const RawAddress& address, uint8_t features), (override));
106   MOCK_METHOD((void), OnFeaturesUpdate,
107               (const RawAddress& address, uint8_t features), (override));
108   MOCK_METHOD((void), OnActivePresetSelected,
109               ((std::variant<RawAddress, int> addr_or_group_id),
110                uint8_t preset_index),
111               (override));
112   MOCK_METHOD((void), OnActivePresetSelectError,
113               ((std::variant<RawAddress, int> addr_or_group_id),
114                ErrorCode result),
115               (override));
116   MOCK_METHOD((void), OnPresetInfo,
117               ((std::variant<RawAddress, int> addr_or_group_id),
118                PresetInfoReason change_id,
119                std::vector<PresetInfo> preset_change_records),
120               (override));
121   MOCK_METHOD((void), OnPresetInfoError,
122               ((std::variant<RawAddress, int> addr_or_group_id),
123                uint8_t preset_index, ErrorCode error_code),
124               (override));
125   MOCK_METHOD((void), OnSetPresetNameError,
126               ((std::variant<RawAddress, int> addr_or_group_id),
127                uint8_t preset_index, ErrorCode error_code),
128               (override));
129 };
130 
131 class HasClientTestBase : public ::testing::Test {
132  protected:
133   std::map<uint16_t, uint8_t> current_peer_active_preset_idx_;
134   std::map<uint16_t, uint8_t> current_peer_features_val_;
135   std::map<uint16_t, std::set<HasPreset, HasPreset::ComparatorDesc>>
136       current_peer_presets_;
137 
138   struct HasDbBuilder {
139     bool has;
140 
141     static constexpr uint16_t kGapSvcStartHdl = 0x0001;
142     static constexpr uint16_t kGapDeviceNameValHdl = 0x0003;
143     static constexpr uint16_t kGapSvcEndHdl = kGapDeviceNameValHdl;
144 
145     static constexpr uint16_t kSvcStartHdl = 0x0010;
146     static constexpr uint16_t kFeaturesValHdl = 0x0012;
147     static constexpr uint16_t kPresetsCtpValHdl = 0x0015;
148     static constexpr uint16_t kActivePresetIndexValHdl = 0x0018;
149     static constexpr uint16_t kSvcEndHdl = 0x001E;
150 
151     static constexpr uint16_t kGattSvcStartHdl = 0x0090;
152     static constexpr uint16_t kGattSvcChangedValHdl = 0x0092;
153     static constexpr uint16_t kGattSvcEndHdl = kGattSvcChangedValHdl + 1;
154 
155     bool features;
156     bool features_ntf;
157 
158     bool preset_cp;
159     bool preset_cp_ntf;
160     bool preset_cp_ind;
161 
162     bool active_preset_idx;
163     bool active_preset_idx_ntf;
164 
Buildbluetooth::has::internal::__anonfc23c1c00111::HasClientTestBase::HasDbBuilder165     const gatt::Database Build() {
166       gatt::DatabaseBuilder bob;
167 
168       /* Generic Access Service */
169       bob.AddService(kGapSvcStartHdl, kGapSvcEndHdl, Uuid::From16Bit(0x1800),
170                      true);
171       /* Device Name Char. */
172       bob.AddCharacteristic(kGapDeviceNameValHdl - 1, kGapDeviceNameValHdl,
173                             Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
174 
175       /* 0x0004-0x000f left empty on purpose */
176       if (has) {
177         bob.AddService(kSvcStartHdl, kSvcEndHdl,
178                        ::bluetooth::le_audio::has::kUuidHearingAccessService,
179                        true);
180 
181         if (features) {
182           bob.AddCharacteristic(
183               kFeaturesValHdl - 1, kFeaturesValHdl,
184               ::bluetooth::le_audio::has::kUuidHearingAidFeatures,
185               GATT_CHAR_PROP_BIT_READ |
186                   (features_ntf ? GATT_CHAR_PROP_BIT_NOTIFY : 0));
187 
188           if (features_ntf) {
189             bob.AddDescriptor(kFeaturesValHdl + 1,
190                               Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
191           }
192         }
193 
194         if (preset_cp) {
195           bob.AddCharacteristic(
196               kPresetsCtpValHdl - 1, kPresetsCtpValHdl,
197               ::bluetooth::le_audio::has::kUuidHearingAidPresetControlPoint,
198               GATT_CHAR_PROP_BIT_WRITE |
199                   (preset_cp_ntf ? GATT_CHAR_PROP_BIT_NOTIFY : 0) |
200                   (preset_cp_ind ? GATT_CHAR_PROP_BIT_INDICATE : 0));
201 
202           if (preset_cp_ntf || preset_cp_ind) {
203             bob.AddDescriptor(kPresetsCtpValHdl + 1,
204                               Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
205           }
206         }
207 
208         if (active_preset_idx) {
209           bob.AddCharacteristic(
210               kActivePresetIndexValHdl - 1, kActivePresetIndexValHdl,
211               ::bluetooth::le_audio::has::kUuidActivePresetIndex,
212               GATT_CHAR_PROP_BIT_READ |
213                   (active_preset_idx_ntf ? GATT_CHAR_PROP_BIT_NOTIFY : 0));
214 
215           if (active_preset_idx_ntf)
216             bob.AddDescriptor(kActivePresetIndexValHdl + 1,
217                               Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
218         }
219       }
220 
221       /* GATTS */
222       /* 0x001F-0x0090 left empty on purpose */
223       bob.AddService(kGattSvcStartHdl, kGattSvcEndHdl,
224                      Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
225       bob.AddCharacteristic(kGattSvcChangedValHdl - 1, kGattSvcChangedValHdl,
226                             Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
227                             GATT_CHAR_PROP_BIT_NOTIFY);
228       bob.AddDescriptor(kGattSvcChangedValHdl + 1,
229                         Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
230       return bob.Build();
231     };
232   };
233 
FindCharacteristicByValueHandle(const gatt::Service * svc,uint16_t handle)234   const gatt::Characteristic* FindCharacteristicByValueHandle(
235       const gatt::Service* svc, uint16_t handle) {
236     if (svc == nullptr) return nullptr;
237 
238     auto it =
239         std::find_if(svc->characteristics.cbegin(), svc->characteristics.cend(),
240                      [handle](const auto& characteristic) {
241                        return characteristic.value_handle == handle;
242                      });
243     return (it != svc->characteristics.cend()) ? &(*it) : nullptr;
244   }
245 
set_sample_database(const RawAddress & address,HasDbBuilder & builder,uint8_t features_val=0x0,std::optional<std::set<HasPreset,HasPreset::ComparatorDesc>> presets_op=std::nullopt)246   void set_sample_database(
247       const RawAddress& address, HasDbBuilder& builder,
248       uint8_t features_val = 0x0,
249       std::optional<std::set<HasPreset, HasPreset::ComparatorDesc>> presets_op =
250           std::nullopt) {
251     uint16_t conn_id = GetTestConnId(address);
252 
253     /* For some test cases these defaults are enough */
254     if (!presets_op)
255       presets_op = {{
256           HasPreset(6, HasPreset::kPropertyAvailable, "Universal"),
257           HasPreset(
258               55, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
259               "YourPreset55"),
260       }};
261     auto& presets = presets_op.value();
262     auto const active_preset = presets.begin();
263 
264     services_map[conn_id] = builder.Build().Services();
265     current_peer_features_val_.insert_or_assign(conn_id, features_val);
266     current_peer_active_preset_idx_.insert_or_assign(conn_id,
267                                                      active_preset->GetIndex());
268     current_peer_presets_.insert_or_assign(conn_id, std::move(presets));
269 
270     ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
271         .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
272                                      GATT_READ_OP_CB cb, void* cb_data) {
273           auto* svc = gatt::FindService(services_map[conn_id], handle);
274           if (svc == nullptr) return;
275 
276           std::vector<uint8_t> value;
277           tGATT_STATUS status = GATT_SUCCESS;
278 
279           switch (handle) {
280             case HasDbBuilder::kGapDeviceNameValHdl:
281               value.resize(20);
282               break;
283             case HasDbBuilder::kFeaturesValHdl:
284               value.resize(1);
285               value[0] = current_peer_features_val_.at(conn_id);
286               break;
287             case HasDbBuilder::kActivePresetIndexValHdl:
288               value.resize(1);
289               value[0] = current_peer_active_preset_idx_.at(conn_id);
290               break;
291             case HasDbBuilder::kPresetsCtpValHdl:
292               /* passthrough */
293             default:
294               status = GATT_READ_NOT_PERMIT;
295               break;
296           }
297 
298           if (cb)
299             cb(conn_id, status, handle, value.size(), value.data(), cb_data);
300         }));
301 
302     /* Default action for the Control Point operation writes */
303     ON_CALL(gatt_queue,
304             WriteCharacteristic(conn_id, HasDbBuilder::kPresetsCtpValHdl, _,
305                                 GATT_WRITE, _, _))
306         .WillByDefault(Invoke([this, address](uint16_t conn_id, uint16_t handle,
307                                               std::vector<uint8_t> value,
308                                               tGATT_WRITE_TYPE write_type,
309                                               GATT_WRITE_OP_CB cb,
310                                               void* cb_data) {
311           auto pp = value.data();
312           auto len = value.size();
313           uint8_t op, index, num_of_indices;
314 
315           const bool indicate = false;
316 
317           if (len < 1) {
318             if (cb)
319               cb(conn_id, GATT_INVALID_ATTR_LEN, handle, value.size(),
320                  value.data(), cb_data);
321             return;
322           }
323 
324           STREAM_TO_UINT8(op, pp)
325           --len;
326           if (op > static_cast<std::underlying_type_t<
327                        ::bluetooth::le_audio::has::PresetCtpOpcode>>(
328                        ::bluetooth::le_audio::has::PresetCtpOpcode::OP_MAX_)) {
329             /* Invalid Opcode */
330             if (cb)
331               cb(conn_id, (tGATT_STATUS)0x80, handle, value.size(),
332                  value.data(), cb_data);
333             return;
334           }
335 
336           switch (
337               static_cast<::bluetooth::le_audio::has::PresetCtpOpcode>(op)) {
338             case ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS:
339               if (len < 2) {
340                 if (cb)
341                   cb(conn_id, GATT_INVALID_ATTR_LEN, handle, value.size(),
342                      value.data(), cb_data);
343 
344               } else {
345                 STREAM_TO_UINT8(index, pp);
346                 STREAM_TO_UINT8(num_of_indices, pp);
347                 len -= 2;
348                 ASSERT_EQ(0u, len);
349 
350                 InjectNotifyReadPresetsResponse(conn_id, address, handle, value,
351                                                 indicate, index, num_of_indices,
352                                                 cb, cb_data);
353               }
354               break;
355 
356             case ::bluetooth::le_audio::has::PresetCtpOpcode::
357                 SET_ACTIVE_PRESET: {
358               if (len < 1) {
359                 if (cb)
360                   cb(conn_id, GATT_INVALID_ATTR_LEN, handle, value.size(),
361                      value.data(), cb_data);
362                 break;
363               }
364               STREAM_TO_UINT8(index, pp);
365               --len;
366               ASSERT_EQ(0u, len);
367 
368               auto presets = current_peer_presets_.at(conn_id);
369               if (presets.count(index)) {
370                 current_peer_active_preset_idx_.insert_or_assign(conn_id,
371                                                                  index);
372                 if (cb)
373                   cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
374                      cb_data);
375                 InjectActivePresetNotification(conn_id, address, handle, value,
376                                                index, cb, cb_data);
377               } else {
378                 /* Preset Operation Not Possible */
379                 if (cb)
380                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
381                      value.data(), cb_data);
382               }
383             } break;
384 
385             case ::bluetooth::le_audio::has::PresetCtpOpcode::
386                 SET_ACTIVE_PRESET_SYNC: {
387               auto features = current_peer_features_val_.at(conn_id);
388               if ((features & ::bluetooth::has::
389                                   kFeatureBitPresetSynchronizationSupported) ==
390                   0) {
391                 /* Synchronization Not Supported */
392                 if (cb)
393                   cb(conn_id, (tGATT_STATUS)0x82, handle, value.size(),
394                      value.data(), cb_data);
395                 break;
396               }
397 
398               if (len < 1) {
399                 if (cb)
400                   cb(conn_id, GATT_INVALID_ATTR_LEN, handle, value.size(),
401                      value.data(), cb_data);
402                 break;
403               }
404               STREAM_TO_UINT8(index, pp);
405               --len;
406               ASSERT_EQ(0u, len);
407 
408               auto csis_api = CsisClient::Get();
409               int group_id = bluetooth::groups::kGroupUnknown;
410               if (csis_api != nullptr) {
411                 group_id = csis_api->GetGroupId(
412                     address, ::bluetooth::le_audio::uuid::kCapServiceUuid);
413               }
414 
415               if (group_id != bluetooth::groups::kGroupUnknown) {
416                 if (cb)
417                   cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
418                      cb_data);
419                 /* Send notification from all grouped devices */
420                 auto addresses = csis_api->GetDeviceList(group_id);
421                 for (auto& addr : addresses) {
422                   auto conn = GetTestConnId(addr);
423                   InjectActivePresetNotification(conn, addr, handle, value,
424                                                  index, cb, cb_data);
425                 }
426               } else {
427                 /* Preset Operation Not Possible */
428                 if (cb)
429                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
430                      value.data(), cb_data);
431               }
432             } break;
433 
434             case ::bluetooth::le_audio::has::PresetCtpOpcode::SET_NEXT_PRESET: {
435               ASSERT_EQ(0u, len);
436               ASSERT_NE(0u, current_peer_active_preset_idx_.count(conn_id));
437               ASSERT_NE(0u, current_peer_presets_.count(conn_id));
438 
439               auto current_preset = current_peer_active_preset_idx_.at(conn_id);
440               auto presets = current_peer_presets_.at(conn_id);
441               auto current = presets.find(current_preset);
442               if (current != presets.end()) {
443                 ++current;
444                 if (current == presets.end()) current = presets.begin();
445 
446                 current_peer_active_preset_idx_.insert_or_assign(
447                     conn_id, current->GetIndex());
448                 InjectActivePresetNotification(conn_id, address, handle, value,
449                                                current->GetIndex(), cb,
450                                                cb_data);
451 
452               } else {
453                 /* Preset Operation Not Possible */
454                 if (cb)
455                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
456                      value.data(), cb_data);
457               }
458             } break;
459 
460             case ::bluetooth::le_audio::has::PresetCtpOpcode::SET_PREV_PRESET: {
461               ASSERT_EQ(0u, len);
462               ASSERT_NE(0u, current_peer_active_preset_idx_.count(conn_id));
463               ASSERT_NE(0u, current_peer_presets_.count(conn_id));
464 
465               auto current_preset = current_peer_active_preset_idx_.at(conn_id);
466               auto presets = current_peer_presets_.at(conn_id);
467               auto rit = presets.rbegin();
468               while (rit != presets.rend()) {
469                 if (rit->GetIndex() == current_preset) {
470                   rit++;
471                   /* Wrap around */
472                   if (rit == presets.rend()) {
473                     rit = presets.rbegin();
474                   }
475                   break;
476                 }
477                 rit++;
478               }
479 
480               if (rit != presets.rend()) {
481                 if (cb)
482                   cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
483                      cb_data);
484                 current_peer_active_preset_idx_.insert_or_assign(
485                     conn_id, rit->GetIndex());
486                 InjectActivePresetNotification(conn_id, address, handle, value,
487                                                rit->GetIndex(), cb, cb_data);
488               } else {
489                 /* Preset Operation Not Possible */
490                 if (cb)
491                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
492                      value.data(), cb_data);
493               }
494             } break;
495 
496             case ::bluetooth::le_audio::has::PresetCtpOpcode::
497                 SET_NEXT_PRESET_SYNC: {
498               ASSERT_EQ(0u, len);
499               auto features = current_peer_features_val_.at(conn_id);
500               if ((features & ::bluetooth::has::
501                                   kFeatureBitPresetSynchronizationSupported) ==
502                   0) {
503                 /* Synchronization Not Supported */
504                 if (cb)
505                   cb(conn_id, (tGATT_STATUS)0x82, handle, value.size(),
506                      value.data(), cb_data);
507                 break;
508               }
509 
510               auto current_preset = current_peer_active_preset_idx_.at(conn_id);
511               auto presets = current_peer_presets_.at(conn_id);
512               auto rit = presets.begin();
513               while (rit != presets.end()) {
514                 if (rit->GetIndex() == current_preset) {
515                   rit++;
516                   /* Wrap around */
517                   if (rit == presets.end()) {
518                     rit = presets.begin();
519                   }
520                   break;
521                 }
522                 rit++;
523               }
524 
525               if (rit != presets.end()) {
526                 auto synced_group = mock_csis_client_module_.GetGroupId(
527                     GetTestAddress(conn_id),
528                     ::bluetooth::le_audio::uuid::kCapServiceUuid);
529                 auto addresses =
530                     mock_csis_client_module_.GetDeviceList(synced_group);
531 
532                 // Emulate locally synced op. - notify from all of the devices
533                 for (auto addr : addresses) {
534                   auto cid = GetTestConnId(addr);
535                   if ((cid == conn_id) && (cb != nullptr))
536                     cb(cid, GATT_SUCCESS, handle, value.size(), value.data(),
537                        cb_data);
538 
539                   current_peer_active_preset_idx_.insert_or_assign(
540                       conn_id, rit->GetIndex());
541                   InjectActivePresetNotification(cid, addr, handle, value,
542                                                  rit->GetIndex(), cb, cb_data);
543                 }
544               } else {
545                 /* Preset Operation Not Possible */
546                 if (cb)
547                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
548                      value.data(), cb_data);
549               }
550             } break;
551 
552             case ::bluetooth::le_audio::has::PresetCtpOpcode::
553                 SET_PREV_PRESET_SYNC: {
554               ASSERT_EQ(0u, len);
555               auto features = current_peer_features_val_.at(conn_id);
556               if ((features & ::bluetooth::has::
557                                   kFeatureBitPresetSynchronizationSupported) ==
558                   0) {
559                 /* Synchronization Not Supported */
560                 if (cb)
561                   cb(conn_id, (tGATT_STATUS)0x82, handle, value.size(),
562                      value.data(), cb_data);
563                 break;
564               }
565 
566               auto current_preset = current_peer_active_preset_idx_.at(conn_id);
567               auto presets = current_peer_presets_.at(conn_id);
568               auto rit = presets.rbegin();
569               while (rit != presets.rend()) {
570                 if (rit->GetIndex() == current_preset) {
571                   rit++;
572                   /* Wrap around */
573                   if (rit == presets.rend()) {
574                     rit = presets.rbegin();
575                   }
576                   break;
577                 }
578                 rit++;
579               }
580 
581               if (rit != presets.rend()) {
582                 auto synced_group = mock_csis_client_module_.GetGroupId(
583                     GetTestAddress(conn_id),
584                     ::bluetooth::le_audio::uuid::kCapServiceUuid);
585                 auto addresses =
586                     mock_csis_client_module_.GetDeviceList(synced_group);
587 
588                 // Emulate locally synced op. - notify from all of the devices
589                 for (auto addr : addresses) {
590                   auto cid = GetTestConnId(addr);
591                   if ((cid == conn_id) && (cb != nullptr))
592                     cb(cid, GATT_SUCCESS, handle, value.size(), value.data(),
593                        cb_data);
594 
595                   current_peer_active_preset_idx_.insert_or_assign(
596                       conn_id, rit->GetIndex());
597                   InjectActivePresetNotification(cid, addr, handle, value,
598                                                  rit->GetIndex(), cb, cb_data);
599                 }
600               } else {
601                 /* Preset Operation Not Possible */
602                 if (cb)
603                   cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(),
604                      value.data(), cb_data);
605               }
606             } break;
607 
608             case ::bluetooth::le_audio::has::PresetCtpOpcode::
609                 WRITE_PRESET_NAME: {
610               STREAM_TO_UINT8(index, pp);
611               --len;
612               auto name = std::string(pp, pp + len);
613               len = 0;
614 
615               ASSERT_NE(0u, current_peer_presets_.count(conn_id));
616               auto presets = current_peer_presets_.at(conn_id);
617               auto rit = presets.rbegin();
618               auto current = rit;
619               while (rit != presets.rend()) {
620                 if (rit->GetIndex() == index) {
621                   current = rit;
622                   rit++;
623                   break;
624                 }
625                 rit++;
626               }
627 
628               auto prev_index = (rit == presets.rend()) ? 0 : rit->GetIndex();
629 
630               ASSERT_NE(current, presets.rend());
631               if (cb)
632                 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
633                    cb_data);
634 
635               auto new_preset = HasPreset(current->GetIndex(),
636                                           current->GetProperties(), name);
637               presets.erase(current->GetIndex());
638               presets.insert(new_preset);
639 
640               InjectPresetChanged(conn_id, address, indicate, new_preset,
641                                   prev_index,
642                                   ::bluetooth::le_audio::has::
643                                       PresetCtpChangeId::PRESET_GENERIC_UPDATE,
644                                   true);
645             } break;
646 
647             default:
648               if (cb)
649                 cb(conn_id, GATT_INVALID_HANDLE, handle, value.size(),
650                    value.data(), cb_data);
651               break;
652           }
653         }));
654   }
655 
SetUp(void)656   void SetUp(void) override {
657     reset_mock_function_count_map();
658     bluetooth::manager::SetMockBtmInterface(&btm_interface);
659     bluetooth::storage::SetMockBtifStorageInterface(&btif_storage_interface_);
660     gatt::SetMockBtaGattInterface(&gatt_interface);
661     gatt::SetMockBtaGattQueue(&gatt_queue);
662     callbacks.reset(new MockHasCallbacks());
663 
664     encryption_result = true;
665 
666     ON_CALL(btm_interface, IsLinkKeyKnown(_, _))
667         .WillByDefault(DoAll(Return(true)));
668 
669     ON_CALL(btm_interface, SetEncryption(_, _, _, _, _))
670         .WillByDefault(
671             Invoke([this](const RawAddress& bd_addr, tBT_TRANSPORT transport,
672                           tBTM_SEC_CALLBACK* p_callback, void* p_ref_data,
673                           tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS {
674               InjectEncryptionEvent(bd_addr);
675               return BTM_SUCCESS;
676             }));
677 
678     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
679     ON_CALL(mock_csis_client_module_, Get())
680         .WillByDefault(Return(&mock_csis_client_module_));
681     ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
682         .WillByDefault(Return(true));
683 
684     /* default action for GetCharacteristic function call */
685     ON_CALL(gatt_interface, GetCharacteristic(_, _))
686         .WillByDefault(
687             Invoke([&](uint16_t conn_id,
688                        uint16_t handle) -> const gatt::Characteristic* {
689               std::list<gatt::Service>& services = services_map[conn_id];
690               for (auto const& service : services) {
691                 for (auto const& characteristic : service.characteristics) {
692                   if (characteristic.value_handle == handle) {
693                     return &characteristic;
694                   }
695                 }
696               }
697 
698               return nullptr;
699             }));
700 
701     /* default action for GetOwningService function call */
702     ON_CALL(gatt_interface, GetOwningService(_, _))
703         .WillByDefault(Invoke(
704             [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
705               std::list<gatt::Service>& services = services_map[conn_id];
706               for (auto const& service : services) {
707                 if (service.handle <= handle && service.end_handle >= handle) {
708                   return &service;
709                 }
710               }
711 
712               return nullptr;
713             }));
714 
715     ON_CALL(gatt_interface, ServiceSearchRequest(_, _))
716         .WillByDefault(WithArg<0>(Invoke(
717             [&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
718 
719     /* default action for GetServices function call */
720     ON_CALL(gatt_interface, GetServices(_))
721         .WillByDefault(WithArg<0>(
722             Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
723               return &services_map[conn_id];
724             })));
725 
726     /* default action for RegisterForNotifications function call */
727     ON_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
728         .WillByDefault(Return(GATT_SUCCESS));
729 
730     /* default action for DeregisterForNotifications function call */
731     ON_CALL(gatt_interface, DeregisterForNotifications(gatt_if, _, _))
732         .WillByDefault(Return(GATT_SUCCESS));
733 
734     /* default action for WriteDescriptor function call */
735     ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
736         .WillByDefault(
737             Invoke([](uint16_t conn_id, uint16_t handle,
738                       std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
739                       GATT_WRITE_OP_CB cb, void* cb_data) -> void {
740               if (cb)
741                 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
742                    cb_data);
743             }));
744 
745     /* by default connect only direct connection requests */
746     ON_CALL(gatt_interface, Open(_, _, _, _))
747         .WillByDefault(
748             Invoke([&](tGATT_IF client_if, const RawAddress& remote_bda,
749                        tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) {
750               if (connection_type == BTM_BLE_DIRECT_CONNECTION)
751                 InjectConnectedEvent(remote_bda, GetTestConnId(remote_bda));
752             }));
753 
754     ON_CALL(gatt_interface, Close(_))
755         .WillByDefault(Invoke(
756             [&](uint16_t conn_id) { InjectDisconnectedEvent(conn_id); }));
757   }
758 
TearDown(void)759   void TearDown(void) override {
760     services_map.clear();
761     gatt::SetMockBtaGattQueue(nullptr);
762     gatt::SetMockBtaGattInterface(nullptr);
763     bluetooth::storage::SetMockBtifStorageInterface(nullptr);
764     bluetooth::manager::SetMockBtmInterface(nullptr);
765     callbacks.reset();
766 
767     current_peer_active_preset_idx_.clear();
768     current_peer_features_val_.clear();
769   }
770 
TestAppRegister(void)771   void TestAppRegister(void) {
772     BtaAppRegisterCallback app_register_callback;
773     EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
774         .WillOnce(DoAll(SaveArg<0>(&gatt_callback),
775                         SaveArg<1>(&app_register_callback)));
776     HasClient::Initialize(callbacks.get(), base::DoNothing());
777     ASSERT_TRUE(gatt_callback);
778     ASSERT_TRUE(app_register_callback);
779     app_register_callback.Run(gatt_if, GATT_SUCCESS);
780     ASSERT_TRUE(HasClient::IsHasClientRunning());
781     Mock::VerifyAndClearExpectations(&gatt_interface);
782   }
783 
TestAppUnregister(void)784   void TestAppUnregister(void) {
785     EXPECT_CALL(gatt_interface, AppDeregister(gatt_if));
786     HasClient::CleanUp();
787     ASSERT_FALSE(HasClient::IsHasClientRunning());
788     gatt_callback = nullptr;
789   }
790 
TestConnect(const RawAddress & address)791   void TestConnect(const RawAddress& address) {
792     ON_CALL(btm_interface, BTM_IsEncrypted(address, _))
793         .WillByDefault(DoAll(Return(encryption_result)));
794 
795     EXPECT_CALL(gatt_interface,
796                 Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _));
797     HasClient::Get()->Connect(address);
798 
799     Mock::VerifyAndClearExpectations(&*callbacks);
800     Mock::VerifyAndClearExpectations(&gatt_queue);
801     Mock::VerifyAndClearExpectations(&gatt_interface);
802     Mock::VerifyAndClearExpectations(&btm_interface);
803   }
804 
TestDisconnect(const RawAddress & address,uint16_t conn_id)805   void TestDisconnect(const RawAddress& address, uint16_t conn_id) {
806     EXPECT_CALL(gatt_interface, CancelOpen(_, address, _)).Times(AnyNumber());
807     if (conn_id != GATT_INVALID_CONN_ID) {
808       assert(0);
809       EXPECT_CALL(gatt_interface, Close(conn_id));
810     } else {
811       EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _));
812     }
813     HasClient::Get()->Disconnect(address);
814   }
815 
TestAddFromStorage(const RawAddress & address,uint8_t features,bool auto_connect)816   void TestAddFromStorage(const RawAddress& address, uint8_t features,
817                           bool auto_connect) {
818     if (auto_connect) {
819       EXPECT_CALL(gatt_interface,
820                   Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, _));
821       HasClient::Get()->AddFromStorage(address, features, auto_connect);
822 
823       /* Inject connected event for autoconnect/background connection */
824       InjectConnectedEvent(address, GetTestConnId(address));
825     } else {
826       EXPECT_CALL(gatt_interface, Open(gatt_if, address, _, _)).Times(0);
827       HasClient::Get()->AddFromStorage(address, features, auto_connect);
828     }
829 
830     Mock::VerifyAndClearExpectations(&gatt_interface);
831   }
832 
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)833   void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
834                             tGATT_STATUS status = GATT_SUCCESS) {
835     tBTA_GATTC_OPEN event_data = {
836         .status = status,
837         .conn_id = conn_id,
838         .client_if = gatt_if,
839         .remote_bda = address,
840         .transport = GATT_TRANSPORT_LE,
841         .mtu = 240,
842     };
843 
844     connected_devices[conn_id] = address;
845     gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
846   }
847 
InjectDisconnectedEvent(uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST,bool allow_fake_conn=false)848   void InjectDisconnectedEvent(
849       uint16_t conn_id,
850       tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST,
851       bool allow_fake_conn = false) {
852     if (!allow_fake_conn) ASSERT_NE(connected_devices.count(conn_id), 0u);
853 
854     tBTA_GATTC_CLOSE event_data = {
855         .conn_id = conn_id,
856         .status = GATT_SUCCESS,
857         .client_if = gatt_if,
858         .remote_bda = connected_devices[conn_id],
859         .reason = reason,
860     };
861 
862     connected_devices.erase(conn_id);
863     gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
864   }
865 
InjectSearchCompleteEvent(uint16_t conn_id)866   void InjectSearchCompleteEvent(uint16_t conn_id) {
867     tBTA_GATTC_SEARCH_CMPL event_data = {
868         .conn_id = conn_id,
869         .status = GATT_SUCCESS,
870     };
871 
872     gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
873   }
874 
InjectNotificationEvent(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value,bool indicate=false)875   void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id,
876                                uint16_t handle, std::vector<uint8_t> value,
877                                bool indicate = false) {
878     tBTA_GATTC_NOTIFY event_data = {
879         .conn_id = conn_id,
880         .bda = test_address,
881         .handle = handle,
882         .len = (uint8_t)value.size(),
883         .is_notify = !indicate,
884     };
885 
886     ASSERT_TRUE(value.size() < GATT_MAX_ATTR_LEN);
887     std::copy(value.begin(), value.end(), event_data.value);
888     gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
889   }
890 
InjectEncryptionEvent(const RawAddress & test_address)891   void InjectEncryptionEvent(const RawAddress& test_address) {
892     tBTA_GATTC_ENC_CMPL_CB event_data = {
893         .client_if = static_cast<tGATT_IF>(GetTestConnId(test_address)),
894         .remote_bda = test_address,
895     };
896 
897     gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT, (tBTA_GATTC*)&event_data);
898   }
899 
SetEncryptionResult(const RawAddress & address,bool success)900   void SetEncryptionResult(const RawAddress& address, bool success) {
901     encryption_result = success;
902 
903     ON_CALL(btm_interface, BTM_IsEncrypted(address, _))
904         .WillByDefault(DoAll(Return(encryption_result)));
905 
906     ON_CALL(btm_interface, IsLinkKeyKnown(address, _))
907         .WillByDefault(DoAll(Return(true)));
908   }
909 
InjectNotifyReadPresetResponse(uint16_t conn_id,RawAddress const & address,uint16_t handle,const HasPreset & preset,bool indicate,bool is_last)910   void InjectNotifyReadPresetResponse(uint16_t conn_id,
911                                       RawAddress const& address,
912                                       uint16_t handle, const HasPreset& preset,
913                                       bool indicate, bool is_last) {
914     std::vector<uint8_t> value;
915 
916     value.push_back(static_cast<std::underlying_type_t<
917                         ::bluetooth::le_audio::has::PresetCtpOpcode>>(
918         ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESET_RESPONSE));
919     value.push_back(is_last ? 0x01 : 0x00);
920 
921     preset.ToCharacteristicValue(value);
922     InjectNotificationEvent(address, conn_id, handle, value, indicate);
923   }
924 
InjectPresetChanged(uint16_t conn_id,RawAddress const & address,bool indicate,const HasPreset & preset,uint8_t prev_index,::bluetooth::le_audio::has::PresetCtpChangeId change_id,bool is_last)925   void InjectPresetChanged(
926       uint16_t conn_id, RawAddress const& address, bool indicate,
927       const HasPreset& preset, uint8_t prev_index,
928       ::bluetooth::le_audio::has::PresetCtpChangeId change_id, bool is_last) {
929     std::vector<uint8_t> value;
930 
931     value.push_back(static_cast<std::underlying_type_t<
932                         ::bluetooth::le_audio::has::PresetCtpOpcode>>(
933         ::bluetooth::le_audio::has::PresetCtpOpcode::PRESET_CHANGED));
934     value.push_back(static_cast<uint8_t>(change_id));
935     value.push_back(is_last ? 0x01 : 0x00);
936 
937     switch (change_id) {
938       case ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_GENERIC_UPDATE:
939         value.push_back(prev_index);
940         preset.ToCharacteristicValue(value);
941         break;
942       case ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_DELETED:
943       case ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_AVAILABLE:
944       case ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_UNAVAILABLE:
945       default:
946         value.push_back(preset.GetIndex());
947         break;
948     }
949 
950     InjectNotificationEvent(address, conn_id, HasDbBuilder::kPresetsCtpValHdl,
951                             value, indicate);
952   }
953 
InjectNotifyReadPresetsResponse(uint16_t conn_id,RawAddress const & address,uint16_t handle,std::vector<uint8_t> value,bool indicate,int index,int num_of_indices,GATT_WRITE_OP_CB cb,void * cb_data)954   void InjectNotifyReadPresetsResponse(
955       uint16_t conn_id, RawAddress const& address, uint16_t handle,
956       std::vector<uint8_t> value, bool indicate, int index, int num_of_indices,
957       GATT_WRITE_OP_CB cb, void* cb_data) {
958     auto presets = current_peer_presets_.at(conn_id);
959     log::assert_that(!presets.empty(), "Mocking error!");
960 
961     /* Index is a start index, not necessary is a valid index for the
962      * peer device */
963     auto preset = presets.find(index);
964     while (preset == presets.end() &&
965            index++ <= ::bluetooth::le_audio::has::kMaxNumOfPresets) {
966       preset = presets.find(index);
967     }
968 
969     if (preset == presets.end()) {
970       /* operation not possible */
971       if (cb)
972         cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(), value.data(),
973            cb_data);
974 
975       return;
976     }
977 
978     if (cb)
979       cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
980     /* Notify presets */
981     int num_of_notif = 1;
982     while (1) {
983       bool last =
984           preset == std::prev(presets.end()) || num_of_notif == num_of_indices;
985       InjectNotifyReadPresetResponse(conn_id, address, handle, *preset,
986                                      indicate, (last));
987       if (last) return;
988 
989       num_of_notif++;
990       preset++;
991     }
992   }
993 
InjectActivePresetNotification(uint16_t conn_id,RawAddress const & address,uint16_t handle,std::vector<uint8_t> wr_value,uint8_t index,GATT_WRITE_OP_CB cb,void * cb_data)994   void InjectActivePresetNotification(uint16_t conn_id,
995                                       RawAddress const& address,
996                                       uint16_t handle,
997                                       std::vector<uint8_t> wr_value,
998                                       uint8_t index, GATT_WRITE_OP_CB cb,
999                                       void* cb_data) {
1000     auto presets = current_peer_presets_.at(conn_id);
1001     log::assert_that(!presets.empty(), "Mocking error!");
1002 
1003     auto preset = presets.find(index);
1004     if (preset == presets.end()) {
1005       /* preset operation not possible */
1006       if (cb)
1007         cb(conn_id, (tGATT_STATUS)0x83, handle, wr_value.size(),
1008            wr_value.data(), cb_data);
1009       return;
1010     }
1011 
1012     std::vector<uint8_t> value;
1013     value.push_back(index);
1014     InjectNotificationEvent(
1015         address, conn_id, HasDbBuilder::kActivePresetIndexValHdl, value, false);
1016   }
1017 
SetSampleDatabaseHasNoFeatures(const RawAddress & address)1018   void SetSampleDatabaseHasNoFeatures(const RawAddress& address) {
1019     HasDbBuilder builder = {
1020         .has = true,
1021         .features = false,
1022         .features_ntf = false,
1023         .preset_cp = true,
1024         .preset_cp_ntf = false,
1025         .preset_cp_ind = true,
1026         .active_preset_idx = true,
1027         .active_preset_idx_ntf = true,
1028     };
1029     set_sample_database(address, builder);
1030   }
1031 
SetSampleDatabaseHasNoPresetChange(const RawAddress & address,uint8_t features_value=0x00)1032   void SetSampleDatabaseHasNoPresetChange(const RawAddress& address,
1033                                           uint8_t features_value = 0x00) {
1034     HasDbBuilder builder = {
1035         .has = true,
1036         .features = true,
1037         .features_ntf = false,
1038         .preset_cp = false,
1039         .preset_cp_ntf = false,
1040         .preset_cp_ind = false,
1041         .active_preset_idx = false,
1042         .active_preset_idx_ntf = false,
1043     };
1044     set_sample_database(address, builder, features_value);
1045   }
1046 
SetSampleDatabaseHasNoOptionalNtf(const RawAddress & address,uint8_t features=0x00)1047   void SetSampleDatabaseHasNoOptionalNtf(const RawAddress& address,
1048                                          uint8_t features = 0x00) {
1049     HasDbBuilder builder = {
1050         .has = true,
1051         .features = true,
1052         .features_ntf = false,
1053         .preset_cp = true,
1054         .preset_cp_ntf = false,
1055         .preset_cp_ind = true,
1056         .active_preset_idx = true,
1057         .active_preset_idx_ntf = true,
1058     };
1059     set_sample_database(address, builder, features);
1060   }
1061 
SetSampleDatabaseNoHas(const RawAddress & address,uint8_t features=0x00)1062   void SetSampleDatabaseNoHas(const RawAddress& address,
1063                               uint8_t features = 0x00) {
1064     HasDbBuilder builder = {
1065         .has = false,
1066         .features = false,
1067         .features_ntf = false,
1068         .preset_cp = false,
1069         .preset_cp_ntf = false,
1070         .preset_cp_ind = false,
1071         .active_preset_idx = true,
1072         .active_preset_idx_ntf = true,
1073     };
1074     set_sample_database(address, builder, features);
1075   }
1076 
SetSampleDatabaseHasBrokenNoActivePreset(const RawAddress & address,uint8_t features=0x00)1077   void SetSampleDatabaseHasBrokenNoActivePreset(const RawAddress& address,
1078                                                 uint8_t features = 0x00) {
1079     HasDbBuilder builder = {
1080         .has = true,
1081         .features = true,
1082         .features_ntf = false,
1083         .preset_cp = true,
1084         .preset_cp_ntf = true,
1085         .preset_cp_ind = true,
1086         .active_preset_idx = false,
1087         .active_preset_idx_ntf = false,
1088     };
1089     set_sample_database(address, builder, features);
1090   }
1091 
SetSampleDatabaseHasBrokenNoActivePresetNtf(const RawAddress & address,uint8_t features=0x00)1092   void SetSampleDatabaseHasBrokenNoActivePresetNtf(const RawAddress& address,
1093                                                    uint8_t features = 0x00) {
1094     HasDbBuilder builder = {
1095         .has = true,
1096         .features = true,
1097         .features_ntf = false,
1098         .preset_cp = true,
1099         .preset_cp_ntf = true,
1100         .preset_cp_ind = true,
1101         .active_preset_idx = true,
1102         .active_preset_idx_ntf = false,
1103     };
1104     set_sample_database(address, builder, features);
1105   }
1106 
SetSampleDatabaseHasOnlyFeaturesNtf(const RawAddress & address,uint8_t features=0x00)1107   void SetSampleDatabaseHasOnlyFeaturesNtf(const RawAddress& address,
1108                                            uint8_t features = 0x00) {
1109     HasDbBuilder builder = {
1110         .has = true,
1111         .features = true,
1112         .features_ntf = true,
1113         .preset_cp = false,
1114         .preset_cp_ntf = false,
1115         .preset_cp_ind = false,
1116         .active_preset_idx = false,
1117         .active_preset_idx_ntf = false,
1118     };
1119     set_sample_database(address, builder, features);
1120   }
1121 
SetSampleDatabaseHasOnlyFeaturesNoNtf(const RawAddress & address,uint8_t features=0x00)1122   void SetSampleDatabaseHasOnlyFeaturesNoNtf(const RawAddress& address,
1123                                              uint8_t features = 0x00) {
1124     HasDbBuilder builder = {
1125         .has = true,
1126         .features = true,
1127         .features_ntf = false,
1128         .preset_cp = false,
1129         .preset_cp_ntf = false,
1130         .preset_cp_ind = false,
1131         .active_preset_idx = false,
1132         .active_preset_idx_ntf = false,
1133     };
1134     set_sample_database(address, builder, features);
1135   }
1136 
SetSampleDatabaseHasPresetsNtf(const RawAddress & address,uint8_t features=bluetooth::has::kFeatureBitHearingAidTypeMonaural,std::optional<std::set<HasPreset,HasPreset::ComparatorDesc>> presets=std::nullopt)1137   void SetSampleDatabaseHasPresetsNtf(
1138       const RawAddress& address,
1139       uint8_t features = bluetooth::has::kFeatureBitHearingAidTypeMonaural,
1140       std::optional<std::set<HasPreset, HasPreset::ComparatorDesc>> presets =
1141           std::nullopt) {
1142     HasDbBuilder builder = {
1143         .has = true,
1144         .features = true,
1145         .features_ntf = true,
1146         .preset_cp = true,
1147         .preset_cp_ntf = true,
1148         .preset_cp_ind = true,
1149         .active_preset_idx = true,
1150         .active_preset_idx_ntf = true,
1151     };
1152 
1153     set_sample_database(address, builder, features, presets);
1154   }
1155 
SetSampleDatabaseHasNoPresetsFlagsOnly(const RawAddress & address)1156   void SetSampleDatabaseHasNoPresetsFlagsOnly(const RawAddress& address) {
1157     uint8_t features = bluetooth::has::kFeatureBitHearingAidTypeMonaural;
1158     HasDbBuilder builder = {
1159         .has = true,
1160         .features = true,
1161         .features_ntf = true,
1162         .preset_cp = false,
1163         .preset_cp_ntf = false,
1164         .preset_cp_ind = false,
1165         .active_preset_idx = false,
1166         .active_preset_idx_ntf = false,
1167     };
1168 
1169     set_sample_database(address, builder, features, std::nullopt);
1170   }
1171 
1172   std::unique_ptr<MockHasCallbacks> callbacks;
1173   bluetooth::manager::MockBtmInterface btm_interface;
1174   bluetooth::storage::MockBtifStorageInterface btif_storage_interface_;
1175   gatt::MockBtaGattInterface gatt_interface;
1176   gatt::MockBtaGattQueue gatt_queue;
1177   MockCsisClient mock_csis_client_module_;
1178   tBTA_GATTC_CBACK* gatt_callback;
1179   const uint8_t gatt_if = 0xfe;
1180   std::map<uint8_t, RawAddress> connected_devices;
1181   std::map<uint16_t, std::list<gatt::Service>> services_map;
1182   bool encryption_result;
1183 };
1184 
1185 class HasClientTest : public HasClientTestBase {
SetUp(void)1186   void SetUp(void) override {
1187     HasClientTestBase::SetUp();
1188     TestAppRegister();
1189   }
TearDown(void)1190   void TearDown(void) override {
1191     TestAppUnregister();
1192     HasClientTestBase::TearDown();
1193   }
1194 };
1195 
TEST_F(HasClientTestBase,test_get_uninitialized)1196 TEST_F(HasClientTestBase, test_get_uninitialized) {
1197   ASSERT_DEATH(HasClient::Get(), "");
1198 }
1199 
TEST_F(HasClientTestBase,test_initialize)1200 TEST_F(HasClientTestBase, test_initialize) {
1201   HasClient::Initialize(callbacks.get(), base::DoNothing());
1202   ASSERT_TRUE(HasClient::IsHasClientRunning());
1203   HasClient::CleanUp();
1204 }
1205 
TEST_F(HasClientTestBase,test_initialize_twice)1206 TEST_F(HasClientTestBase, test_initialize_twice) {
1207   HasClient::Initialize(callbacks.get(), base::DoNothing());
1208   HasClient* has_p = HasClient::Get();
1209   HasClient::Initialize(callbacks.get(), base::DoNothing());
1210   ASSERT_EQ(has_p, HasClient::Get());
1211   HasClient::CleanUp();
1212 }
1213 
TEST_F(HasClientTestBase,test_cleanup_initialized)1214 TEST_F(HasClientTestBase, test_cleanup_initialized) {
1215   HasClient::Initialize(callbacks.get(), base::DoNothing());
1216   HasClient::CleanUp();
1217   ASSERT_FALSE(HasClient::IsHasClientRunning());
1218 }
1219 
TEST_F(HasClientTestBase,test_cleanup_uninitialized)1220 TEST_F(HasClientTestBase, test_cleanup_uninitialized) {
1221   HasClient::CleanUp();
1222   ASSERT_FALSE(HasClient::IsHasClientRunning());
1223 }
1224 
TEST_F(HasClientTestBase,test_app_registration)1225 TEST_F(HasClientTestBase, test_app_registration) {
1226   TestAppRegister();
1227   TestAppUnregister();
1228 }
1229 
TEST_F(HasClientTest,test_connect)1230 TEST_F(HasClientTest, test_connect) { TestConnect(GetTestAddress(1)); }
1231 
TEST_F(HasClientTest,test_add_from_storage)1232 TEST_F(HasClientTest, test_add_from_storage) {
1233   TestAddFromStorage(GetTestAddress(1), 0, true);
1234   TestAddFromStorage(GetTestAddress(2), 0, false);
1235 }
1236 
TEST_F(HasClientTest,test_connect_after_remove)1237 TEST_F(HasClientTest, test_connect_after_remove) {
1238   const RawAddress test_address = GetTestAddress(1);
1239 
1240   /* Override the default action to prevent us sendind the connected event */
1241   EXPECT_CALL(gatt_interface,
1242               Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _))
1243       .WillOnce(Return());
1244   HasClient::Get()->Connect(test_address);
1245   TestDisconnect(test_address, GATT_INVALID_CONN_ID);
1246   Mock::VerifyAndClearExpectations(&gatt_interface);
1247 
1248   EXPECT_CALL(*callbacks,
1249               OnConnectionState(ConnectionState::DISCONNECTED, test_address));
1250 
1251   // Device has no Link Key
1252   ON_CALL(btm_interface, IsLinkKeyKnown(test_address, _))
1253       .WillByDefault(DoAll(Return(true)));
1254   HasClient::Get()->Connect(test_address);
1255   Mock::VerifyAndClearExpectations(&callbacks);
1256 }
1257 
TEST_F(HasClientTest,test_disconnect_non_connected)1258 TEST_F(HasClientTest, test_disconnect_non_connected) {
1259   const RawAddress test_address = GetTestAddress(1);
1260 
1261   /* Override the default action to prevent us sendind the connected event */
1262   EXPECT_CALL(gatt_interface,
1263               Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _))
1264       .WillOnce(Return());
1265   HasClient::Get()->Connect(test_address);
1266   TestDisconnect(test_address, GATT_INVALID_CONN_ID);
1267 }
1268 
TEST_F(HasClientTest,test_has_connected)1269 TEST_F(HasClientTest, test_has_connected) {
1270   const RawAddress test_address = GetTestAddress(1);
1271   /* Minimal possible HA device (only feature flags) */
1272   SetSampleDatabaseHasNoPresetChange(
1273       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1274 
1275   EXPECT_CALL(
1276       *callbacks,
1277       OnDeviceAvailable(test_address,
1278                         bluetooth::has::kFeatureBitHearingAidTypeBinaural));
1279   EXPECT_CALL(*callbacks,
1280               OnConnectionState(ConnectionState::CONNECTED, test_address));
1281   TestConnect(test_address);
1282 }
1283 
TEST_F(HasClientTest,test_disconnect_connected)1284 TEST_F(HasClientTest, test_disconnect_connected) {
1285   const RawAddress test_address = GetTestAddress(1);
1286   /* Minimal possible HA device (only feature flags) */
1287   SetSampleDatabaseHasNoPresetChange(
1288       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1289 
1290   EXPECT_CALL(*callbacks,
1291               OnConnectionState(ConnectionState::CONNECTED, test_address))
1292       .Times(1);
1293   TestConnect(test_address);
1294 
1295   EXPECT_CALL(*callbacks,
1296               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1297       .Times(1);
1298   TestDisconnect(test_address, 1);
1299 }
1300 
TEST_F(HasClientTest,test_disconnected_while_autoconnect)1301 TEST_F(HasClientTest, test_disconnected_while_autoconnect) {
1302   const RawAddress test_address = GetTestAddress(1);
1303   TestAddFromStorage(test_address,
1304                      bluetooth::has::kFeatureBitHearingAidTypeBinaural, true);
1305   /* autoconnect - don't indicate disconnection */
1306   EXPECT_CALL(*callbacks,
1307               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1308       .Times(0);
1309   /* Verify that the device still can connect in te background */
1310   InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER, true);
1311 }
1312 
TEST_F(HasClientTest,test_encryption_failed)1313 TEST_F(HasClientTest, test_encryption_failed) {
1314   const RawAddress test_address = GetTestAddress(1);
1315   SetSampleDatabaseHasNoPresetChange(
1316       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1317   EXPECT_CALL(*callbacks,
1318               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1319       .Times(1);
1320   EXPECT_CALL(*callbacks,
1321               OnConnectionState(ConnectionState::CONNECTED, test_address))
1322       .Times(0);
1323   SetEncryptionResult(test_address, false);
1324   TestConnect(test_address);
1325 }
1326 
TEST_F(HasClientTest,test_service_discovery_complete_before_encryption)1327 TEST_F(HasClientTest, test_service_discovery_complete_before_encryption) {
1328   const RawAddress test_address = GetTestAddress(1);
1329   SetSampleDatabaseHasPresetsNtf(
1330       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1331 
1332   EXPECT_CALL(*callbacks,
1333               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1334       .Times(0);
1335   EXPECT_CALL(*callbacks,
1336               OnConnectionState(ConnectionState::CONNECTED, test_address))
1337       .Times(0);
1338 
1339   SetEncryptionResult(test_address, false);
1340   ON_CALL(btm_interface, SetEncryption(_, _, _, _, _))
1341       .WillByDefault(Return(BTM_SUCCESS));
1342 
1343   TestConnect(test_address);
1344   auto test_conn_id = GetTestConnId(test_address);
1345   InjectSearchCompleteEvent(test_conn_id);
1346 
1347   Mock::VerifyAndClearExpectations(callbacks.get());
1348 
1349   EXPECT_CALL(*callbacks,
1350               OnConnectionState(ConnectionState::CONNECTED, test_address))
1351       .Times(1);
1352 
1353   SetEncryptionResult(test_address, true);
1354   InjectEncryptionEvent(test_address);
1355   Mock::VerifyAndClearExpectations(callbacks.get());
1356 }
1357 
TEST_F(HasClientTest,test_disconnect_when_link_key_is_gone)1358 TEST_F(HasClientTest, test_disconnect_when_link_key_is_gone) {
1359   const RawAddress test_address = GetTestAddress(1);
1360   SetSampleDatabaseHasPresetsNtf(
1361       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1362 
1363   EXPECT_CALL(*callbacks,
1364               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1365       .Times(0);
1366   EXPECT_CALL(*callbacks,
1367               OnConnectionState(ConnectionState::CONNECTED, test_address))
1368       .Times(0);
1369 
1370   ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _))
1371       .WillByDefault(DoAll(Return(false)));
1372   ON_CALL(btm_interface, SetEncryption(test_address, _, _, _, _))
1373       .WillByDefault(Return(BTM_ERR_KEY_MISSING));
1374 
1375   auto test_conn_id = GetTestConnId(test_address);
1376   EXPECT_CALL(gatt_interface, Close(test_conn_id)).Times(1);
1377   InjectConnectedEvent(test_address, GetTestConnId(test_address));
1378 
1379   Mock::VerifyAndClearExpectations(callbacks.get());
1380 }
1381 
TEST_F(HasClientTest,test_reconnect_after_encryption_failed)1382 TEST_F(HasClientTest, test_reconnect_after_encryption_failed) {
1383   const RawAddress test_address = GetTestAddress(1);
1384   SetSampleDatabaseHasNoPresetChange(
1385       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1386   EXPECT_CALL(*callbacks,
1387               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1388       .Times(1);
1389   EXPECT_CALL(*callbacks,
1390               OnConnectionState(ConnectionState::CONNECTED, test_address))
1391       .Times(0);
1392   SetEncryptionResult(test_address, false);
1393   TestConnect(test_address);
1394 
1395   EXPECT_CALL(*callbacks,
1396               OnConnectionState(ConnectionState::CONNECTED, test_address))
1397       .Times(1);
1398   SetEncryptionResult(test_address, true);
1399   InjectConnectedEvent(test_address, GetTestConnId(test_address));
1400 }
1401 
TEST_F(HasClientTest,test_reconnect_after_encryption_failed_from_storage)1402 TEST_F(HasClientTest, test_reconnect_after_encryption_failed_from_storage) {
1403   const RawAddress test_address = GetTestAddress(1);
1404 
1405   SetSampleDatabaseHasNoPresetChange(
1406       test_address, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
1407   SetEncryptionResult(test_address, false);
1408   TestAddFromStorage(test_address, 0, true);
1409   /* autoconnect - don't indicate disconnection */
1410   EXPECT_CALL(*callbacks,
1411               OnConnectionState(ConnectionState::DISCONNECTED, test_address))
1412       .Times(0);
1413   Mock::VerifyAndClearExpectations(&btm_interface);
1414 
1415   /* Fake no persistent storage data */
1416   ON_CALL(btif_storage_interface_, GetLeaudioHasPresets(_, _, _))
1417       .WillByDefault([]() { return false; });
1418 
1419   EXPECT_CALL(*callbacks,
1420               OnConnectionState(ConnectionState::CONNECTED, test_address))
1421       .Times(1);
1422   SetEncryptionResult(test_address, true);
1423   InjectConnectedEvent(test_address, GetTestConnId(test_address));
1424 }
1425 
TEST_F(HasClientTest,test_load_from_storage_and_connect)1426 TEST_F(HasClientTest, test_load_from_storage_and_connect) {
1427   const RawAddress test_address = GetTestAddress(1);
1428   SetSampleDatabaseHasPresetsNtf(test_address, kFeatureBitDynamicPresets);
1429   SetEncryptionResult(test_address, true);
1430 
1431   std::set<HasPreset, HasPreset::ComparatorDesc> has_presets = {{
1432       HasPreset(5, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1433                 "YourWritablePreset5"),
1434       HasPreset(55, HasPreset::kPropertyAvailable, "YourPreset55"),
1435   }};
1436 
1437   /* Load persistent storage data */
1438   ON_CALL(btif_storage_interface_, GetLeaudioHasPresets(test_address, _, _))
1439       .WillByDefault([&has_presets](const RawAddress& address,
1440                                     std::vector<uint8_t>& presets_bin,
1441                                     uint8_t& active_preset) {
1442         /* Generate presets binary to be used instead the attribute values */
1443         HasDevice device(address, 0);
1444         device.has_presets = has_presets;
1445         active_preset = 55;
1446 
1447         if (device.SerializePresets(presets_bin)) return true;
1448 
1449         return false;
1450       });
1451 
1452   EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
1453       .Times(1      // preset control point
1454              + 1    // active preset
1455              + 1);  // features
1456 
1457   EXPECT_CALL(*callbacks,
1458               OnDeviceAvailable(test_address,
1459                                 (kFeatureBitWritablePresets |
1460                                  kFeatureBitPresetSynchronizationSupported |
1461                                  kFeatureBitHearingAidTypeBanded)));
1462 
1463   std::vector<PresetInfo> loaded_preset_details;
1464   EXPECT_CALL(*callbacks,
1465               OnPresetInfo(std::variant<RawAddress, int>(test_address),
1466                            PresetInfoReason::ALL_PRESET_INFO, _))
1467       .WillOnce(SaveArg<2>(&loaded_preset_details));
1468 
1469   EXPECT_CALL(*callbacks, OnActivePresetSelected(
1470                               std::variant<RawAddress, int>(test_address), 55));
1471 
1472   EXPECT_CALL(*callbacks,
1473               OnConnectionState(ConnectionState::CONNECTED, test_address));
1474 
1475   /* Expect no read or write operations when loading from storage */
1476   EXPECT_CALL(gatt_queue, ReadCharacteristic(1, _, _, _)).Times(0);
1477   EXPECT_CALL(gatt_queue, WriteDescriptor(1, _, _, _, _, _)).Times(3);
1478 
1479   TestAddFromStorage(test_address,
1480                      kFeatureBitWritablePresets |
1481                          kFeatureBitPresetSynchronizationSupported |
1482                          kFeatureBitHearingAidTypeBanded,
1483                      true);
1484 
1485   for (auto const& info : loaded_preset_details) {
1486     auto preset = has_presets.find(info.preset_index);
1487     ASSERT_NE(preset, has_presets.end());
1488     if (preset->GetProperties() & HasPreset::kPropertyAvailable)
1489       ASSERT_TRUE(info.available);
1490     if (preset->GetProperties() & HasPreset::kPropertyWritable)
1491       ASSERT_TRUE(info.writable);
1492     ASSERT_EQ(preset->GetName(), info.preset_name);
1493   }
1494 }
1495 
TEST_F(HasClientTest,test_load_from_storage)1496 TEST_F(HasClientTest, test_load_from_storage) {
1497   const RawAddress test_address = GetTestAddress(1);
1498   SetSampleDatabaseHasPresetsNtf(test_address, kFeatureBitDynamicPresets);
1499   SetEncryptionResult(test_address, true);
1500 
1501   std::set<HasPreset, HasPreset::ComparatorDesc> has_presets = {{
1502       HasPreset(5, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1503                 "YourWritablePreset5"),
1504       HasPreset(55, HasPreset::kPropertyAvailable, "YourPreset55"),
1505   }};
1506 
1507   /* Load persistent storage data */
1508   ON_CALL(btif_storage_interface_, GetLeaudioHasPresets(test_address, _, _))
1509       .WillByDefault([&has_presets](const RawAddress& address,
1510                                     std::vector<uint8_t>& presets_bin,
1511                                     uint8_t& active_preset) {
1512         /* Generate presets binary to be used instead the attribute values */
1513         HasDevice device(address, 0);
1514         device.has_presets = has_presets;
1515         active_preset = 55;
1516 
1517         if (device.SerializePresets(presets_bin)) return true;
1518 
1519         return false;
1520       });
1521 
1522   EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
1523       .Times(0);  // features
1524 
1525   EXPECT_CALL(*callbacks,
1526               OnDeviceAvailable(test_address,
1527                                 (kFeatureBitWritablePresets |
1528                                  kFeatureBitPresetSynchronizationSupported |
1529                                  kFeatureBitHearingAidTypeBanded)));
1530 
1531   std::vector<PresetInfo> loaded_preset_details;
1532   EXPECT_CALL(*callbacks,
1533               OnPresetInfo(std::variant<RawAddress, int>(test_address),
1534                            PresetInfoReason::ALL_PRESET_INFO, _))
1535       .Times(0);
1536 
1537   /* Expect no read or write operations when loading from storage */
1538   EXPECT_CALL(gatt_queue, ReadCharacteristic(1, _, _, _)).Times(0);
1539   EXPECT_CALL(gatt_queue, WriteDescriptor(1, _, _, _, _, _)).Times(0);
1540 
1541   TestAddFromStorage(test_address,
1542                      kFeatureBitWritablePresets |
1543                          kFeatureBitPresetSynchronizationSupported |
1544                          kFeatureBitHearingAidTypeBanded,
1545                      false);
1546 }
1547 
TEST_F(HasClientTest,test_write_to_storage)1548 TEST_F(HasClientTest, test_write_to_storage) {
1549   const RawAddress test_address = GetTestAddress(1);
1550 
1551   std::set<HasPreset, HasPreset::ComparatorDesc> has_presets = {{
1552       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
1553       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1554                 "Preset2"),
1555   }};
1556   SetSampleDatabaseHasPresetsNtf(
1557       test_address,
1558       bluetooth::has::kFeatureBitHearingAidTypeBanded |
1559           bluetooth::has::kFeatureBitWritablePresets |
1560           bluetooth::has::kFeatureBitDynamicPresets,
1561       has_presets);
1562 
1563   std::vector<uint8_t> serialized;
1564   EXPECT_CALL(
1565       btif_storage_interface_,
1566       AddLeaudioHasDevice(test_address, _,
1567                           bluetooth::has::kFeatureBitHearingAidTypeBanded |
1568                               bluetooth::has::kFeatureBitWritablePresets |
1569                               bluetooth::has::kFeatureBitDynamicPresets,
1570                           1))
1571       .WillOnce(SaveArg<1>(&serialized));
1572   TestConnect(test_address);
1573 
1574   /* Deserialize the written binary to verify the content */
1575   HasDevice clone(test_address,
1576                   bluetooth::has::kFeatureBitHearingAidTypeBanded |
1577                       bluetooth::has::kFeatureBitWritablePresets |
1578                       bluetooth::has::kFeatureBitDynamicPresets);
1579   ASSERT_TRUE(HasDevice::DeserializePresets(serialized.data(),
1580                                             serialized.size(), clone));
1581   auto storage_info = clone.GetAllPresetInfo();
1582   ASSERT_EQ(storage_info.size(), has_presets.size());
1583   for (auto const& info : storage_info) {
1584     auto preset = has_presets.find(info.preset_index);
1585     ASSERT_NE(preset, has_presets.end());
1586     if (preset->GetProperties() & HasPreset::kPropertyAvailable)
1587       ASSERT_TRUE(info.available);
1588     if (preset->GetProperties() & HasPreset::kPropertyWritable)
1589       ASSERT_TRUE(info.writable);
1590     ASSERT_EQ(preset->GetName(), info.preset_name);
1591   }
1592 }
1593 
TEST_F(HasClientTest,test_discovery_basic_has_no_opt_ntf)1594 TEST_F(HasClientTest, test_discovery_basic_has_no_opt_ntf) {
1595   const RawAddress test_address = GetTestAddress(1);
1596   auto test_conn_id = GetTestConnId(test_address);
1597 
1598   SetSampleDatabaseHasNoOptionalNtf(test_address);
1599 
1600   std::variant<RawAddress, int> addr_or_group = test_address;
1601   std::vector<PresetInfo> preset_details;
1602   uint8_t active_preset_index;
1603   uint8_t has_features;
1604 
1605   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _))
1606       .WillOnce(SaveArg<1>(&has_features));
1607   EXPECT_CALL(*callbacks,
1608               OnConnectionState(ConnectionState::CONNECTED, test_address));
1609   EXPECT_CALL(*callbacks, OnPresetInfo(_, PresetInfoReason::ALL_PRESET_INFO, _))
1610       .WillOnce(DoAll(SaveArg<0>(&addr_or_group), SaveArg<2>(&preset_details)));
1611   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
1612       .WillOnce(
1613           DoAll(SaveArg<0>(&addr_or_group), SaveArg<1>(&active_preset_index)));
1614   TestConnect(test_address);
1615 
1616   /* Verify sample database content */
1617   ASSERT_TRUE(std::holds_alternative<RawAddress>(addr_or_group));
1618   ASSERT_EQ(std::get<RawAddress>(addr_or_group), test_address);
1619   ASSERT_EQ(has_features, 0x00);
1620   ASSERT_EQ(active_preset_index,
1621             current_peer_presets_.at(test_conn_id).begin()->GetIndex());
1622 
1623   /* Verify presets */
1624   uint16_t conn_id = GetTestConnId(test_address);
1625   ASSERT_NE(preset_details.size(), 0u);
1626   ASSERT_EQ(current_peer_presets_.at(conn_id).size(), preset_details.size());
1627 
1628   for (auto const& preset : current_peer_presets_.at(conn_id)) {
1629     auto it =
1630         std::find_if(preset_details.cbegin(), preset_details.cend(),
1631                      [&preset](auto const& preset_info) {
1632                        return preset_info.preset_index == preset.GetIndex();
1633                      });
1634     ASSERT_NE(it, preset_details.cend());
1635     ASSERT_EQ(preset.GetName(), it->preset_name);
1636     ASSERT_EQ(preset.IsAvailable(), it->available);
1637     ASSERT_EQ(preset.IsWritable(), it->writable);
1638   }
1639 
1640   /* Verify active preset is there */
1641   ASSERT_EQ(preset_details.size(),
1642             current_peer_presets_.at(test_conn_id).size());
1643   ASSERT_TRUE(std::find_if(preset_details.begin(), preset_details.end(),
1644                            [active_preset_index](auto const& preset_info) {
1645                              return preset_info.preset_index ==
1646                                     active_preset_index;
1647                            }) != preset_details.end());
1648 }
1649 
TEST_F(HasClientTest,test_discovery_has_not_found)1650 TEST_F(HasClientTest, test_discovery_has_not_found) {
1651   const RawAddress test_address = GetTestAddress(1);
1652   SetSampleDatabaseNoHas(test_address);
1653 
1654   EXPECT_CALL(*callbacks,
1655               OnConnectionState(ConnectionState::CONNECTED, test_address))
1656       .Times(0);
1657   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _)).Times(0);
1658   EXPECT_CALL(*callbacks, OnFeaturesUpdate(test_address, _)).Times(0);
1659   EXPECT_CALL(*callbacks,
1660               OnConnectionState(ConnectionState::DISCONNECTED, test_address));
1661 
1662   TestConnect(test_address);
1663 }
1664 
TEST_F(HasClientTest,test_discovery_has_broken_no_active_preset)1665 TEST_F(HasClientTest, test_discovery_has_broken_no_active_preset) {
1666   const RawAddress test_address = GetTestAddress(1);
1667   SetSampleDatabaseHasBrokenNoActivePreset(test_address);
1668 
1669   EXPECT_CALL(*callbacks,
1670               OnConnectionState(ConnectionState::CONNECTED, test_address))
1671       .Times(0);
1672   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _)).Times(0);
1673   EXPECT_CALL(*callbacks, OnFeaturesUpdate(test_address, _)).Times(0);
1674   EXPECT_CALL(*callbacks,
1675               OnConnectionState(ConnectionState::DISCONNECTED, test_address));
1676 
1677   TestConnect(test_address);
1678 }
1679 
TEST_F(HasClientTest,test_discovery_has_broken_no_active_preset_ntf)1680 TEST_F(HasClientTest, test_discovery_has_broken_no_active_preset_ntf) {
1681   const RawAddress test_address = GetTestAddress(1);
1682   SetSampleDatabaseHasBrokenNoActivePresetNtf(test_address);
1683 
1684   EXPECT_CALL(*callbacks,
1685               OnConnectionState(ConnectionState::CONNECTED, test_address))
1686       .Times(0);
1687   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _)).Times(0);
1688   EXPECT_CALL(*callbacks, OnFeaturesUpdate(test_address, _)).Times(0);
1689   EXPECT_CALL(*callbacks,
1690               OnConnectionState(ConnectionState::DISCONNECTED, test_address));
1691 
1692   TestConnect(test_address);
1693 }
1694 
TEST_F(HasClientTest,test_discovery_has_features_ntf)1695 TEST_F(HasClientTest, test_discovery_has_features_ntf) {
1696   const RawAddress test_address = GetTestAddress(1);
1697   auto test_conn_id = GetTestConnId(test_address);
1698   uint8_t has_features;
1699 
1700   SetSampleDatabaseHasOnlyFeaturesNtf(
1701       test_address, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1702 
1703   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _))
1704       .WillOnce(SaveArg<1>(&has_features));
1705   EXPECT_CALL(*callbacks,
1706               OnConnectionState(ConnectionState::CONNECTED, test_address))
1707       .Times(1);
1708 
1709   /* Verify subscription to features */
1710   EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
1711       .Times(AnyNumber());
1712   EXPECT_CALL(gatt_interface,
1713               RegisterForNotifications(gatt_if, test_address,
1714                                        HasDbBuilder::kFeaturesValHdl));
1715 
1716   /* Verify features CCC was written */
1717   EXPECT_CALL(gatt_queue, WriteDescriptor(test_conn_id, _, _, _, _, _))
1718       .Times(AnyNumber());
1719   EXPECT_CALL(gatt_queue,
1720               WriteDescriptor(test_conn_id, HasDbBuilder::kFeaturesValHdl + 1,
1721                               std::vector<uint8_t>{0x01, 0x00}, _, _, _));
1722   TestConnect(test_address);
1723 
1724   /* Verify features */
1725   ASSERT_EQ(has_features, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1726 
1727   uint8_t new_features;
1728 
1729   /* Verify peer features change notification */
1730   EXPECT_CALL(*callbacks, OnFeaturesUpdate(test_address, _))
1731       .WillOnce(SaveArg<1>(&new_features));
1732   InjectNotificationEvent(test_address, test_conn_id,
1733                           HasDbBuilder::kFeaturesValHdl,
1734                           std::vector<uint8_t>({0x00}));
1735   ASSERT_NE(has_features, new_features);
1736 }
1737 
TEST_F(HasClientTest,test_discovery_has_features_no_ntf)1738 TEST_F(HasClientTest, test_discovery_has_features_no_ntf) {
1739   const RawAddress test_address = GetTestAddress(1);
1740   auto test_conn_id = GetTestConnId(test_address);
1741   uint8_t has_features;
1742 
1743   SetSampleDatabaseHasOnlyFeaturesNoNtf(
1744       test_address, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1745 
1746   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _))
1747       .WillOnce(SaveArg<1>(&has_features));
1748   EXPECT_CALL(*callbacks,
1749               OnConnectionState(ConnectionState::CONNECTED, test_address))
1750       .Times(1);
1751 
1752   /* Verify no subscription to features */
1753   EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
1754       .Times(AnyNumber());
1755   EXPECT_CALL(gatt_interface,
1756               RegisterForNotifications(gatt_if, test_address,
1757                                        HasDbBuilder::kFeaturesValHdl))
1758       .Times(0);
1759 
1760   /* Verify no features CCC was written */
1761   EXPECT_CALL(gatt_queue, WriteDescriptor(test_conn_id, _, _, _, _, _))
1762       .Times(AnyNumber());
1763   EXPECT_CALL(gatt_queue,
1764               WriteDescriptor(test_conn_id, HasDbBuilder::kFeaturesValHdl + 1,
1765                               _, _, _, _))
1766       .Times(0);
1767   TestConnect(test_address);
1768 
1769   /* Verify features */
1770   ASSERT_EQ(has_features, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1771 }
1772 
TEST_F(HasClientTest,test_discovery_has_multiple_presets_ntf)1773 TEST_F(HasClientTest, test_discovery_has_multiple_presets_ntf) {
1774   const RawAddress test_address = GetTestAddress(1);
1775   SetSampleDatabaseHasPresetsNtf(
1776       test_address, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1777 
1778   std::variant<RawAddress, int> addr_or_group = test_address;
1779   std::vector<PresetInfo> preset_details;
1780   uint8_t active_preset_index;
1781   uint8_t has_features;
1782 
1783   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _))
1784       .WillOnce(SaveArg<1>(&has_features));
1785   EXPECT_CALL(*callbacks,
1786               OnConnectionState(ConnectionState::CONNECTED, test_address));
1787   EXPECT_CALL(*callbacks, OnPresetInfo(_, PresetInfoReason::ALL_PRESET_INFO, _))
1788       .WillOnce(DoAll(SaveArg<0>(&addr_or_group), SaveArg<2>(&preset_details)));
1789   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
1790       .WillOnce(
1791           DoAll(SaveArg<0>(&addr_or_group), SaveArg<1>(&active_preset_index)));
1792 
1793   /* Verify subscription to control point */
1794   EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
1795       .Times(AnyNumber());
1796   EXPECT_CALL(gatt_interface,
1797               RegisterForNotifications(gatt_if, test_address,
1798                                        HasDbBuilder::kPresetsCtpValHdl));
1799 
1800   /* Verify features CCC was written */
1801   EXPECT_CALL(gatt_queue, WriteDescriptor(1, _, _, _, _, _)).Times(AnyNumber());
1802   EXPECT_CALL(gatt_queue,
1803               WriteDescriptor(1, HasDbBuilder::kPresetsCtpValHdl + 1,
1804                               std::vector<uint8_t>{0x03, 0x00}, _, _, _));
1805   TestConnect(test_address);
1806 
1807   /* Verify features */
1808   ASSERT_EQ(has_features, bluetooth::has::kFeatureBitHearingAidTypeBanded);
1809 }
1810 
TEST_F(HasClientTest,test_active_preset_change)1811 TEST_F(HasClientTest, test_active_preset_change) {
1812   const RawAddress test_address = GetTestAddress(1);
1813   auto test_conn_id = GetTestConnId(test_address);
1814 
1815   SetSampleDatabaseHasNoOptionalNtf(test_address);
1816 
1817   uint8_t active_preset_index;
1818   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _));
1819   EXPECT_CALL(*callbacks,
1820               OnPresetInfo(_, PresetInfoReason::ALL_PRESET_INFO, _));
1821   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
1822       .WillOnce(SaveArg<1>(&active_preset_index));
1823   EXPECT_CALL(*callbacks,
1824               OnConnectionState(ConnectionState::CONNECTED, test_address));
1825   TestConnect(test_address);
1826 
1827   uint8_t new_active_preset;
1828   EXPECT_CALL(*callbacks, OnActivePresetSelected(
1829                               std::variant<RawAddress, int>(test_address), _))
1830       .WillOnce(SaveArg<1>(&new_active_preset));
1831   InjectNotificationEvent(test_address, test_conn_id,
1832                           HasDbBuilder::kActivePresetIndexValHdl,
1833                           std::vector<uint8_t>({0x00}));
1834 
1835   ASSERT_NE(active_preset_index, new_active_preset);
1836   ASSERT_EQ(new_active_preset, 0x00);
1837 }
1838 
TEST_F(HasClientTest,test_duplicate_presets)1839 TEST_F(HasClientTest, test_duplicate_presets) {
1840   const RawAddress test_address = GetTestAddress(1);
1841   std::vector<PresetInfo> preset_details;
1842 
1843   /* Handle duplicates gracefully */
1844   SetSampleDatabaseHasPresetsNtf(
1845       test_address, kFeatureBitWritablePresets,
1846       {{HasPreset(5,
1847                   HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1848                   "YourWritablePreset5"),
1849         HasPreset(5,
1850                   HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1851                   "YourWritablePreset5")}});
1852 
1853   EXPECT_CALL(*callbacks,
1854               OnConnectionState(ConnectionState::CONNECTED, test_address));
1855   EXPECT_CALL(*callbacks, OnPresetInfo(_, PresetInfoReason::ALL_PRESET_INFO, _))
1856       .WillOnce(SaveArg<2>(&preset_details));
1857   TestConnect(test_address);
1858 
1859   /* Verify presets - expect 1, no duplicates */
1860   ASSERT_EQ(preset_details.size(), 1u);
1861   auto preset = std::find_if(
1862       preset_details.begin(), preset_details.end(),
1863       [](auto const& preset_info) { return preset_info.preset_index == 5; });
1864   ASSERT_TRUE(preset != preset_details.end());
1865   ASSERT_EQ("YourWritablePreset5", preset->preset_name);
1866   ASSERT_TRUE(preset->available);
1867   ASSERT_TRUE(preset->writable);
1868 }
1869 
TEST_F(HasClientTest,test_preset_set_name_invalid_index)1870 TEST_F(HasClientTest, test_preset_set_name_invalid_index) {
1871   const RawAddress test_address = GetTestAddress(1);
1872   SetSampleDatabaseHasPresetsNtf(test_address);
1873   TestConnect(test_address);
1874 
1875   EXPECT_CALL(*callbacks,
1876               OnSetPresetNameError(std::variant<RawAddress, int>(test_address),
1877                                    0x40, ErrorCode::INVALID_PRESET_INDEX))
1878       .Times(1);
1879   EXPECT_CALL(gatt_queue,
1880               WriteCharacteristic(1, HasDbBuilder::kPresetsCtpValHdl, _,
1881                                   GATT_WRITE, _, _))
1882       .Times(0);
1883 
1884   HasClient::Get()->SetPresetName(test_address, 0x40, "new preset name");
1885 }
1886 
TEST_F(HasClientTest,test_preset_set_name_non_writable)1887 TEST_F(HasClientTest, test_preset_set_name_non_writable) {
1888   const RawAddress test_address = GetTestAddress(1);
1889   uint16_t test_conn_id = GetTestConnId(test_address);
1890 
1891   SetSampleDatabaseHasPresetsNtf(
1892       test_address, kFeatureBitWritablePresets,
1893       {{
1894           HasPreset(5, HasPreset::kPropertyAvailable, "YourPreset5"),
1895           HasPreset(
1896               55, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1897               "YourWritablePreset55"),
1898       }});
1899   TestConnect(test_address);
1900 
1901   EXPECT_CALL(*callbacks,
1902               OnSetPresetNameError(_, _, ErrorCode::SET_NAME_NOT_ALLOWED))
1903       .Times(1);
1904   EXPECT_CALL(gatt_queue,
1905               WriteCharacteristic(1, HasDbBuilder::kPresetsCtpValHdl, _,
1906                                   GATT_WRITE, _, _))
1907       .Times(0);
1908 
1909   HasClient::Get()->SetPresetName(
1910       test_address, current_peer_presets_.at(test_conn_id).begin()->GetIndex(),
1911       "new preset name");
1912 }
1913 
TEST_F(HasClientTest,test_preset_set_name_to_long)1914 TEST_F(HasClientTest, test_preset_set_name_to_long) {
1915   const RawAddress test_address = GetTestAddress(1);
1916   uint16_t test_conn_id = GetTestConnId(test_address);
1917 
1918   SetSampleDatabaseHasPresetsNtf(
1919       test_address, kFeatureBitWritablePresets,
1920       {{HasPreset(5,
1921                   HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1922                   "YourWritablePreset")}});
1923   TestConnect(test_address);
1924 
1925   EXPECT_CALL(*callbacks,
1926               OnSetPresetNameError(_, _, ErrorCode::INVALID_PRESET_NAME_LENGTH))
1927       .Times(1);
1928   EXPECT_CALL(gatt_queue,
1929               WriteCharacteristic(test_conn_id, HasDbBuilder::kPresetsCtpValHdl,
1930                                   _, GATT_WRITE, _, _))
1931       .Times(0);
1932 
1933   HasClient::Get()->SetPresetName(test_address, 5,
1934                                   "this name is more than 40 characters long");
1935 }
1936 
TEST_F(HasClientTest,test_preset_set_name)1937 TEST_F(HasClientTest, test_preset_set_name) {
1938   const RawAddress test_address = GetTestAddress(1);
1939   uint16_t test_conn_id = GetTestConnId(test_address);
1940 
1941   SetSampleDatabaseHasPresetsNtf(
1942       test_address, kFeatureBitWritablePresets,
1943       {{HasPreset(5,
1944                   HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
1945                   "YourWritablePreset5")}});
1946 
1947   TestConnect(test_address);
1948 
1949   std::vector<uint8_t> value;
1950   EXPECT_CALL(*callbacks, OnSetPresetNameError(_, _, _)).Times(0);
1951   EXPECT_CALL(gatt_queue,
1952               WriteCharacteristic(test_conn_id, HasDbBuilder::kPresetsCtpValHdl,
1953                                   _, GATT_WRITE, _, _));
1954 
1955   std::vector<PresetInfo> updated_preset_details;
1956   EXPECT_CALL(*callbacks,
1957               OnPresetInfo(std::variant<RawAddress, int>(test_address),
1958                            PresetInfoReason::PRESET_INFO_UPDATE, _))
1959       .WillOnce(SaveArg<2>(&updated_preset_details));
1960   HasClient::Get()->SetPresetName(test_address, 5, "new preset name");
1961 
1962   ASSERT_EQ(1u, updated_preset_details.size());
1963   ASSERT_EQ(updated_preset_details[0].preset_name, "new preset name");
1964 }
1965 
TEST_F(HasClientTest,test_preset_group_set_name)1966 TEST_F(HasClientTest, test_preset_group_set_name) {
1967   /* None of these devices support preset syncing */
1968   const RawAddress test_address1 = GetTestAddress(1);
1969   SetSampleDatabaseHasPresetsNtf(
1970       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural |
1971                          bluetooth::has::kFeatureBitWritablePresets);
1972 
1973   const RawAddress test_address2 = GetTestAddress(2);
1974   SetSampleDatabaseHasPresetsNtf(
1975       test_address2, bluetooth::has::kFeatureBitHearingAidTypeBinaural |
1976                          bluetooth::has::kFeatureBitWritablePresets);
1977 
1978   TestConnect(test_address1);
1979   TestConnect(test_address2);
1980 
1981   /* Mock the csis group with two devices */
1982   uint8_t not_synced_group = 13;
1983   ON_CALL(mock_csis_client_module_, GetDeviceList(not_synced_group))
1984       .WillByDefault(
1985           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
1986   ON_CALL(
1987       mock_csis_client_module_,
1988       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
1989       .WillByDefault(Return(not_synced_group));
1990   ON_CALL(
1991       mock_csis_client_module_,
1992       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
1993       .WillByDefault(Return(not_synced_group));
1994 
1995   std::vector<PresetInfo> preset_details;
1996   EXPECT_CALL(*callbacks, OnActivePresetSelected(
1997                               std::variant<RawAddress, int>(test_address1), 55))
1998       .Times(0);
1999   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2000                               std::variant<RawAddress, int>(test_address2), 55))
2001       .Times(0);
2002 
2003   /* This should be a group callback */
2004   EXPECT_CALL(*callbacks,
2005               OnPresetInfo(std::variant<RawAddress, int>(not_synced_group),
2006                            PresetInfoReason::PRESET_INFO_UPDATE, _))
2007       .Times(1)
2008       .WillOnce(SaveArg<2>(&preset_details));
2009 
2010   /* No locally synced opcodes support so expect both devices getting writes */
2011   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address1),
2012                                               HasDbBuilder::kPresetsCtpValHdl,
2013                                               _, GATT_WRITE, _, _))
2014       .Times(1);
2015   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address2),
2016                                               HasDbBuilder::kPresetsCtpValHdl,
2017                                               _, GATT_WRITE, _, _))
2018       .Times(1);
2019 
2020   HasClient::Get()->SetPresetName(not_synced_group, 55, "new preset name");
2021   ASSERT_EQ(preset_details.size(), 1u);
2022   ASSERT_EQ(preset_details[0].preset_name, "new preset name");
2023   ASSERT_EQ(preset_details[0].preset_index, 55);
2024 }
2025 
TEST_F(HasClientTest,test_multiple_presets_get_name)2026 TEST_F(HasClientTest, test_multiple_presets_get_name) {
2027   const RawAddress test_address = GetTestAddress(1);
2028   SetSampleDatabaseHasPresetsNtf(
2029       test_address, kFeatureBitWritablePresets,
2030       {{
2031           HasPreset(
2032               5, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2033               "YourWritablePreset5"),
2034           HasPreset(55, HasPreset::kPropertyAvailable, "YourPreset55"),
2035           HasPreset(99, 0, "YourPreset99"),
2036       }});
2037 
2038   std::vector<PresetInfo> preset_details;
2039 
2040   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _));
2041   EXPECT_CALL(*callbacks,
2042               OnConnectionState(ConnectionState::CONNECTED, test_address));
2043   EXPECT_CALL(*callbacks, OnPresetInfo(_, PresetInfoReason::ALL_PRESET_INFO, _))
2044       .WillOnce(SaveArg<2>(&preset_details));
2045   TestConnect(test_address);
2046 
2047   /* Get each preset info individually */
2048   for (auto const& preset : preset_details) {
2049     std::vector<PresetInfo> new_preset_details;
2050 
2051     EXPECT_CALL(*callbacks,
2052                 OnPresetInfo(std::variant<RawAddress, int>(test_address),
2053                              PresetInfoReason::PRESET_INFO_REQUEST_RESPONSE, _))
2054         .Times(1)
2055         .WillOnce(SaveArg<2>(&new_preset_details));
2056     HasClient::Get()->GetPresetInfo(test_address, preset.preset_index);
2057 
2058     Mock::VerifyAndClearExpectations(&*callbacks);
2059     ASSERT_EQ(1u, new_preset_details.size());
2060     ASSERT_EQ(preset.preset_index, new_preset_details[0].preset_index);
2061     ASSERT_EQ(preset.preset_name, new_preset_details[0].preset_name);
2062     ASSERT_EQ(preset.writable, new_preset_details[0].writable);
2063     ASSERT_EQ(preset.available, new_preset_details[0].available);
2064   }
2065 }
2066 
TEST_F(HasClientTest,test_presets_get_name_invalid_index)2067 TEST_F(HasClientTest, test_presets_get_name_invalid_index) {
2068   const RawAddress test_address = GetTestAddress(1);
2069   SetSampleDatabaseHasPresetsNtf(test_address);
2070   TestConnect(test_address);
2071 
2072   EXPECT_CALL(*callbacks,
2073               OnPresetInfoError(std::variant<RawAddress, int>(test_address),
2074                                 128, ErrorCode::INVALID_PRESET_INDEX));
2075   HasClient::Get()->GetPresetInfo(test_address, 128);
2076 
2077   EXPECT_CALL(*callbacks,
2078               OnPresetInfoError(std::variant<RawAddress, int>(test_address), 0,
2079                                 ErrorCode::INVALID_PRESET_INDEX));
2080   HasClient::Get()->GetPresetInfo(test_address, 0);
2081 }
2082 
TEST_F(HasClientTest,test_presets_changed_generic_update_no_add_or_delete)2083 TEST_F(HasClientTest, test_presets_changed_generic_update_no_add_or_delete) {
2084   const RawAddress test_address = GetTestAddress(1);
2085   uint16_t test_conn_id = GetTestConnId(test_address);
2086 
2087   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2088       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2089       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2090                 "Preset2"),
2091       HasPreset(4, HasPreset::kPropertyAvailable, "Preset4"),
2092       HasPreset(7, HasPreset::kPropertyAvailable, "Preset7"),
2093   }};
2094   SetSampleDatabaseHasPresetsNtf(
2095       test_address,
2096       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2097           bluetooth::has::kFeatureBitDynamicPresets |
2098           bluetooth::has::kFeatureBitWritablePresets,
2099       presets);
2100 
2101   EXPECT_CALL(*callbacks,
2102               OnConnectionState(ConnectionState::CONNECTED, test_address));
2103   TestConnect(test_address);
2104 
2105   std::vector<PresetInfo> preset_details;
2106   EXPECT_CALL(*callbacks,
2107               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2108                            PresetInfoReason::PRESET_INFO_UPDATE, _))
2109       .Times(1)
2110       .WillOnce(SaveArg<2>(&preset_details));
2111 
2112   /* Inject generic update on the first preset */
2113   auto preset_index = 2;
2114   auto new_test_preset = HasPreset(preset_index, 0, "props new name");
2115   ASSERT_NE(*current_peer_presets_.at(test_conn_id).find(preset_index),
2116             new_test_preset);
2117 
2118   InjectPresetChanged(
2119       test_conn_id, test_address, false, new_test_preset, 1 /* prev_index */,
2120       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_GENERIC_UPDATE,
2121       true /* is_last */);
2122 
2123   /* Verify received preset info update on the 2nd preset */
2124   ASSERT_EQ(1u, preset_details.size());
2125   ASSERT_EQ(new_test_preset.GetIndex(), preset_details[0].preset_index);
2126   ASSERT_EQ(new_test_preset.IsAvailable(), preset_details[0].available);
2127   ASSERT_EQ(new_test_preset.IsWritable(), preset_details[0].writable);
2128   ASSERT_EQ(new_test_preset.GetName(), preset_details[0].preset_name);
2129 }
2130 
TEST_F(HasClientTest,test_presets_changed_generic_update_add_and_delete)2131 TEST_F(HasClientTest, test_presets_changed_generic_update_add_and_delete) {
2132   const RawAddress test_address = GetTestAddress(1);
2133   uint16_t test_conn_id = GetTestConnId(test_address);
2134 
2135   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2136       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2137       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2138                 "Preset2"),
2139       HasPreset(4, HasPreset::kPropertyAvailable, "Preset4"),
2140       HasPreset(5, HasPreset::kPropertyAvailable, "Preset5"),
2141       HasPreset(32, HasPreset::kPropertyAvailable, "Preset32"),
2142   }};
2143   SetSampleDatabaseHasPresetsNtf(
2144       test_address,
2145       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2146           bluetooth::has::kFeatureBitWritablePresets,
2147       presets);
2148 
2149   std::vector<PresetInfo> preset_details;
2150   EXPECT_CALL(*callbacks,
2151               OnConnectionState(ConnectionState::CONNECTED, test_address));
2152   EXPECT_CALL(*callbacks,
2153               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2154                            PresetInfoReason::ALL_PRESET_INFO, _))
2155       .Times(1)
2156       .WillOnce(SaveArg<2>(&preset_details));
2157   TestConnect(test_address);
2158 
2159   /* Expect more OnPresetInfo call */
2160   std::vector<PresetInfo> updated_preset_details;
2161   EXPECT_CALL(*callbacks,
2162               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2163                            PresetInfoReason::PRESET_INFO_UPDATE, _))
2164       .Times(1)
2165       .WillOnce(SaveArg<2>(&updated_preset_details));
2166 
2167   /* Expect more OnPresetInfo call */
2168   std::vector<PresetInfo> deleted_preset_details;
2169   EXPECT_CALL(*callbacks,
2170               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2171                            PresetInfoReason::PRESET_DELETED, _))
2172       .Times(1)
2173       .WillOnce(SaveArg<2>(&deleted_preset_details));
2174 
2175   /* Inject generic updates */
2176   /* First event replaces all the existing presets from 1 to 8 with preset 8
2177    */
2178   auto new_test_preset1 =
2179       HasPreset(8, HasPreset::kPropertyAvailable, "props new name9");
2180   InjectPresetChanged(
2181       test_conn_id, test_address, false, new_test_preset1, 1 /* prev_index */,
2182       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_GENERIC_UPDATE,
2183       false /* is_last */);
2184 
2185   /* Second event adds preset 9 to the already existing presets 1 and 8 */
2186   auto new_test_preset2 =
2187       HasPreset(9, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2188                 "props new name11");
2189   InjectPresetChanged(
2190       test_conn_id, test_address, false, new_test_preset2, 8 /* prev_index */,
2191       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_GENERIC_UPDATE,
2192       false /* is_last */);
2193 
2194   /* Third event deletes preset 1 with the generic update */
2195   InjectPresetChanged(
2196       test_conn_id, test_address, false, new_test_preset1, 0 /* prev_index */,
2197       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_GENERIC_UPDATE,
2198       true /* is_last */);
2199 
2200   /* Verify received preset info - expect presets 1, 32 unchanged, 8, 9
2201    * updated, and 1, 2, 4, 5 deleted.
2202    */
2203   ASSERT_EQ(2u, updated_preset_details.size());
2204   ASSERT_EQ(new_test_preset1.GetIndex(),
2205             updated_preset_details[0].preset_index);
2206   ASSERT_EQ(new_test_preset1.IsAvailable(),
2207             updated_preset_details[0].available);
2208   ASSERT_EQ(new_test_preset1.IsWritable(), updated_preset_details[0].writable);
2209   ASSERT_EQ(new_test_preset1.GetName(), updated_preset_details[0].preset_name);
2210   ASSERT_EQ(new_test_preset2.GetIndex(),
2211             updated_preset_details[1].preset_index);
2212   ASSERT_EQ(new_test_preset2.IsAvailable(),
2213             updated_preset_details[1].available);
2214   ASSERT_EQ(new_test_preset2.IsWritable(), updated_preset_details[1].writable);
2215   ASSERT_EQ(new_test_preset2.GetName(), updated_preset_details[1].preset_name);
2216 
2217   ASSERT_EQ(4u, deleted_preset_details.size());
2218   ASSERT_EQ(2, deleted_preset_details[0].preset_index);
2219   ASSERT_EQ(4, deleted_preset_details[1].preset_index);
2220   ASSERT_EQ(5, deleted_preset_details[2].preset_index);
2221   ASSERT_EQ(1, deleted_preset_details[3].preset_index);
2222 }
2223 
TEST_F(HasClientTest,test_presets_changed_deleted)2224 TEST_F(HasClientTest, test_presets_changed_deleted) {
2225   const RawAddress test_address = GetTestAddress(1);
2226   uint16_t test_conn_id = GetTestConnId(test_address);
2227 
2228   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2229       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2230       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2231                 "Preset2"),
2232   }};
2233   SetSampleDatabaseHasPresetsNtf(
2234       test_address,
2235       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2236           bluetooth::has::kFeatureBitWritablePresets |
2237           bluetooth::has::kFeatureBitDynamicPresets,
2238       presets);
2239 
2240   std::vector<PresetInfo> preset_details;
2241   EXPECT_CALL(*callbacks,
2242               OnConnectionState(ConnectionState::CONNECTED, test_address));
2243   EXPECT_CALL(*callbacks,
2244               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2245                            PresetInfoReason::ALL_PRESET_INFO, _))
2246       .Times(1)
2247       .WillOnce(SaveArg<2>(&preset_details));
2248   TestConnect(test_address);
2249 
2250   /* Expect second OnPresetInfo call */
2251   std::vector<PresetInfo> deleted_preset_details;
2252   EXPECT_CALL(*callbacks,
2253               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2254                            PresetInfoReason::PRESET_DELETED, _))
2255       .Times(1)
2256       .WillOnce(SaveArg<2>(&deleted_preset_details));
2257 
2258   /* Inject preset deletion of index 2 */
2259   auto deleted_index = preset_details[1].preset_index;
2260   InjectPresetChanged(
2261       test_conn_id, test_address, false, *presets.find(deleted_index),
2262       0 /* prev_index */,
2263       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_DELETED,
2264       true /* is_last */);
2265 
2266   ASSERT_EQ(2u, preset_details.size());
2267   ASSERT_EQ(1u, deleted_preset_details.size());
2268   ASSERT_EQ(preset_details[1].preset_index,
2269             deleted_preset_details[0].preset_index);
2270   ASSERT_EQ(preset_details[1].writable, deleted_preset_details[0].writable);
2271   ASSERT_EQ(preset_details[1].available, deleted_preset_details[0].available);
2272   ASSERT_EQ(preset_details[1].preset_name,
2273             deleted_preset_details[0].preset_name);
2274 }
2275 
TEST_F(HasClientTest,test_presets_changed_available)2276 TEST_F(HasClientTest, test_presets_changed_available) {
2277   const RawAddress test_address = GetTestAddress(1);
2278   uint16_t test_conn_id = GetTestConnId(test_address);
2279 
2280   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2281       HasPreset(1, 0, "Universal"),
2282       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2283                 "Preset2"),
2284   }};
2285   SetSampleDatabaseHasPresetsNtf(
2286       test_address,
2287       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2288           bluetooth::has::kFeatureBitWritablePresets |
2289           bluetooth::has::kFeatureBitDynamicPresets,
2290       presets);
2291 
2292   std::vector<PresetInfo> preset_details;
2293   EXPECT_CALL(*callbacks,
2294               OnConnectionState(ConnectionState::CONNECTED, test_address));
2295   EXPECT_CALL(*callbacks,
2296               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2297                            PresetInfoReason::ALL_PRESET_INFO, _))
2298       .Times(1)
2299       .WillOnce(SaveArg<2>(&preset_details));
2300   TestConnect(test_address);
2301 
2302   /* Expect second OnPresetInfo call */
2303   std::vector<PresetInfo> changed_preset_details;
2304   EXPECT_CALL(*callbacks,
2305               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2306                            PresetInfoReason::PRESET_AVAILABILITY_CHANGED, _))
2307       .Times(1)
2308       .WillOnce(SaveArg<2>(&changed_preset_details));
2309 
2310   /* Inject preset deletion of index 2 */
2311   auto changed_index = preset_details[0].preset_index;
2312   InjectPresetChanged(
2313       test_conn_id, test_address, false, *presets.find(changed_index),
2314       0 /* prev_index */,
2315       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_AVAILABLE,
2316       true /* is_last */);
2317 
2318   ASSERT_EQ(2u, preset_details.size());
2319   ASSERT_EQ(1u, changed_preset_details.size());
2320   ASSERT_EQ(preset_details[0].preset_index,
2321             changed_preset_details[0].preset_index);
2322   ASSERT_EQ(preset_details[0].writable, changed_preset_details[0].writable);
2323   ASSERT_EQ(preset_details[0].preset_name,
2324             changed_preset_details[0].preset_name);
2325   /* This field should have changed */
2326   ASSERT_NE(preset_details[0].available, changed_preset_details[0].available);
2327   ASSERT_TRUE(changed_preset_details[0].available);
2328 }
2329 
TEST_F(HasClientTest,test_presets_changed_unavailable)2330 TEST_F(HasClientTest, test_presets_changed_unavailable) {
2331   const RawAddress test_address = GetTestAddress(1);
2332   uint16_t test_conn_id = GetTestConnId(test_address);
2333 
2334   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2335       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2336       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2337                 "Preset2"),
2338   }};
2339   SetSampleDatabaseHasPresetsNtf(
2340       test_address,
2341       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2342           bluetooth::has::kFeatureBitWritablePresets |
2343           bluetooth::has::kFeatureBitDynamicPresets,
2344       presets);
2345 
2346   std::vector<PresetInfo> preset_details;
2347   EXPECT_CALL(*callbacks,
2348               OnConnectionState(ConnectionState::CONNECTED, test_address));
2349   EXPECT_CALL(*callbacks,
2350               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2351                            PresetInfoReason::ALL_PRESET_INFO, _))
2352       .Times(1)
2353       .WillOnce(SaveArg<2>(&preset_details));
2354   TestConnect(test_address);
2355 
2356   /* Expect second OnPresetInfo call */
2357   std::vector<PresetInfo> changed_preset_details;
2358   EXPECT_CALL(*callbacks,
2359               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2360                            PresetInfoReason::PRESET_AVAILABILITY_CHANGED, _))
2361       .Times(1)
2362       .WillOnce(SaveArg<2>(&changed_preset_details));
2363 
2364   /* Inject preset deletion of index 2 */
2365   auto changed_index = preset_details[0].preset_index;
2366   InjectPresetChanged(
2367       test_conn_id, test_address, false, *presets.find(changed_index),
2368       0 /* prev_index */,
2369       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_UNAVAILABLE,
2370       true /* is_last */);
2371 
2372   ASSERT_EQ(2u, preset_details.size());
2373   ASSERT_EQ(1u, changed_preset_details.size());
2374   ASSERT_EQ(preset_details[0].preset_index,
2375             changed_preset_details[0].preset_index);
2376   ASSERT_EQ(preset_details[0].writable, changed_preset_details[0].writable);
2377   ASSERT_EQ(preset_details[0].preset_name,
2378             changed_preset_details[0].preset_name);
2379   /* This field should have changed */
2380   ASSERT_NE(preset_details[0].available, changed_preset_details[0].available);
2381   ASSERT_FALSE(changed_preset_details[0].available);
2382 }
2383 
TEST_F(HasClientTest,test_select_preset_valid)2384 TEST_F(HasClientTest, test_select_preset_valid) {
2385   const RawAddress test_address = GetTestAddress(1);
2386   SetSampleDatabaseHasPresetsNtf(test_address);
2387 
2388   uint8_t active_preset_index = 0;
2389   std::vector<PresetInfo> preset_details;
2390 
2391   EXPECT_CALL(*callbacks,
2392               OnConnectionState(ConnectionState::CONNECTED, test_address));
2393   EXPECT_CALL(*callbacks,
2394               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2395                            PresetInfoReason::ALL_PRESET_INFO, _))
2396       .Times(1)
2397       .WillOnce(SaveArg<2>(&preset_details));
2398   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
2399       .WillOnce(SaveArg<1>(&active_preset_index));
2400   TestConnect(test_address);
2401 
2402   ASSERT_TRUE(preset_details.size() > 1);
2403   ASSERT_EQ(preset_details.front().preset_index, active_preset_index);
2404 
2405   uint8_t new_active_preset_index = 0;
2406   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
2407       .WillOnce(SaveArg<1>(&new_active_preset_index));
2408 
2409   HasClient::Get()->SelectActivePreset(test_address,
2410                                        preset_details.back().preset_index);
2411   Mock::VerifyAndClearExpectations(&*callbacks);
2412 
2413   ASSERT_NE(active_preset_index, new_active_preset_index);
2414   ASSERT_EQ(preset_details.back().preset_index, new_active_preset_index);
2415 }
2416 
TEST_F(HasClientTest,test_select_group_preset_invalid_group)2417 TEST_F(HasClientTest, test_select_group_preset_invalid_group) {
2418   const RawAddress test_address1 = GetTestAddress(1);
2419   SetSampleDatabaseHasPresetsNtf(test_address1);
2420 
2421   const RawAddress test_address2 = GetTestAddress(2);
2422   SetSampleDatabaseHasPresetsNtf(test_address2);
2423 
2424   TestConnect(test_address1);
2425   TestConnect(test_address2);
2426 
2427   /* Mock the csis group with no devices */
2428   uint8_t unlucky_group = 13;
2429   ON_CALL(mock_csis_client_module_, GetDeviceList(unlucky_group))
2430       .WillByDefault(Return(std::vector<RawAddress>()));
2431 
2432   EXPECT_CALL(*callbacks, OnActivePresetSelectError(
2433                               std::variant<RawAddress, int>(unlucky_group),
2434                               ErrorCode::OPERATION_NOT_POSSIBLE))
2435       .Times(1);
2436 
2437   HasClient::Get()->SelectActivePreset(unlucky_group, 6);
2438 }
2439 
TEST_F(HasClientTest,test_select_group_preset_valid_no_preset_sync_supported)2440 TEST_F(HasClientTest, test_select_group_preset_valid_no_preset_sync_supported) {
2441   /* None of these devices support preset syncing */
2442   const RawAddress test_address1 = GetTestAddress(1);
2443   SetSampleDatabaseHasPresetsNtf(
2444       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2445 
2446   const RawAddress test_address2 = GetTestAddress(2);
2447   SetSampleDatabaseHasPresetsNtf(
2448       test_address2, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2449 
2450   TestConnect(test_address1);
2451   TestConnect(test_address2);
2452 
2453   /* Mock the csis group with two devices */
2454   uint8_t not_synced_group = 13;
2455   ON_CALL(mock_csis_client_module_, GetDeviceList(not_synced_group))
2456       .WillByDefault(
2457           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2458   ON_CALL(
2459       mock_csis_client_module_,
2460       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2461       .WillByDefault(Return(not_synced_group));
2462   ON_CALL(
2463       mock_csis_client_module_,
2464       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2465       .WillByDefault(Return(not_synced_group));
2466 
2467   uint8_t group_active_preset_index = 0;
2468   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2469                               std::variant<RawAddress, int>(test_address1), 55))
2470       .Times(0);
2471   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2472                               std::variant<RawAddress, int>(test_address2), 55))
2473       .Times(0);
2474   EXPECT_CALL(*callbacks,
2475               OnActivePresetSelected(
2476                   std::variant<RawAddress, int>(not_synced_group), _))
2477       .WillOnce(SaveArg<1>(&group_active_preset_index));
2478 
2479   /* No locally synced opcodes support so expect both devices getting writes */
2480   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address1),
2481                                               HasDbBuilder::kPresetsCtpValHdl,
2482                                               _, GATT_WRITE, _, _))
2483       .Times(1);
2484   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address2),
2485                                               HasDbBuilder::kPresetsCtpValHdl,
2486                                               _, GATT_WRITE, _, _))
2487       .Times(1);
2488 
2489   HasClient::Get()->SelectActivePreset(not_synced_group, 55);
2490   ASSERT_EQ(group_active_preset_index, 55);
2491 }
2492 
TEST_F(HasClientTest,test_select_group_preset_valid_preset_sync_supported)2493 TEST_F(HasClientTest, test_select_group_preset_valid_preset_sync_supported) {
2494   /* Only one of these devices support preset syncing */
2495   const RawAddress test_address1 = GetTestAddress(1);
2496   uint16_t test_conn_id1 = GetTestConnId(test_address1);
2497   SetSampleDatabaseHasPresetsNtf(
2498       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2499 
2500   const RawAddress test_address2 = GetTestAddress(2);
2501   uint16_t test_conn_id2 = GetTestConnId(test_address2);
2502   SetSampleDatabaseHasPresetsNtf(
2503       test_address2,
2504       bluetooth::has::kFeatureBitHearingAidTypeBinaural |
2505           bluetooth::has::kFeatureBitPresetSynchronizationSupported);
2506 
2507   uint8_t active_preset_index1 = 0;
2508   uint8_t active_preset_index2 = 0;
2509 
2510   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2511                               std::variant<RawAddress, int>(test_address1), _))
2512       .WillOnce(SaveArg<1>(&active_preset_index1));
2513   TestConnect(test_address1);
2514 
2515   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2516                               std::variant<RawAddress, int>(test_address2), _))
2517       .WillOnce(SaveArg<1>(&active_preset_index2));
2518   TestConnect(test_address2);
2519 
2520   /* Mock the csis group with two devices */
2521   uint8_t synced_group = 13;
2522   ON_CALL(mock_csis_client_module_, GetDeviceList(synced_group))
2523       .WillByDefault(
2524           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2525   ON_CALL(
2526       mock_csis_client_module_,
2527       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2528       .WillByDefault(Return(synced_group));
2529   ON_CALL(
2530       mock_csis_client_module_,
2531       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2532       .WillByDefault(Return(synced_group));
2533 
2534   EXPECT_CALL(*callbacks, OnActivePresetSelectError(
2535                               _, ErrorCode::GROUP_OPERATION_NOT_SUPPORTED))
2536       .Times(0);
2537 
2538   /* Expect callback from the group but not from the devices */
2539   uint8_t group_active_preset_index = 0;
2540   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2541                               std::variant<RawAddress, int>(test_address1), _))
2542       .Times(0);
2543   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2544                               std::variant<RawAddress, int>(test_address2), _))
2545       .Times(0);
2546   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2547                               std::variant<RawAddress, int>(synced_group), _))
2548       .WillOnce(SaveArg<1>(&group_active_preset_index));
2549 
2550   /* Expect Ctp write on on this device which forwards operation to the other */
2551   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id1,
2552                                               HasDbBuilder::kPresetsCtpValHdl,
2553                                               _, GATT_WRITE, _, _))
2554       .Times(0);
2555   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id2,
2556                                               HasDbBuilder::kPresetsCtpValHdl,
2557                                               _, GATT_WRITE, _, _))
2558       .Times(1);
2559 
2560   HasClient::Get()->SelectActivePreset(synced_group, 55);
2561   ASSERT_EQ(group_active_preset_index, 55);
2562 }
2563 
TEST_F(HasClientTest,test_select_preset_invalid)2564 TEST_F(HasClientTest, test_select_preset_invalid) {
2565   const RawAddress test_address = GetTestAddress(1);
2566   uint16_t test_conn_id = GetTestConnId(test_address);
2567 
2568   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2569       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2570       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2571                 "Preset2"),
2572   }};
2573   SetSampleDatabaseHasPresetsNtf(
2574       test_address,
2575       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2576           bluetooth::has::kFeatureBitWritablePresets |
2577           bluetooth::has::kFeatureBitDynamicPresets,
2578       presets);
2579 
2580   uint8_t active_preset_index = 0;
2581   std::vector<PresetInfo> preset_details;
2582 
2583   EXPECT_CALL(*callbacks,
2584               OnConnectionState(ConnectionState::CONNECTED, test_address));
2585   EXPECT_CALL(*callbacks,
2586               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2587                            PresetInfoReason::ALL_PRESET_INFO, _))
2588       .Times(1)
2589       .WillOnce(SaveArg<2>(&preset_details));
2590   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
2591       .WillOnce(SaveArg<1>(&active_preset_index));
2592   TestConnect(test_address);
2593 
2594   ASSERT_TRUE(preset_details.size() > 1);
2595   ASSERT_EQ(preset_details.front().preset_index, active_preset_index);
2596 
2597   /* Inject preset deletion of index 2 */
2598   auto deleted_index = preset_details[1].preset_index;
2599   InjectPresetChanged(
2600       test_conn_id, test_address, false, *presets.find(deleted_index),
2601       0 /* prev_index */,
2602       ::bluetooth::le_audio::has::PresetCtpChangeId::PRESET_DELETED,
2603       true /* is_last */);
2604 
2605   EXPECT_CALL(*callbacks, OnActivePresetSelectError(
2606                               std::variant<RawAddress, int>(test_address),
2607                               ErrorCode::INVALID_PRESET_INDEX))
2608       .Times(1);
2609 
2610   /* Check if preset was actually deleted - try setting it as an active one */
2611   HasClient::Get()->SelectActivePreset(test_address,
2612                                        preset_details[1].preset_index);
2613 }
2614 
TEST_F(HasClientTest,test_select_preset_next)2615 TEST_F(HasClientTest, test_select_preset_next) {
2616   const RawAddress test_address = GetTestAddress(1);
2617 
2618   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2619       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2620       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2621                 "Preset2"),
2622   }};
2623   SetSampleDatabaseHasPresetsNtf(
2624       test_address,
2625       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2626           bluetooth::has::kFeatureBitWritablePresets |
2627           bluetooth::has::kFeatureBitDynamicPresets,
2628       presets);
2629 
2630   uint8_t active_preset_index = 0;
2631   std::vector<PresetInfo> preset_details;
2632 
2633   EXPECT_CALL(*callbacks,
2634               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2635                            PresetInfoReason::ALL_PRESET_INFO, _))
2636       .Times(1)
2637       .WillOnce(SaveArg<2>(&preset_details));
2638   EXPECT_CALL(*callbacks, OnActivePresetSelected(_, _))
2639       .WillOnce(SaveArg<1>(&active_preset_index));
2640   TestConnect(test_address);
2641 
2642   ASSERT_TRUE(preset_details.size() > 1);
2643   ASSERT_EQ(1, active_preset_index);
2644 
2645   /* Verify active preset change */
2646   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2647                               std::variant<RawAddress, int>(test_address), 2));
2648   HasClient::Get()->NextActivePreset(test_address);
2649 }
2650 
TEST_F(HasClientTest,test_select_group_preset_next_no_preset_sync_supported)2651 TEST_F(HasClientTest, test_select_group_preset_next_no_preset_sync_supported) {
2652   /* None of these devices support preset syncing */
2653   const RawAddress test_address1 = GetTestAddress(1);
2654   SetSampleDatabaseHasPresetsNtf(
2655       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2656 
2657   const RawAddress test_address2 = GetTestAddress(2);
2658   SetSampleDatabaseHasPresetsNtf(
2659       test_address2, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2660 
2661   TestConnect(test_address1);
2662   TestConnect(test_address2);
2663 
2664   /* Mock the csis group with two devices */
2665   uint8_t not_synced_group = 13;
2666   ON_CALL(mock_csis_client_module_, GetDeviceList(not_synced_group))
2667       .WillByDefault(
2668           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2669   ON_CALL(
2670       mock_csis_client_module_,
2671       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2672       .WillByDefault(Return(not_synced_group));
2673   ON_CALL(
2674       mock_csis_client_module_,
2675       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2676       .WillByDefault(Return(not_synced_group));
2677 
2678   uint8_t group_active_preset_index = 0;
2679   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2680                               std::variant<RawAddress, int>(test_address1), 55))
2681       .Times(0);
2682   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2683                               std::variant<RawAddress, int>(test_address2), 55))
2684       .Times(0);
2685   EXPECT_CALL(*callbacks,
2686               OnActivePresetSelected(
2687                   std::variant<RawAddress, int>(not_synced_group), _))
2688       .WillOnce(SaveArg<1>(&group_active_preset_index));
2689 
2690   /* No locally synced opcodes support so expect both devices getting writes */
2691   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address1),
2692                                               HasDbBuilder::kPresetsCtpValHdl,
2693                                               _, GATT_WRITE, _, _))
2694       .Times(1);
2695   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address2),
2696                                               HasDbBuilder::kPresetsCtpValHdl,
2697                                               _, GATT_WRITE, _, _))
2698       .Times(1);
2699 
2700   HasClient::Get()->NextActivePreset(not_synced_group);
2701   ASSERT_EQ(group_active_preset_index, 55);
2702 }
2703 
TEST_F(HasClientTest,test_select_group_preset_next_preset_sync_supported)2704 TEST_F(HasClientTest, test_select_group_preset_next_preset_sync_supported) {
2705   /* Only one of these devices support preset syncing */
2706   const RawAddress test_address1 = GetTestAddress(1);
2707   uint16_t test_conn_id1 = GetTestConnId(test_address1);
2708   SetSampleDatabaseHasPresetsNtf(
2709       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2710 
2711   const RawAddress test_address2 = GetTestAddress(2);
2712   uint16_t test_conn_id2 = GetTestConnId(test_address2);
2713   SetSampleDatabaseHasPresetsNtf(
2714       test_address2,
2715       bluetooth::has::kFeatureBitHearingAidTypeBinaural |
2716           bluetooth::has::kFeatureBitPresetSynchronizationSupported);
2717 
2718   uint8_t active_preset_index1 = 0;
2719   uint8_t active_preset_index2 = 0;
2720 
2721   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2722                               std::variant<RawAddress, int>(test_address1), _))
2723       .WillOnce(SaveArg<1>(&active_preset_index1));
2724   TestConnect(test_address1);
2725 
2726   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2727                               std::variant<RawAddress, int>(test_address2), _))
2728       .WillOnce(SaveArg<1>(&active_preset_index2));
2729   TestConnect(test_address2);
2730 
2731   /* Mock the csis group with two devices */
2732   uint8_t synced_group = 13;
2733   ON_CALL(mock_csis_client_module_, GetDeviceList(synced_group))
2734       .WillByDefault(
2735           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2736   ON_CALL(
2737       mock_csis_client_module_,
2738       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2739       .WillByDefault(Return(synced_group));
2740   ON_CALL(
2741       mock_csis_client_module_,
2742       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2743       .WillByDefault(Return(synced_group));
2744 
2745   EXPECT_CALL(*callbacks, OnActivePresetSelectError(
2746                               _, ErrorCode::GROUP_OPERATION_NOT_SUPPORTED))
2747       .Times(0);
2748 
2749   /* Expect callback from the group but not from the devices */
2750   uint8_t group_active_preset_index = 0;
2751   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2752                               std::variant<RawAddress, int>(test_address1), _))
2753       .Times(0);
2754   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2755                               std::variant<RawAddress, int>(test_address2), _))
2756       .Times(0);
2757   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2758                               std::variant<RawAddress, int>(synced_group), _))
2759       .WillOnce(SaveArg<1>(&group_active_preset_index));
2760 
2761   /* Expect Ctp write on on this device which forwards operation to the other */
2762   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id1,
2763                                               HasDbBuilder::kPresetsCtpValHdl,
2764                                               _, GATT_WRITE, _, _))
2765       .Times(0);
2766   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id2,
2767                                               HasDbBuilder::kPresetsCtpValHdl,
2768                                               _, GATT_WRITE, _, _))
2769       .Times(1);
2770 
2771   HasClient::Get()->NextActivePreset(synced_group);
2772   ASSERT_EQ(group_active_preset_index, 55);
2773 }
2774 
TEST_F(HasClientTest,test_select_preset_prev)2775 TEST_F(HasClientTest, test_select_preset_prev) {
2776   const RawAddress test_address = GetTestAddress(1);
2777 
2778   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
2779       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
2780       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
2781                 "Preset2"),
2782   }};
2783   SetSampleDatabaseHasPresetsNtf(
2784       test_address,
2785       bluetooth::has::kFeatureBitHearingAidTypeBanded |
2786           bluetooth::has::kFeatureBitWritablePresets |
2787           bluetooth::has::kFeatureBitDynamicPresets,
2788       presets);
2789 
2790   uint8_t active_preset_index = 0;
2791   std::vector<PresetInfo> preset_details;
2792 
2793   EXPECT_CALL(*callbacks,
2794               OnPresetInfo(std::variant<RawAddress, int>(test_address),
2795                            PresetInfoReason::ALL_PRESET_INFO, _))
2796       .Times(1)
2797       .WillOnce(SaveArg<2>(&preset_details));
2798   ON_CALL(*callbacks, OnActivePresetSelected(_, _))
2799       .WillByDefault(SaveArg<1>(&active_preset_index));
2800   TestConnect(test_address);
2801 
2802   HasClient::Get()->SelectActivePreset(test_address, 2);
2803   ASSERT_TRUE(preset_details.size() > 1);
2804   ASSERT_EQ(2, active_preset_index);
2805 
2806   /* Verify active preset change */
2807   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2808                               std::variant<RawAddress, int>(test_address), 1));
2809   HasClient::Get()->PreviousActivePreset(test_address);
2810 }
2811 
TEST_F(HasClientTest,test_select_group_preset_prev_no_preset_sync_supported)2812 TEST_F(HasClientTest, test_select_group_preset_prev_no_preset_sync_supported) {
2813   /* None of these devices support preset syncing */
2814   const RawAddress test_address1 = GetTestAddress(1);
2815   SetSampleDatabaseHasPresetsNtf(
2816       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2817 
2818   const RawAddress test_address2 = GetTestAddress(2);
2819   SetSampleDatabaseHasPresetsNtf(
2820       test_address2, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2821 
2822   TestConnect(test_address1);
2823   TestConnect(test_address2);
2824 
2825   /* Mock the csis group with two devices */
2826   uint8_t not_synced_group = 13;
2827   ON_CALL(mock_csis_client_module_, GetDeviceList(not_synced_group))
2828       .WillByDefault(
2829           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2830   ON_CALL(
2831       mock_csis_client_module_,
2832       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2833       .WillByDefault(Return(not_synced_group));
2834   ON_CALL(
2835       mock_csis_client_module_,
2836       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2837       .WillByDefault(Return(not_synced_group));
2838 
2839   uint8_t group_active_preset_index = 0;
2840   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2841                               std::variant<RawAddress, int>(test_address1), 55))
2842       .Times(0);
2843   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2844                               std::variant<RawAddress, int>(test_address2), 55))
2845       .Times(0);
2846   EXPECT_CALL(*callbacks,
2847               OnActivePresetSelected(
2848                   std::variant<RawAddress, int>(not_synced_group), _))
2849       .WillOnce(SaveArg<1>(&group_active_preset_index));
2850 
2851   /* No locally synced opcodes support so expect both devices getting writes */
2852   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address1),
2853                                               HasDbBuilder::kPresetsCtpValHdl,
2854                                               _, GATT_WRITE, _, _))
2855       .Times(1);
2856   EXPECT_CALL(gatt_queue, WriteCharacteristic(GetTestConnId(test_address2),
2857                                               HasDbBuilder::kPresetsCtpValHdl,
2858                                               _, GATT_WRITE, _, _))
2859       .Times(1);
2860 
2861   HasClient::Get()->PreviousActivePreset(not_synced_group);
2862   ASSERT_EQ(group_active_preset_index, 55);
2863 }
2864 
TEST_F(HasClientTest,test_select_group_preset_prev_preset_sync_supported)2865 TEST_F(HasClientTest, test_select_group_preset_prev_preset_sync_supported) {
2866   /* Only one of these devices support preset syncing */
2867   const RawAddress test_address1 = GetTestAddress(1);
2868   uint16_t test_conn_id1 = GetTestConnId(test_address1);
2869   SetSampleDatabaseHasPresetsNtf(
2870       test_address1, bluetooth::has::kFeatureBitHearingAidTypeBinaural);
2871 
2872   const RawAddress test_address2 = GetTestAddress(2);
2873   uint16_t test_conn_id2 = GetTestConnId(test_address2);
2874   SetSampleDatabaseHasPresetsNtf(
2875       test_address2,
2876       bluetooth::has::kFeatureBitHearingAidTypeBinaural |
2877           bluetooth::has::kFeatureBitPresetSynchronizationSupported);
2878 
2879   uint8_t active_preset_index1 = 0;
2880   uint8_t active_preset_index2 = 0;
2881 
2882   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2883                               std::variant<RawAddress, int>(test_address1), _))
2884       .WillOnce(SaveArg<1>(&active_preset_index1));
2885   TestConnect(test_address1);
2886 
2887   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2888                               std::variant<RawAddress, int>(test_address2), _))
2889       .WillOnce(SaveArg<1>(&active_preset_index2));
2890   TestConnect(test_address2);
2891 
2892   /* Mock the csis group with two devices */
2893   uint8_t synced_group = 13;
2894   ON_CALL(mock_csis_client_module_, GetDeviceList(synced_group))
2895       .WillByDefault(
2896           Return(std::vector<RawAddress>({{test_address1, test_address2}})));
2897   ON_CALL(
2898       mock_csis_client_module_,
2899       GetGroupId(test_address1, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2900       .WillByDefault(Return(synced_group));
2901   ON_CALL(
2902       mock_csis_client_module_,
2903       GetGroupId(test_address2, ::bluetooth::le_audio::uuid::kCapServiceUuid))
2904       .WillByDefault(Return(synced_group));
2905 
2906   EXPECT_CALL(*callbacks, OnActivePresetSelectError(
2907                               _, ErrorCode::GROUP_OPERATION_NOT_SUPPORTED))
2908       .Times(0);
2909 
2910   /* Expect callback from the group but not from the devices */
2911   uint8_t group_active_preset_index = 0;
2912   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2913                               std::variant<RawAddress, int>(test_address1), _))
2914       .Times(0);
2915   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2916                               std::variant<RawAddress, int>(test_address2), _))
2917       .Times(0);
2918   EXPECT_CALL(*callbacks, OnActivePresetSelected(
2919                               std::variant<RawAddress, int>(synced_group), _))
2920       .WillOnce(SaveArg<1>(&group_active_preset_index));
2921 
2922   /* Expect Ctp write on on this device which forwards operation to the other */
2923   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id1,
2924                                               HasDbBuilder::kPresetsCtpValHdl,
2925                                               _, GATT_WRITE, _, _))
2926       .Times(0);
2927   EXPECT_CALL(gatt_queue, WriteCharacteristic(test_conn_id2,
2928                                               HasDbBuilder::kPresetsCtpValHdl,
2929                                               _, GATT_WRITE, _, _))
2930       .Times(1);
2931 
2932   HasClient::Get()->PreviousActivePreset(synced_group);
2933   ASSERT_EQ(group_active_preset_index, 55);
2934 }
2935 
TEST_F(HasClientTest,test_select_has_no_presets)2936 TEST_F(HasClientTest, test_select_has_no_presets) {
2937   const RawAddress test_address = GetTestAddress(1);
2938   SetSampleDatabaseHasNoPresetsFlagsOnly(test_address);
2939 
2940   EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _)).Times(1);
2941   EXPECT_CALL(*callbacks,
2942               OnConnectionState(ConnectionState::CONNECTED, test_address))
2943       .Times(1);
2944   TestConnect(test_address);
2945 
2946   /* Test this not so useful service */
2947   EXPECT_CALL(*callbacks,
2948               OnActivePresetSelectError(_, ErrorCode::OPERATION_NOT_SUPPORTED))
2949       .Times(3);
2950 
2951   HasClient::Get()->SelectActivePreset(test_address, 0x01);
2952   HasClient::Get()->NextActivePreset(test_address);
2953   HasClient::Get()->PreviousActivePreset(test_address);
2954 }
2955 
GetSocketBufferSize(int sockfd)2956 static int GetSocketBufferSize(int sockfd) {
2957   int socket_buffer_size;
2958   socklen_t optlen = sizeof(socket_buffer_size);
2959   getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&socket_buffer_size,
2960              &optlen);
2961   return socket_buffer_size;
2962 }
2963 
SimpleJsonValidator(int fd,int * dumpsys_byte_cnt)2964 bool SimpleJsonValidator(int fd, int* dumpsys_byte_cnt) {
2965   std::ostringstream ss;
2966 
2967   char buf{0};
2968   bool within_double_quotes{false};
2969   int left_bracket{0}, right_bracket{0};
2970   int left_sq_bracket{0}, right_sq_bracket{0};
2971   while (read(fd, &buf, 1) != -1) {
2972     switch (buf) {
2973       (*dumpsys_byte_cnt)++;
2974       case '"':
2975         within_double_quotes = !within_double_quotes;
2976         break;
2977       case '{':
2978         if (!within_double_quotes) {
2979           left_bracket++;
2980         }
2981         break;
2982       case '}':
2983         if (!within_double_quotes) {
2984           right_bracket++;
2985         }
2986         break;
2987       case '[':
2988         if (!within_double_quotes) {
2989           left_sq_bracket++;
2990         }
2991         break;
2992       case ']':
2993         if (!within_double_quotes) {
2994           right_sq_bracket++;
2995         }
2996         break;
2997       default:
2998         break;
2999     }
3000     ss << buf;
3001   }
3002   log::error("{}", ss.str());
3003   return (left_bracket == right_bracket) &&
3004          (left_sq_bracket == right_sq_bracket);
3005 }
3006 
TEST_F(HasClientTest,test_dumpsys)3007 TEST_F(HasClientTest, test_dumpsys) {
3008   const RawAddress test_address = GetTestAddress(1);
3009 
3010   std::set<HasPreset, HasPreset::ComparatorDesc> presets = {{
3011       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
3012       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3013                 "Preset2"),
3014   }};
3015   SetSampleDatabaseHasPresetsNtf(
3016       test_address,
3017       bluetooth::has::kFeatureBitHearingAidTypeBanded |
3018           bluetooth::has::kFeatureBitWritablePresets |
3019           bluetooth::has::kFeatureBitDynamicPresets,
3020       presets);
3021 
3022   uint8_t active_preset_index = 0;
3023   std::vector<PresetInfo> preset_details;
3024 
3025   EXPECT_CALL(*callbacks,
3026               OnPresetInfo(std::variant<RawAddress, int>(test_address),
3027                            PresetInfoReason::ALL_PRESET_INFO, _))
3028       .Times(1)
3029       .WillOnce(SaveArg<2>(&preset_details));
3030   ON_CALL(*callbacks, OnActivePresetSelected(_, _))
3031       .WillByDefault(SaveArg<1>(&active_preset_index));
3032   TestConnect(test_address);
3033 
3034   int sv[2];
3035   ASSERT_EQ(0, socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, sv));
3036   int socket_buffer_size = GetSocketBufferSize(sv[0]);
3037 
3038   HasClient::Get()->DebugDump(sv[0]);
3039   int dumpsys_byte_cnt = 0;
3040   ASSERT_TRUE(dumpsys_byte_cnt < socket_buffer_size);
3041   ASSERT_TRUE(SimpleJsonValidator(sv[1], &dumpsys_byte_cnt));
3042 }
3043 
TEST_F(HasClientTest,test_connect_database_out_of_sync)3044 TEST_F(HasClientTest, test_connect_database_out_of_sync) {
3045   osi_property_set_bool("persist.bluetooth.has.always_use_preset_cache", false);
3046 
3047   const RawAddress test_address = GetTestAddress(1);
3048   std::set<HasPreset, HasPreset::ComparatorDesc> has_presets = {{
3049       HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
3050       HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3051                 "Preset2"),
3052   }};
3053   SetSampleDatabaseHasPresetsNtf(
3054       test_address,
3055       bluetooth::has::kFeatureBitHearingAidTypeBanded |
3056           bluetooth::has::kFeatureBitWritablePresets |
3057           bluetooth::has::kFeatureBitDynamicPresets,
3058       has_presets);
3059 
3060   EXPECT_CALL(*callbacks, OnDeviceAvailable(
3061                               test_address,
3062                               bluetooth::has::kFeatureBitHearingAidTypeBanded |
3063                                   bluetooth::has::kFeatureBitWritablePresets |
3064                                   bluetooth::has::kFeatureBitDynamicPresets));
3065   EXPECT_CALL(*callbacks,
3066               OnConnectionState(ConnectionState::CONNECTED, test_address));
3067   TestConnect(test_address);
3068 
3069   ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
3070       .WillByDefault(
3071           Invoke([this](uint16_t conn_id, uint16_t handle,
3072                         std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
3073                         GATT_WRITE_OP_CB cb, void* cb_data) {
3074             auto* svc = gatt::FindService(services_map[conn_id], handle);
3075             if (svc == nullptr) return;
3076 
3077             tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC;
3078             if (cb)
3079               cb(conn_id, status, handle, value.size(), value.data(), cb_data);
3080           }));
3081 
3082   ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return());
3083   EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
3084   HasClient::Get()->GetPresetInfo(test_address, 1);
3085 }
3086 
3087 class HasTypesTest : public ::testing::Test {
3088  protected:
SetUp(void)3089   void SetUp(void) override { reset_mock_function_count_map(); }
3090 
TearDown(void)3091   void TearDown(void) override {}
3092 };  // namespace
3093 
TEST_F(HasTypesTest,test_has_preset_serialize)3094 TEST_F(HasTypesTest, test_has_preset_serialize) {
3095   HasPreset preset(0x01,
3096                    HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3097                    "My Writable Preset01");
3098 
3099   auto sp_sz = preset.SerializedSize();
3100   std::vector<uint8_t> serialized(sp_sz);
3101 
3102   ASSERT_EQ(1 +      // preset index
3103                 1 +  // properties
3104                 1 +  // name length
3105                 preset.GetName().length(),
3106             sp_sz);
3107 
3108   /* Serialize should move the received buffer pointer by the size of data
3109    */
3110   ASSERT_EQ(preset.Serialize(serialized.data(), serialized.size()),
3111             serialized.data() + serialized.size());
3112 
3113   /* Deserialize */
3114   HasPreset clone;
3115   ASSERT_EQ(HasPreset::Deserialize(serialized.data(), serialized.size(), clone),
3116             serialized.data() + serialized.size());
3117 
3118   /* Verify */
3119   ASSERT_EQ(preset.GetIndex(), clone.GetIndex());
3120   ASSERT_EQ(preset.GetProperties(), clone.GetProperties());
3121   ASSERT_EQ(preset.GetName(), clone.GetName());
3122 }
3123 
TEST_F(HasTypesTest,test_has_preset_serialize_output_buffer_to_small)3124 TEST_F(HasTypesTest, test_has_preset_serialize_output_buffer_to_small) {
3125   HasPreset preset(0x01,
3126                    HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3127                    "My Writable Preset01");
3128 
3129   /* On failure, the offset should still point on .data() */
3130   std::vector<uint8_t> serialized(preset.SerializedSize() - 1);
3131   ASSERT_EQ(preset.Serialize(serialized.data(), serialized.size()),
3132             serialized.data());
3133   ASSERT_EQ(preset.Serialize(serialized.data(), 0), serialized.data());
3134   ASSERT_EQ(preset.Serialize(serialized.data(), 1), serialized.data());
3135   ASSERT_EQ(preset.Serialize(serialized.data(), 10), serialized.data());
3136 }
3137 
TEST_F(HasTypesTest,test_has_preset_serialize_name_to_long)3138 TEST_F(HasTypesTest, test_has_preset_serialize_name_to_long) {
3139   HasPreset preset(0x01,
3140                    HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3141                    "This name is more than 40 characters long");
3142 
3143   /* On failure, the offset should still point on .data() */
3144   std::vector<uint8_t> serialized(preset.SerializedSize());
3145   EXPECT_EQ(preset.Serialize(serialized.data(), serialized.size()),
3146             serialized.data());
3147 }
3148 
TEST_F(HasTypesTest,test_has_preset_deserialize_input_buffer_to_small)3149 TEST_F(HasTypesTest, test_has_preset_deserialize_input_buffer_to_small) {
3150   HasPreset preset(0x01,
3151                    HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3152                    "My Writable Preset01");
3153 
3154   std::vector<uint8_t> serialized(preset.SerializedSize());
3155 
3156   /* Serialize should move the received buffer pointer by the size of data
3157    */
3158   ASSERT_EQ(preset.Serialize(serialized.data(), serialized.size()),
3159             serialized.data() + serialized.size());
3160 
3161   /* Deserialize */
3162   HasPreset clone;
3163   ASSERT_EQ(HasPreset::Deserialize(serialized.data(), 0, clone),
3164             serialized.data());
3165   ASSERT_EQ(HasPreset::Deserialize(serialized.data(), 1, clone),
3166             serialized.data());
3167   ASSERT_EQ(HasPreset::Deserialize(serialized.data(), 11, clone),
3168             serialized.data());
3169   ASSERT_EQ(
3170       HasPreset::Deserialize(serialized.data(), serialized.size() - 1, clone),
3171       serialized.data());
3172 }
3173 
TEST_F(HasTypesTest,test_has_presets_serialize)3174 TEST_F(HasTypesTest, test_has_presets_serialize) {
3175   HasPreset preset(0x01,
3176                    HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable,
3177                    "My Writable Preset01");
3178 
3179   HasPreset preset2(0x02, 0, "Nonwritable Unavailable Preset");
3180 
3181   HasDevice has_device(GetTestAddress(1));
3182   has_device.has_presets.insert(preset);
3183   has_device.has_presets.insert(preset2);
3184 
3185   auto out_buf_sz = has_device.SerializedPresetsSize();
3186   ASSERT_EQ(out_buf_sz, preset.SerializedSize() + preset2.SerializedSize() + 2);
3187 
3188   /* Serialize should append to the vector */
3189   std::vector<uint8_t> serialized;
3190   ASSERT_TRUE(has_device.SerializePresets(serialized));
3191   ASSERT_EQ(out_buf_sz, serialized.size());
3192 
3193   /* Deserialize */
3194   HasDevice clone(GetTestAddress(1));
3195   ASSERT_TRUE(HasDevice::DeserializePresets(serialized.data(),
3196                                             serialized.size(), clone));
3197 
3198   /* Verify */
3199   ASSERT_EQ(clone.has_presets.size(), has_device.has_presets.size());
3200   ASSERT_NE(0u, clone.has_presets.count(0x01));
3201   ASSERT_NE(0u, clone.has_presets.count(0x02));
3202 
3203   ASSERT_EQ(clone.has_presets.find(0x01)->GetIndex(),
3204             has_device.has_presets.find(0x01)->GetIndex());
3205   ASSERT_EQ(clone.has_presets.find(0x01)->GetProperties(),
3206             has_device.has_presets.find(0x01)->GetProperties());
3207   ASSERT_EQ(clone.has_presets.find(0x01)->GetName(),
3208             has_device.has_presets.find(0x01)->GetName());
3209 
3210   ASSERT_EQ(clone.has_presets.find(0x02)->GetIndex(),
3211             has_device.has_presets.find(0x02)->GetIndex());
3212   ASSERT_EQ(clone.has_presets.find(0x02)->GetProperties(),
3213             has_device.has_presets.find(0x02)->GetProperties());
3214   ASSERT_EQ(clone.has_presets.find(0x02)->GetName(),
3215             has_device.has_presets.find(0x02)->GetName());
3216 }
3217 
TEST_F(HasTypesTest,test_group_op_coordinator_init)3218 TEST_F(HasTypesTest, test_group_op_coordinator_init) {
3219   HasCtpGroupOpCoordinator::Initialize([](void*) {
3220     /* Do nothing */
3221   });
3222   ASSERT_EQ(0u, HasCtpGroupOpCoordinator::ref_cnt);
3223   auto address1 = GetTestAddress(1);
3224   auto address2 = GetTestAddress(2);
3225 
3226   HasCtpGroupOpCoordinator wrapper(
3227       {address1, address2},
3228       HasCtpOp(0x01, ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS,
3229                6));
3230   ASSERT_EQ(2u, wrapper.ref_cnt);
3231 
3232   HasCtpGroupOpCoordinator::Cleanup();
3233   ASSERT_EQ(0u, wrapper.ref_cnt);
3234 
3235   ASSERT_EQ(1, get_func_call_count("alarm_free"));
3236   ASSERT_EQ(1, get_func_call_count("alarm_new"));
3237 }
3238 
TEST_F(HasTypesTest,test_group_op_coordinator_copy)3239 TEST_F(HasTypesTest, test_group_op_coordinator_copy) {
3240   HasCtpGroupOpCoordinator::Initialize([](void*) {
3241     /* Do nothing */
3242   });
3243   ASSERT_EQ(0u, HasCtpGroupOpCoordinator::ref_cnt);
3244   auto address1 = GetTestAddress(1);
3245   auto address2 = GetTestAddress(2);
3246 
3247   HasCtpGroupOpCoordinator wrapper(
3248       {address1, address2},
3249       HasCtpOp(0x01, ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS,
3250                6));
3251   HasCtpGroupOpCoordinator wrapper2(
3252       {address1},
3253       HasCtpOp(0x01, ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS,
3254                6));
3255   ASSERT_EQ(3u, wrapper.ref_cnt);
3256   HasCtpGroupOpCoordinator wrapper3 = wrapper2;
3257   auto* wrapper4 =
3258       new HasCtpGroupOpCoordinator(HasCtpGroupOpCoordinator(wrapper2));
3259   ASSERT_EQ(5u, wrapper.ref_cnt);
3260 
3261   delete wrapper4;
3262   ASSERT_EQ(4u, wrapper.ref_cnt);
3263 
3264   HasCtpGroupOpCoordinator::Cleanup();
3265   ASSERT_EQ(0u, wrapper.ref_cnt);
3266 
3267   ASSERT_EQ(1, get_func_call_count("alarm_free"));
3268   ASSERT_EQ(1, get_func_call_count("alarm_new"));
3269 }
3270 
TEST_F(HasTypesTest,test_group_op_coordinator_completion)3271 TEST_F(HasTypesTest, test_group_op_coordinator_completion) {
3272   HasCtpGroupOpCoordinator::Initialize([](void*) {
3273     /* Do nothing */
3274     log::info("callback call");
3275   });
3276   ASSERT_EQ(0u, HasCtpGroupOpCoordinator::ref_cnt);
3277   auto address1 = GetTestAddress(1);
3278   auto address2 = GetTestAddress(2);
3279   auto address3 = GetTestAddress(3);
3280 
3281   HasCtpGroupOpCoordinator wrapper(
3282       {address1, address3},
3283       HasCtpOp(0x01, ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS,
3284                6));
3285   HasCtpGroupOpCoordinator wrapper2(
3286       {address2},
3287       HasCtpOp(0x01, ::bluetooth::le_audio::has::PresetCtpOpcode::READ_PRESETS,
3288                6));
3289   ASSERT_EQ(3u, wrapper.ref_cnt);
3290 
3291   ASSERT_FALSE(wrapper.IsFullyCompleted());
3292 
3293   wrapper.SetCompleted(address1);
3294   ASSERT_EQ(2u, wrapper.ref_cnt);
3295 
3296   wrapper.SetCompleted(address3);
3297   ASSERT_EQ(1u, wrapper.ref_cnt);
3298   ASSERT_FALSE(wrapper.IsFullyCompleted());
3299   ASSERT_EQ(0, get_func_call_count("alarm_free"));
3300 
3301   /* Non existing address completion */
3302   wrapper.SetCompleted(address2);
3303   ASSERT_EQ(0, get_func_call_count("alarm_free"));
3304   ASSERT_EQ(1u, wrapper.ref_cnt);
3305 
3306   /* Last device address completion */
3307   wrapper2.SetCompleted(address2);
3308   ASSERT_TRUE(wrapper.IsFullyCompleted());
3309   ASSERT_EQ(0u, wrapper.ref_cnt);
3310   const int alarm_free_count = get_func_call_count("alarm_free");
3311   ASSERT_EQ(1, alarm_free_count);
3312 
3313   HasCtpGroupOpCoordinator::Cleanup();
3314 
3315   ASSERT_EQ(alarm_free_count, get_func_call_count("alarm_free"));
3316   ASSERT_EQ(1, get_func_call_count("alarm_new"));
3317 }
3318 
3319 }  // namespace
3320 }  // namespace internal
3321 }  // namespace has
3322 }  // namespace bluetooth
3323