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