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