1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/gap/android_vendor_capabilities.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
18 #include "pw_unit_test/framework.h"
19
20 namespace bt::gap {
21 namespace {
22
23 namespace android_emb = pw::bluetooth::vendor::android_hci;
24 namespace pwemb = pw::bluetooth::emboss;
25
26 using android_emb::Capability;
27
TEST(AndroidVendorCapabilitiesTest,NonSuccess)28 TEST(AndroidVendorCapabilitiesTest, NonSuccess) {
29 auto params = hci::EventPacket::New<
30 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
31 hci_spec::kCommandCompleteEventCode,
32 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
33 version_0_55_size());
34
35 auto view = params.unchecked_view_t();
36 view.status().Write(pw::bluetooth::emboss::StatusCode::UNKNOWN_COMMAND);
37
38 view.max_advt_instances().Write(1);
39 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
40 view.total_scan_results_storage().Write(2);
41 view.max_irk_list_sz().Write(3);
42 view.filtering_support().Write(Capability::CAPABLE);
43 view.max_filter().Write(4);
44 view.activity_energy_info_support().Write(Capability::CAPABLE);
45
46 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
47 EXPECT_EQ(0u, capabilities.max_simultaneous_advertisements());
48 EXPECT_EQ(false, capabilities.supports_offloaded_rpa());
49 EXPECT_EQ(0u, capabilities.scan_results_storage_bytes());
50 EXPECT_EQ(0u, capabilities.irk_list_size());
51 EXPECT_EQ(false, capabilities.supports_filtering());
52 EXPECT_EQ(0u, capabilities.max_filters());
53 EXPECT_EQ(false, capabilities.supports_activity_energy_info());
54 EXPECT_EQ(0u, capabilities.version_major());
55 EXPECT_EQ(0u, capabilities.version_minor());
56 EXPECT_EQ(0u, capabilities.max_advertisers_tracked());
57 EXPECT_EQ(false, capabilities.supports_extended_scan());
58 EXPECT_EQ(false, capabilities.supports_debug_logging());
59 EXPECT_EQ(false, capabilities.supports_offloading_le_address_generation());
60 EXPECT_EQ(0u, capabilities.a2dp_source_offload_capability_mask());
61 EXPECT_EQ(false, capabilities.supports_bluetooth_quality_report());
62 EXPECT_EQ(0u, capabilities.supports_dynamic_audio_buffer());
63 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
64 }
65
TEST(AndroidVendorCapabilitiesTest,Version055)66 TEST(AndroidVendorCapabilitiesTest, Version055) {
67 auto params = hci::EventPacket::New<
68 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
69 hci_spec::kCommandCompleteEventCode,
70 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
71 version_0_55_size());
72
73 auto view = params.unchecked_view_t();
74 view.status().Write(pwemb::StatusCode::SUCCESS);
75
76 view.max_advt_instances().Write(1);
77 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
78 view.total_scan_results_storage().Write(2);
79 view.max_irk_list_sz().Write(3);
80 view.filtering_support().Write(Capability::CAPABLE);
81 view.max_filter().Write(4);
82 view.activity_energy_info_support().Write(Capability::CAPABLE);
83
84 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
85 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
86 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
87 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
88 EXPECT_EQ(3u, capabilities.irk_list_size());
89 EXPECT_EQ(true, capabilities.supports_filtering());
90 EXPECT_EQ(4u, capabilities.max_filters());
91 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
92 EXPECT_EQ(0u, capabilities.version_major());
93 EXPECT_EQ(55u, capabilities.version_minor());
94 EXPECT_EQ(0u, capabilities.max_advertisers_tracked());
95 EXPECT_EQ(false, capabilities.supports_extended_scan());
96 EXPECT_EQ(false, capabilities.supports_debug_logging());
97 EXPECT_EQ(false, capabilities.supports_offloading_le_address_generation());
98 EXPECT_EQ(0u, capabilities.a2dp_source_offload_capability_mask());
99 EXPECT_EQ(false, capabilities.supports_bluetooth_quality_report());
100 EXPECT_EQ(0u, capabilities.supports_dynamic_audio_buffer());
101 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
102 }
103
TEST(AndroidVendorCapabilitiesTest,Version095)104 TEST(AndroidVendorCapabilitiesTest, Version095) {
105 auto params = hci::EventPacket::New<
106 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
107 hci_spec::kCommandCompleteEventCode,
108 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
109 version_0_95_size());
110
111 auto view = params.unchecked_view_t();
112 view.status().Write(pwemb::StatusCode::SUCCESS);
113
114 view.max_advt_instances().Write(1);
115 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
116 view.total_scan_results_storage().Write(2);
117 view.max_irk_list_sz().Write(3);
118 view.filtering_support().Write(Capability::CAPABLE);
119 view.max_filter().Write(4);
120 view.activity_energy_info_support().Write(Capability::CAPABLE);
121 view.version_supported().major_number().Write(0);
122 view.version_supported().minor_number().Write(95);
123
124 ASSERT_TRUE(view.has_total_num_of_advt_tracked().ValueOr(false));
125 view.total_num_of_advt_tracked().UncheckedWrite(5u);
126
127 ASSERT_TRUE(view.has_extended_scan_support().ValueOr(false));
128 view.extended_scan_support().UncheckedWrite(Capability::CAPABLE);
129
130 ASSERT_TRUE(view.has_debug_logging_supported().ValueOr(false));
131 view.debug_logging_supported().UncheckedWrite(Capability::CAPABLE);
132
133 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
134 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
135 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
136 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
137 EXPECT_EQ(3u, capabilities.irk_list_size());
138 EXPECT_EQ(true, capabilities.supports_filtering());
139 EXPECT_EQ(4u, capabilities.max_filters());
140 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
141 EXPECT_EQ(0u, capabilities.version_major());
142 EXPECT_EQ(95u, capabilities.version_minor());
143 EXPECT_EQ(5u, capabilities.max_advertisers_tracked());
144 EXPECT_EQ(true, capabilities.supports_extended_scan());
145 EXPECT_EQ(true, capabilities.supports_debug_logging());
146 EXPECT_EQ(false, capabilities.supports_offloading_le_address_generation());
147 EXPECT_EQ(0u, capabilities.a2dp_source_offload_capability_mask());
148 EXPECT_EQ(false, capabilities.supports_bluetooth_quality_report());
149 EXPECT_EQ(0u, capabilities.supports_dynamic_audio_buffer());
150 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
151 }
152
TEST(AndroidVendorCapabilitiesTest,Version096)153 TEST(AndroidVendorCapabilitiesTest, Version096) {
154 auto params = hci::EventPacket::New<
155 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
156 hci_spec::kCommandCompleteEventCode,
157 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
158 version_0_96_size());
159
160 auto view = params.unchecked_view_t();
161 view.status().Write(pwemb::StatusCode::SUCCESS);
162
163 view.max_advt_instances().Write(1);
164 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
165 view.total_scan_results_storage().Write(2);
166 view.max_irk_list_sz().Write(3);
167 view.filtering_support().Write(Capability::CAPABLE);
168 view.max_filter().Write(4);
169 view.activity_energy_info_support().Write(Capability::CAPABLE);
170 view.version_supported().major_number().Write(0);
171 view.version_supported().minor_number().Write(96);
172
173 ASSERT_TRUE(view.has_total_num_of_advt_tracked().ValueOr(false));
174 view.total_num_of_advt_tracked().UncheckedWrite(5u);
175
176 ASSERT_TRUE(view.has_extended_scan_support().ValueOr(false));
177 view.extended_scan_support().UncheckedWrite(Capability::CAPABLE);
178
179 ASSERT_TRUE(view.has_debug_logging_supported().ValueOr(false));
180 view.debug_logging_supported().UncheckedWrite(Capability::CAPABLE);
181
182 ASSERT_TRUE(
183 view.has_le_address_generation_offloading_support().ValueOr(false));
184 view.le_address_generation_offloading_support().Write(Capability::CAPABLE);
185
186 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
187 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
188 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
189 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
190 EXPECT_EQ(3u, capabilities.irk_list_size());
191 EXPECT_EQ(true, capabilities.supports_filtering());
192 EXPECT_EQ(4u, capabilities.max_filters());
193 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
194 EXPECT_EQ(0u, capabilities.version_major());
195 EXPECT_EQ(96u, capabilities.version_minor());
196 EXPECT_EQ(5u, capabilities.max_advertisers_tracked());
197 EXPECT_EQ(true, capabilities.supports_extended_scan());
198 EXPECT_EQ(true, capabilities.supports_debug_logging());
199 EXPECT_EQ(true, capabilities.supports_offloading_le_address_generation());
200 EXPECT_EQ(0u, capabilities.a2dp_source_offload_capability_mask());
201 EXPECT_EQ(false, capabilities.supports_bluetooth_quality_report());
202 EXPECT_EQ(0u, capabilities.supports_dynamic_audio_buffer());
203 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
204 }
205
TEST(AndroidVendorCapabilitiesTest,Version098)206 TEST(AndroidVendorCapabilitiesTest, Version098) {
207 auto params = hci::EventPacket::New<
208 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
209 hci_spec::kCommandCompleteEventCode,
210 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
211 version_0_98_size());
212
213 auto view = params.unchecked_view_t();
214 view.status().Write(pwemb::StatusCode::SUCCESS);
215
216 view.max_advt_instances().Write(1);
217 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
218 view.total_scan_results_storage().Write(2);
219 view.max_irk_list_sz().Write(3);
220 view.filtering_support().Write(Capability::CAPABLE);
221 view.max_filter().Write(4);
222 view.activity_energy_info_support().Write(Capability::CAPABLE);
223 view.version_supported().major_number().Write(0);
224 view.version_supported().minor_number().Write(98);
225
226 ASSERT_TRUE(view.has_total_num_of_advt_tracked().ValueOr(false));
227 view.total_num_of_advt_tracked().UncheckedWrite(5u);
228
229 ASSERT_TRUE(view.has_extended_scan_support().ValueOr(false));
230 view.extended_scan_support().UncheckedWrite(Capability::CAPABLE);
231
232 ASSERT_TRUE(view.has_debug_logging_supported().ValueOr(false));
233 view.debug_logging_supported().UncheckedWrite(Capability::CAPABLE);
234
235 ASSERT_TRUE(
236 view.has_le_address_generation_offloading_support().ValueOr(false));
237 view.le_address_generation_offloading_support().Write(Capability::CAPABLE);
238
239 ASSERT_TRUE(view.has_a2dp_source_offload_capability_mask().ValueOr(false));
240 view.a2dp_source_offload_capability_mask().BackingStorage().WriteUInt(6);
241
242 ASSERT_TRUE(view.has_bluetooth_quality_report_support().ValueOr(false));
243 view.bluetooth_quality_report_support().Write(Capability::CAPABLE);
244
245 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
246 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
247 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
248 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
249 EXPECT_EQ(3u, capabilities.irk_list_size());
250 EXPECT_EQ(true, capabilities.supports_filtering());
251 EXPECT_EQ(4u, capabilities.max_filters());
252 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
253 EXPECT_EQ(0u, capabilities.version_major());
254 EXPECT_EQ(98u, capabilities.version_minor());
255 EXPECT_EQ(5u, capabilities.max_advertisers_tracked());
256 EXPECT_EQ(true, capabilities.supports_extended_scan());
257 EXPECT_EQ(true, capabilities.supports_debug_logging());
258 EXPECT_EQ(true, capabilities.supports_offloading_le_address_generation());
259 EXPECT_EQ(6u, capabilities.a2dp_source_offload_capability_mask());
260 EXPECT_EQ(true, capabilities.supports_bluetooth_quality_report());
261 EXPECT_EQ(0u, capabilities.supports_dynamic_audio_buffer());
262 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
263 }
264
TEST(AndroidVendorCapabilitiesTest,Version103)265 TEST(AndroidVendorCapabilitiesTest, Version103) {
266 auto params = hci::EventPacket::New<
267 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
268 hci_spec::kCommandCompleteEventCode,
269 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
270 version_1_03_size());
271
272 auto view = params.unchecked_view_t();
273 view.status().Write(pwemb::StatusCode::SUCCESS);
274
275 view.max_advt_instances().Write(1);
276 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
277 view.total_scan_results_storage().Write(2);
278 view.max_irk_list_sz().Write(3);
279 view.filtering_support().Write(Capability::CAPABLE);
280 view.max_filter().Write(4);
281 view.activity_energy_info_support().Write(Capability::CAPABLE);
282 view.version_supported().major_number().Write(1);
283 view.version_supported().minor_number().Write(03);
284
285 ASSERT_TRUE(view.has_total_num_of_advt_tracked().ValueOr(false));
286 view.total_num_of_advt_tracked().UncheckedWrite(5u);
287
288 ASSERT_TRUE(view.has_extended_scan_support().ValueOr(false));
289 view.extended_scan_support().UncheckedWrite(Capability::CAPABLE);
290
291 ASSERT_TRUE(view.has_debug_logging_supported().ValueOr(false));
292 view.debug_logging_supported().UncheckedWrite(Capability::CAPABLE);
293
294 ASSERT_TRUE(
295 view.has_le_address_generation_offloading_support().ValueOr(false));
296 view.le_address_generation_offloading_support().Write(Capability::CAPABLE);
297
298 ASSERT_TRUE(view.has_a2dp_source_offload_capability_mask().ValueOr(false));
299 view.a2dp_source_offload_capability_mask().BackingStorage().WriteUInt(6);
300
301 ASSERT_TRUE(view.has_bluetooth_quality_report_support().ValueOr(false));
302 view.bluetooth_quality_report_support().Write(Capability::CAPABLE);
303
304 ASSERT_TRUE(view.has_dynamic_audio_buffer_support().ValueOr(false));
305 view.dynamic_audio_buffer_support().sbc().Write(true);
306 view.dynamic_audio_buffer_support().aac().Write(true);
307 view.dynamic_audio_buffer_support().aptx().Write(true);
308
309 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
310 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
311 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
312 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
313 EXPECT_EQ(3u, capabilities.irk_list_size());
314 EXPECT_EQ(true, capabilities.supports_filtering());
315 EXPECT_EQ(4u, capabilities.max_filters());
316 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
317 EXPECT_EQ(1u, capabilities.version_major());
318 EXPECT_EQ(03u, capabilities.version_minor());
319 EXPECT_EQ(5u, capabilities.max_advertisers_tracked());
320 EXPECT_EQ(true, capabilities.supports_extended_scan());
321 EXPECT_EQ(true, capabilities.supports_debug_logging());
322 EXPECT_EQ(true, capabilities.supports_offloading_le_address_generation());
323 EXPECT_EQ(6u, capabilities.a2dp_source_offload_capability_mask());
324 EXPECT_EQ(true, capabilities.supports_bluetooth_quality_report());
325 EXPECT_EQ(7u, capabilities.supports_dynamic_audio_buffer());
326 EXPECT_EQ(false, capabilities.supports_a2dp_offload_v2());
327 }
328
TEST(AndroidVendorCapabilitiesTest,Version104)329 TEST(AndroidVendorCapabilitiesTest, Version104) {
330 auto params = hci::EventPacket::New<
331 android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
332 hci_spec::kCommandCompleteEventCode,
333 android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
334 version_1_04_size());
335
336 auto view = params.unchecked_view_t();
337 view.status().Write(pwemb::StatusCode::SUCCESS);
338
339 view.max_advt_instances().Write(1);
340 view.offloaded_resolution_of_private_address().Write(Capability::CAPABLE);
341 view.total_scan_results_storage().Write(2);
342 view.max_irk_list_sz().Write(3);
343 view.filtering_support().Write(Capability::CAPABLE);
344 view.max_filter().Write(4);
345 view.activity_energy_info_support().Write(Capability::CAPABLE);
346 view.version_supported().major_number().Write(1);
347 view.version_supported().minor_number().Write(04);
348
349 ASSERT_TRUE(view.has_total_num_of_advt_tracked().ValueOr(false));
350 view.total_num_of_advt_tracked().UncheckedWrite(5u);
351
352 ASSERT_TRUE(view.has_extended_scan_support().ValueOr(false));
353 view.extended_scan_support().UncheckedWrite(Capability::CAPABLE);
354
355 ASSERT_TRUE(view.has_debug_logging_supported().ValueOr(false));
356 view.debug_logging_supported().UncheckedWrite(Capability::CAPABLE);
357
358 ASSERT_TRUE(
359 view.has_le_address_generation_offloading_support().ValueOr(false));
360 view.le_address_generation_offloading_support().Write(Capability::CAPABLE);
361
362 ASSERT_TRUE(view.has_a2dp_source_offload_capability_mask().ValueOr(false));
363 view.a2dp_source_offload_capability_mask().BackingStorage().WriteUInt(6);
364
365 ASSERT_TRUE(view.has_bluetooth_quality_report_support().ValueOr(false));
366 view.bluetooth_quality_report_support().Write(Capability::CAPABLE);
367
368 ASSERT_TRUE(view.has_dynamic_audio_buffer_support().ValueOr(false));
369 view.dynamic_audio_buffer_support().sbc().Write(true);
370 view.dynamic_audio_buffer_support().aac().Write(true);
371 view.dynamic_audio_buffer_support().aptx().Write(true);
372
373 ASSERT_TRUE(view.has_a2dp_offload_v2_support().ValueOr(false));
374 view.a2dp_offload_v2_support().Write(Capability::CAPABLE);
375
376 AndroidVendorCapabilities capabilities = AndroidVendorCapabilities::New(view);
377 EXPECT_EQ(1u, capabilities.max_simultaneous_advertisements());
378 EXPECT_EQ(true, capabilities.supports_offloaded_rpa());
379 EXPECT_EQ(2u, capabilities.scan_results_storage_bytes());
380 EXPECT_EQ(3u, capabilities.irk_list_size());
381 EXPECT_EQ(true, capabilities.supports_filtering());
382 EXPECT_EQ(4u, capabilities.max_filters());
383 EXPECT_EQ(true, capabilities.supports_activity_energy_info());
384 EXPECT_EQ(1u, capabilities.version_major());
385 EXPECT_EQ(04u, capabilities.version_minor());
386 EXPECT_EQ(5u, capabilities.max_advertisers_tracked());
387 EXPECT_EQ(true, capabilities.supports_extended_scan());
388 EXPECT_EQ(true, capabilities.supports_debug_logging());
389 EXPECT_EQ(true, capabilities.supports_offloading_le_address_generation());
390 EXPECT_EQ(6u, capabilities.a2dp_source_offload_capability_mask());
391 EXPECT_EQ(true, capabilities.supports_bluetooth_quality_report());
392 EXPECT_EQ(7u, capabilities.supports_dynamic_audio_buffer());
393 EXPECT_EQ(true, capabilities.supports_a2dp_offload_v2());
394 }
395
396 } // namespace
397 } // namespace bt::gap
398