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