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